Fork for workshops

Files at this revision

API Documentation at this revision

Comitter:
JimCarver
Date:
Fri Oct 12 21:22:49 2018 +0000
Commit message:
Initial commit

Changed in this revision

LICENSE Show annotated file Show diff for this revision Revisions of this file
LICENSE.txt Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
img1.png Show annotated file Show diff for this revision Revisions of this file
img2.png Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed_app.json Show annotated file Show diff for this revision Revisions of this file
mbed_cloud_client_user_config.h Show annotated file Show diff for this revision Revisions of this file
mbed_cloud_dev_credentials.c Show annotated file Show diff for this revision Revisions of this file
mbed_settings.py Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice.lib Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/config Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/description Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/index Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/0d/c07f2fe61fed01cd18db482ffff23740de7cb6 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/1f/81351ca17ab112f74d118315f583ff89ac2c32 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/24/e7f0cb7a7cd71dcb14f2fbcfb39076cfff5424 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/26/1eeb9e9f8b2b4b0d119366dda99c6fd7d35c64 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/2b/8efb439a67aaa6915f99befd40d4e918a82c10 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/3c/a4346dcf1c72e57e1e96c7949da51e98b61ce7 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/5a/015333ddcbcdbf68396216dc854a0f279fc050 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/80/0463e448cad5e8a7c356104d9b708ba763bae8 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/80/7cec9a3570e50ef724ef7bcbea256df2d1a0a1 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/8b/da207f635fa99cad8a683e43e5297d9a294bdb Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/a6/47214121d6495e870ea45951499bcac26b3c04 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/aa/110b91d4c5c37acfbeca6150d44c4605d34c75 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/d5/338770d8873cd612570d9ad98afdc7e1a44cac Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/e7/d3e2dde204ccfc574d163f13c396dddf5f4bf1 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/objects/ff/29575af7e0d0074cbbf99ab9ed3354e9a81868 Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/.meta Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/LICENSE Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/QSPIFBlockDevice.cpp Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/QSPIFBlockDevice.h Show annotated file Show diff for this revision Revisions of this file
qspi-blockdevice/README.md Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client.lib Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/config Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/description Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/index Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/objects/pack/pack-5f23bb76255af64b64a8bf318da40d818b23acdc.idx Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/objects/pack/pack-5f23bb76255af64b64a8bf318da40d818b23acdc.pack Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.meta Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/.msub Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/LICENSE.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/README.md Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client.lib Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/config Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/description Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/index Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/objects/pack/pack-22d710d32ce3109292bb30df9fe28d05ce0430fd.idx Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/objects/pack/pack-22d710d32ce3109292bb30df9fe28d05ce0430fd.pack Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.gitattributes Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/.meta Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/CHANGELOG.md Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/CMakeLists.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/DOXYGEN_FRONTPAGE.md Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/README.md Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/contributions.md Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/doxygen/mbedcloudclient_doxy Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/CMakeLists.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/DOXYGEN_FRONTPAGE.md Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/common_includes.cmake Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/crypto-service/cs_der_certs.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/crypto-service/cs_der_keys_and_csrs.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/crypto-service/cs_hash.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/source/cs_der_certs.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/source/cs_der_keys_and_csrs.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/source/cs_hash.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/source/cs_utils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/source/include/cs_utils.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/factory-configurator-client/factory_configurator_client.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/factory-configurator-client/fcc_defs.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/factory-configurator-client/fcc_status.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/factory_configurator_client.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/fcc_dev_flow.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/fcc_sotp.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/fcc_utils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/fcc_verification.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/include/fcc_bundle_fields.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/include/fcc_sotp.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/include/fcc_utils.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/include/fcc_verification.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/fcc-bundle-handler/fcc_bundle_handler.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_certificate_chain_utils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_certificate_utils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_common_utils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_config_params_utils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_csr_utils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_handler.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_key_utils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/include/fcc_bundle_utils.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-output-info-handler/fcc-output-info-handler/fcc_output_info_handler.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-output-info-handler/fcc-output-info-handler/fcc_output_info_handler_defines.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-output-info-handler/source/fcc_output_info_handler.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/ftcd-comm-base/ftcd-comm-base/ftcd_comm_base.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/ftcd-comm-base/source/ftcd_comm_base.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/ftcd-comm-serial/ftcd-comm-serial/ftcd_comm_serial.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/ftcd-comm-serial/source/ftcd_comm_serial.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/ftcd-comm-socket/ftcd-comm-socket/ftcd_comm_socket.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/ftcd-comm-socket/source/ftcd_comm_socket.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/key-config-manager/key-config-manager/kcm_defs.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/key-config-manager/key-config-manager/kcm_status.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/key-config-manager/key-config-manager/key_config_manager.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/key-config-manager/source/include/kcm_internal.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/key-config-manager/source/key_config_manager.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/logger/logger/pv_log.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/CMakeLists.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/Tools/FRDM-K64FfreeRTOS_Create2Partitions Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/esfs.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/esfs_file_name.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/esfs_performance.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/include/esfs.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/include/esfs_file_name.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/include/esfs_performance.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/include/sotp.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp_int.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp_log.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp_log.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp_no_sotp.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp_shared_lock.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp_shared_lock.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-trace-helper/mbed-trace-helper/mbed-trace-helper.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-trace-helper/source/mbed-trace-helper.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/CMakeLists.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/ORIGIN.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/secsrv-cbor/cbor.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/secsrv-cbor/cn-cbor.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/source/cn-cbor.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/source/cn-context.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/source/cn-create.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/source/cn-encoder.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/source/cn-error.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/source/cn-get.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/storage/source/storage.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/storage/storage/storage.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/source/common_utils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/source/fcc_stats.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/source/fcc_time_profiling.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/source/general_utils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/source/pv_error_handling.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/common_utils.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/fcc_malloc.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/fcc_stats.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/fcc_time_profiling.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/general_utils.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/pv_endian.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/pv_error_handling.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/pv_macros.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/CMakeLists.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_ARIA_mbedOS.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_FreeRTOS.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_Linux.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_mbedOS.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_mbedOS_SW_TRNG.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/FreeRTOS/FreeRTOS_HW_RoT_HW_RTC_NOFLASH_2Partitions.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/FreeRTOS/FreeRTOS_SW_RoT_SW_RTC_2FLASH.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/FreeRTOS/FreeRTOS_crypto_only.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/FreeRTOS/FreeRTOS_default.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/Linux/Linux_HW_RoT_HW_RTC_NOFLASH_2Partitions.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/Linux/Linux_PSK.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/Linux/Linux_SW_RoT_SW_RTC_2FLASH.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/Linux/Linux_crypto_only.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/Linux/Linux_default.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/Linux/TARGET_x86_x64/x86_x64_default.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/TARGET_MCU_K64F/K64F_default.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/TARGET_NUCLEO_F429ZI/NUCLEO_default.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/TARGET_UBLOX_C030_U201/C030_default.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/TARGET_UBLOX_EVK_ODIN_W2/ODIN_default.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_FATFS.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_HW_RoT_HW_RTC_NOFLASH_2Partitions.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_IPV6_ONLY.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_PSK.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_SW_RoT_SW_RTC_2FLASH.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_crypto_only.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_default.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_memoryStatistics.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/sotp_fs.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_ext_configs.cmake Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_ext_configs_PSK.cmake Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/DOXYGEN_FRONTPAGE.md Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/Include/PlatIncludes.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/Include/pal_BSP.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/MK64F_FreeRTOS/BoardInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/MK64F_FreeRTOS/FileSystemInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/MK64F_FreeRTOS/NetworkInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/MK64F_FreeRTOS/pal_startup.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/OpenWRT_Generic_Linux/BoardInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/OpenWRT_Generic_Linux/FileSystemInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/OpenWRT_Generic_Linux/NetworkInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/OpenWRT_Generic_Linux/pal_startup.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/Yocto_Generic_Linux/BoardInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/Yocto_Generic_Linux/FileSystemInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/Yocto_Generic_Linux/NetworkInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/Yocto_Generic_Linux/pal_startup.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/mbedOS/FileSystemInit.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/mbedOS/NetworkInit.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/mbedOS/pal_startup.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/pal_insecure_ROT.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/x86_x64_Linux/BoardInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/x86_x64_Linux/FileSystemInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/x86_x64_Linux/NetworkInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/x86_x64_Linux/pal_startup.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/CMakeLists.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Crypto/pal_Crypto.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Networking/pal_network.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/RTOS/pal_rtos.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Storage/FileSystem/pal_fileSystem.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Storage/Flash/pal_internalFlash.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/TLS/pal_TLS.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Update/pal_update.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_Crypto.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_TLS.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_configuration.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_errors.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_fileSystem.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_internalFlash.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_macros.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_network.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_rtos.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_types.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_update.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/pal_init.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_Crypto.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_TLS.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_fileSystem.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_internalFlash.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_network.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_rtos.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_update.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/mbedTLS/Crypto/pal_plat_Crypto.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/mbedTLS/TLS/pal_plat_TLS.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/Board_Specific/TARGET_K64F/pal_plat_K64F.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/Networking/LWIP/pal_plat_network.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/RTOS/pal_plat_rtos.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/Storage/FileSystem/pal_plat_fileSystem.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/Storage/Flash/pal_plat_internalFlash.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/Update/pal_plat_update.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Board_Specific/TARGET_OpenWRT_Generic/pal_plat_OpenWRT_Generic.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Board_Specific/TARGET_Yocto_Generic/pal_plat_Yocto_Generic.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Board_Specific/TARGET_x86_x64/pal_plat_x86_x64.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Networking/pal_plat_network.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/RTOS/pal_plat_rtos.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Storage/FileSystem/pal_plat_fileSystem.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Update/pal_plat_update.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Networking/pal_plat_network.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/RTOS/pal_plat_rtos.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Storage/FileSystem/pal_plat_fileSystem.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Storage/Flash/pal_plat_internalFlash.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Update/pal_plat_update.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/CMakeLists.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Crypto/pal_crypto_test.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Crypto/pal_crypto_test_data.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Crypto/pal_crypto_test_runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/FileSystem/pal_fileSystem_test.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/FileSystem/pal_fileSystem_test_runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Networking/pal_socket_test.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Networking/pal_socket_test_runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/RTOS/pal_rtos_test.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/RTOS/pal_rtos_test_runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/RTOS/pal_rtos_test_utils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/RTOS/pal_rtos_test_utils.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/SOTP/pal_SOTP_test.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/SOTP/pal_SOTP_test_runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Sanity/pal_sanity_test.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Sanity/pal_sanity_test_runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Storage/pal_internalFlash_test.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Storage/pal_internalFlash_test_runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test_address.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test_runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_utils.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Update/pal_update_test.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Update/pal_update_test_runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/test_main.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/test_runners.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Sotp/security/pal_security_test_main.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/Crypto/pal_crypto_test_main.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/FileSystem/pal_FileSystem_test_main.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/Full_pal/pal_all_test_main.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/Networking/pal_Networking_test_main.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/RTOS/pal_rtos_test_main.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/Sanity/pal_sanity_test_main.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/Storage/pal_Storage_test_main.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/TLS/pal_TLS_test_main.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/Update/pal_Update_test_main.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/a_pal_reformat/pal_a_pal_reformat_test_main.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/pal_make.py Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/colour_prompt.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/colour_reporter.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/generate_module.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/generate_test_runner.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/parseOutput.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/stylize_as_junit.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/test_file_filter.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/type_sanitizer.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/unity_test_summary.py Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/unity_test_summary.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/unity_to_junit.py Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/docs/UnityAssertionsReference.pdf Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/docs/UnityConfigurationGuide.pdf Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/docs/UnityGettingStartedGuide.pdf Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/docs/UnityHelperScriptsGuide.pdf Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/docs/license.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/readme.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/src/ProductionCode.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/src/ProductionCode.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/src/ProductionCode2.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/src/ProductionCode2.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/test/TestProductionCode.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/test/TestProductionCode2.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/readme.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/src/ProductionCode.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/src/ProductionCode.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/src/ProductionCode2.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/src/ProductionCode2.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/test/TestProductionCode.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/test/TestProductionCode2.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/test/test_runners/all_tests.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/helper/UnityHelper.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/helper/UnityHelper.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/rakefile.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/rakefile_helper.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/readme.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/src/ProductionCode.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/src/ProductionCode.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/src/ProductionCode2.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/src/ProductionCode2.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/test/TestProductionCode.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/test/TestProductionCode2.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/unity_config.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/eclipse/error_parsers.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/rakefile.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/rakefile_helper.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/readme.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/src/unity_fixture.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/src/unity_fixture.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/src/unity_fixture_internals.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/src/unity_fixture_malloc_overrides.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/test/main/AllTests.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/test/template_fixture_tests.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/test/unity_fixture_Test.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/test/unity_fixture_TestRunner.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/test/unity_output_Spy.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/test/unity_output_Spy.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/release/build.info Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/release/version.info Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/src/unity.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/src/unity.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/src/unity_internals.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_cmd.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_def.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_head1.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_head1.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_cmd.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_def.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_head1.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_head1.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_new1.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_new2.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_param.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_run1.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_run2.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_yaml.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_new1.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_new2.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_param.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_run1.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_run2.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_yaml.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/rakefile Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/rakefile_helper.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/testdata/mocksample.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/testdata/testsample.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/tests/test_generate_test_runner.rb Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/tests/testparameterized.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/tests/testunity.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/Scripts/junit_cmd_wrapper.py Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/memoryProfiler/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/memoryProfiler/Other/pal_memory.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/memoryProfiler/mbed-os/pal_memory.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/stackUsage/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/stackUsage/TestSuite/TargetFunctions.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/stackUsage/TestSuite/Template/template.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/stackUsage/TestSuite/TestsGenarator.py Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/pal_version.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/pal_version.h.in Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/valgrindSuppress.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-randlib/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-randlib/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-randlib/apache-2.0.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-randlib/mbed-client-randlib/platform/arm_hal_random.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-randlib/mbed-client-randlib/randLIB.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client-randlib/source/randLIB.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/DOXYGEN_FRONTPAGE.md Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/doxygen/mbedclient_doxy Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/README.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/apache-2.0.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/doxygen/client-c_doxy Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/nsdl-c/sn_client_config.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/nsdl-c/sn_nsdl.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/nsdl-c/sn_nsdl_lib.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/source/include/sn_grs.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/source/sn_grs.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/source/sn_nsdl.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/mbed-client-classic/m2mconnectionhandlerpimpl.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/mbed-client-classic/m2mtimerpimpl.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/source/m2mconnectionhandler.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/source/m2mtimer.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/source/m2mtimerpimpl.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-mbed-tls/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-mbed-tls/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-mbed-tls/apache-2.0.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-mbed-tls/mbed-client-mbedtls/m2mconnectionsecuritypimpl.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-mbed-tls/source/m2mconnectionsecurity.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-mbed-tls/source/m2mconnectionsecuritypimpl.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/functionpointer.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mbase.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mblockmessage.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mconfig.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mconnectionhandler.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mconnectionobserver.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mconnectionsecurity.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mconstants.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mdevice.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mendpoint.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mfirmware.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2minterface.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2minterfacefactory.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2minterfaceobserver.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mobject.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mobjectinstance.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mobservationhandler.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mreportobserver.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mresource.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mresourcebase.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mresourceinstance.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2msecurity.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mserver.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mstring.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mstringbuffer.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mstringbufferbase.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mtimer.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mtimerobserver.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mvector.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/uriqueryparser.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/eventdata.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mcallbackstorage.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2minterfaceimpl.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mnotificationhandler.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mnsdlinterface.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mnsdlobserver.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mreporthandler.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mtlvdeserializer.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mtlvserializer.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/nsdlaccesshelper.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/nsdllinker.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/smartpointer.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mbase.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mblockmessage.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mcallbackstorage.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mdevice.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mendpoint.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mfirmware.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2minterfacefactory.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2minterfaceimpl.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mnotificationhandler.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mnsdlinterface.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mobject.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mobjectinstance.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mreporthandler.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mresource.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mresourcebase.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mresourceinstance.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2msecurity.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mserver.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mstring.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mstringbufferbase.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mtlvdeserializer.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mtlvserializer.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/nsdlaccesshelper.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/uriqueryparser.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-cloud-client/MbedCloudClient.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-cloud-client/MbedCloudClientConfig.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-cloud-client/MbedCloudClientConfigCheck.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-cloud-client/SimpleM2MResource.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/README.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/apache-2.0.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/doxygen/libcoap_doxy Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/mbed-coap/sn_coap_header.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/mbed-coap/sn_coap_protocol.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/mbed-coap/sn_config.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/source/include/sn_coap_header_internal.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/source/include/sn_coap_protocol_internal.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/source/sn_coap_builder.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/source/sn_coap_header_check.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/source/sn_coap_parser.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/source/sn_coap_protocol.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/CMakeLists.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/mbed-trace/mbed_trace.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/source/CMakeLists.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/source/mbed_trace.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/apache-2.0.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/common_functions.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/ip6string.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/ip_fsc.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/ns_list.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/ns_nvm_helper.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/ns_trace.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/ns_types.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/nsdynmemLIB.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/platform/arm_hal_interrupt.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/platform/arm_hal_nvm.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/IPv6_fcf_lib/ip_fsc.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/libBits/common_functions.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/libList/ns_list.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/libip6string/ip6tos.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/libip6string/stoip6.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/nsdynmemLIB/nsdynmemLIB.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/nvmHelper/ns_nvm_helper.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/arm_hal_interrupt.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/arm_hal_interrupt_private.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/arm_hal_random.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/arm_hal_timer.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/ns_event_loop.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/ns_event_loop.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/ns_hal_init.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/ns_hal_init.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/apache-2.0.txt Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_callback_timer.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_event.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_event_timer.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_scheduler.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/nanostack-event-loop/platform/arm_hal_timer.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/nanostack-event-loop/platform/eventloop_config.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/event.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/event.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/minar_hal_timer.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/ns_timeout.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/ns_timer.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/ns_timer.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/system_timer.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/timer_sys.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/CertificateParser.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/CloudClientStorage.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/ConnectorClient.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/MbedCloudClient.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/ServiceClient.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/SimpleM2MResource.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/UpdateClient.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/include/CertificateParser.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/include/CloudClientStorage.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/include/ConnectorClient.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/include/ServiceClient.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/include/UpdateClient.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/source/include/UpdateClientResources.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/atomic-queue/atomic-queue.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/aq_critical.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/atomic-cm3.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/atomic-queue.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/atomic.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/atomic.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/critical-nordic.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/critical-pal.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/critical-posix.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/critical.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/posix.cmake Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_crypto.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_error.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_metadata_header_v2.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_scheduler.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_test_rot.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_utilities.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_common.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_config.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_crypto.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_error.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_metadata_header_v2.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_public.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_scheduler.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_trace.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_types.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_utilities.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/source/arm_uc_certificate.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/source/arm_uc_certificate_cfstore_api.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/source/arm_uc_certificate_kcm_api.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/source/arm_uc_control_center.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/source/arm_uc_pre_shared_key.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/update-client-control-center/arm_uc_certificate.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/update-client-control-center/arm_uc_control_center.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/update-client-control-center/arm_uc_pre_shared_key.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/device-identity/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/device-identity/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/device-identity/pal4life-device-identity/pal_device_identity.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/device-identity/source/arm_uc_device_identity.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/device-identity/source/arm_uc_device_identity_cfstore.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/device-identity/source/arm_uc_device_identity_kcm.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/firmware-manager/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/firmware-manager/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/firmware-manager/source/arm_uc_firmware_manager.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/firmware-manager/update-client-firmware-manager/arm_uc_firmware_manager.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/DeviceMetadataResource.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/FirmwareUpdateResource.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/lwm2m-control.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/lwm2m-monitor.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/lwm2m-source.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/update-lwm2m-mbed-apis.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/update-lwm2m-mbed-apis.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/update-client-lwm2m/DeviceMetadataResource.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/update-client-lwm2m/FirmwareUpdateResource.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/update-client-lwm2m/lwm2m-control.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/update-client-lwm2m/lwm2m-monitor.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/update-client-lwm2m/lwm2m-source.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmCommon.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmCommon.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmConfig.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmCryptoUtils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmCryptoUtils.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmDerManifestAccessors.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmDerManifestAccessors.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmDerManifestParser.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmDerManifestParser.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmFSMHelper.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmFetchFirmwareInfo.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmFetchFirmwareInfo.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmGetLatestTimestamp.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmGetLatestTimestamp.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmInit.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmInit.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmInsertManifest.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmInsertManifest.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmStateSelector.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmStateSelector.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/manifest-manager-api.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/update-client-manifest-manager/arm-pal-kv.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/update-client-manifest-manager/update-client-manifest-manager-context.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/update-client-manifest-manager/update-client-manifest-manager.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/update-client-manifest-manager/update-client-manifest-types.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/monitor/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/monitor/update-client-monitor/arm_uc_monitor.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/paal/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/paal/source/arm_uc_paal_update.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/paal/update-client-paal/arm_uc_paal_update.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/paal/update-client-paal/arm_uc_paal_update_api.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/source/arm_uc_pal_blockdevice.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/source/arm_uc_pal_blockdevice_implementation.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/source/arm_uc_pal_blockdevice_mbed.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/update-client-pal-blockdevice/arm_uc_pal_blockdevice.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/update-client-pal-blockdevice/arm_uc_pal_blockdevice_implementation.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/update-client-pal-blockdevice/arm_uc_pal_blockdevice_platform.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/source/arm_uc_paal_classic_pal.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/source/arm_uc_pal_filesystem_utils.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/source/arm_uc_pal_filesystem_utils.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/source/arm_uc_pal_linux_extensions.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/source/arm_uc_pal_mbed_extensions.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/update-client-pal-filesystem/arm_uc_pal_extensions.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/update-client-pal-filesystem/arm_uc_pal_filesystem.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/source/arm_uc_pal_flashiap.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/source/arm_uc_pal_flashiap_implementation.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/source/arm_uc_pal_flashiap_mbed.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/update-client-pal-flashiap/arm_uc_pal_flashiap.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/update-client-pal-flashiap/arm_uc_pal_flashiap_implementation.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/update-client-pal-flashiap/arm_uc_pal_flashiap_platform.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/arm_update_cmdline.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_activate.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_active_details.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_details.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_finalize.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_initialize.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_installer.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_prepare.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_read.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_write.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/openwrt/arm_update_activate.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/openwrt/arm_update_active_details.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/openwrt/arm_update_kernel.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/yocto_generic/arm_update_activate.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/yocto_generic/arm_update_active_details.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/yocto_generic/arm_update_common.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/yocto_rpi/arm_update_activate.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/yocto_rpi/arm_update_active_details.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/yotta_install.sh Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/source/arm_uc_pal_linux_generic.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/source/arm_uc_pal_linux_implementation.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/source/arm_uc_pal_linux_implementation_internal.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/source/arm_uc_pal_linux_openwrt.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/source/arm_uc_pal_linux_yocto_generic.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/source/arm_uc_pal_linux_yocto_rpi.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/update-client-pal-linux/arm_uc_pal_linux_generic.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/update-client-pal-linux/arm_uc_pal_linux_implementation.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/update-client-pal-linux/arm_uc_pal_linux_implementation_internal.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/update-client-pal-linux/arm_uc_pal_linux_openwrt.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-target-specific/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-target-specific/source/arm_uc_pal_realtek_rtl8195am.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-target-specific/update-client-pal-target-specific/arm_uc_pal_realtek_rtl8195am.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/source/arm_uc_http_socket.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/source/arm_uc_http_socket_private.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/source/arm_uc_http_socket_private.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/source/arm_uc_socket_help.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/source/arm_uc_socket_help.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/update-client-source-http-socket/arm_uc_http_socket.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http/source/arm_uc_source_http.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http/update-client-source-http/arm_uc_source_http.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http/update-client-source-http/arm_uc_source_http_extra.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-manager/.mbedignore Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-manager/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-manager/source/arm_uc_source_manager.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-manager/update-client-source-manager/arm_uc_source_manager.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source/LICENSE Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source/update-client-source/arm_uc_source.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub_error_handler.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub_error_handler.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub_event_handlers.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub_event_handlers.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub_state_machine.c Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub_state_machine.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/update-client-hub/update_client_certificate.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/update-client-hub/update_client_hub.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/update-client-hub/update_client_public.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed_cloud_client_resource.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/mbed_cloud_client_resource.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/memory_tests.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/memory_tests.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/pal_plat_rot_insecure.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/resource.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/resource.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/simple-mbed-cloud-client.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/simple-mbed-cloud-client.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/sotp_fs_config_MbedOS.h Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/update_ui_example.cpp Show annotated file Show diff for this revision Revisions of this file
simple-mbed-cloud-client/update_ui_example.h Show annotated file Show diff for this revision Revisions of this file
update_default_resources.c Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362.lib Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/FETCH_HEAD Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/HEAD Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/ORIG_HEAD Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/config Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/description Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/hooks/applypatch-msg.sample Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/hooks/commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/hooks/post-update.sample Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/hooks/pre-applypatch.sample Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/hooks/pre-commit.sample Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/hooks/pre-rebase.sample Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/hooks/prepare-commit-msg.sample Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/hooks/update.sample Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/index Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/info/exclude Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/logs/HEAD Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/logs/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/logs/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/objects/pack/pack-8bf1447bb4ae1bb2894fa2c84da739c66001d7d1.idx Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/objects/pack/pack-8bf1447bb4ae1bb2894fa2c84da739c66001d7d1.pack Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/packed-refs Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/refs/heads/master Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.git/refs/remotes/origin/HEAD Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/.meta Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/ATParser.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/ATParser.h Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/BufferedSpi/Buffer/MyBuffer.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/BufferedSpi/Buffer/MyBuffer.h Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedPrint.c Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedSpi.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedSpi.h Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ISM43362.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362/ISM43362.h Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362Interface.cpp Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/ISM43362Interface.h Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/README.md Show annotated file Show diff for this revision Revisions of this file
wifi-ism43362/mbed_lib.json Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,68 @@
+# Mbed Cloud Workshop - Connect Service
+
+## Embedded Application
+
+### Prerequisites
+1. Install [Mbed CLI](https://os.mbed.com/docs/latest/tools/installation-and-setup.html)
+1. Register for an [Mbed OS account](https://os.mbed.com/account/signup/) (if you do not already have one)
+1. Register for an [Mbed Cloud account](http://cloud.mbed.com/quick-start)
+1. Download the code: `mbed import https://github.com/BlackstoneEngineering/mbed-cloud-workshop-connect`
+
+### Let's Code: Device to Dashboard
+1. Create a Developer Certificate for your device
+   1. Log into the [Mbed Cloud Portal](https://portal.mbedcloud.com/) with your developer account.
+   1. Go to **Device Identity** -> **Certificates**.
+   1. Click **Actions** -> **Create a developer certificate**.
+   1. Enter a certificate file name. This file name is for your convenience. For example: `Jenny_Plunkett`
+   1. Click **Create Certificate**.
+   1. A credentials C file called `mbed_cloud_dev_credentials.c` is created. It contains the credentials you need to connect your device to Mbed Cloud.
+   1. Download the file and copy/paste it into your `mbed-cloud-workshop-connect` project folder
+1. Change the wifi SSID and password credentials at the top of `main.cpp`
+   - SSID: `mbed`
+   - Password: `mbedisawesome`
+1. Plug the board into your computer
+1. Compile, flash, and view the board's serial output
+   - `mbed compile --target auto --toolchain GCC_ARM --flash --sterm`
+1. View your Mbed Cloud Portal dashboard: https://portal.mbedcloud.com/dashboard/usage
+
+### Let's Code: Make Device Blink
+- Read number of button presses – GET from "3200/0/5501", "button_count"​
+- Make LED’s Blink – POST to "3201/0/5850", "blink_action” ​
+- Change LED Blink Pattern – PUT to "3201/0/5853", "blink_pattern” 
+
+### Let's Code: Challenge
+- Change variables in Developer Certificate
+   - Serial, name, device type ... etc.
+- Add variables with multiple functions GET/PUT/POST
+
+## Web App
+
+### Let's Code: Web App
+1. Install [Node.js](https://nodejs.org/en/) and [npm](https://www.npmjs.com/)
+1. Clone the Mbed Cloud SDK JavaScript Quickstart to your computer
+   - `git clone https://github.com/ARMmbed/mbed-cloud-sdk-javascript-quickstart`
+1. `cd mbed-cloud-sdk-javascript-quickstart`
+1. Install the required npm packages: `npm install`
+1. Create your API key
+   1. Open the Mbed Cloud Portal: https://portal.mbedcloud.com/
+   1. In the Cloud portal, navigate to **Access management** > **API keys**
+   1. Click **Create new API key**.
+   1. Define the API key name. For example: `Jenny`
+   1. Select the key's group. Note that the key will have the same privileges as the group you select, meaning an administrator key will have full privileges.
+   1. Click **Create API key**. A key is generated.
+   1. Copy the generated API key.
+1. Open `app.js`
+   - Replace the `<access key>` placeholder in the `accessKey` variable on line 8 with the API key you just copied
+1. Run the app: `node app.js`
+1. Open `http://localhost:8080` in your browser
+1. You should now see a list of connected Mbed Cloud JavaScript Quickstart devices
+   <img width="946" src="/img2.png">
+1. If you open the Mbed Cloud portal (https://portal.mbedcloud.com/) you should also see your device listed under **Device directory** > **Devices**
+   <img width="835" src="/img1.png">
+
+### Let's Code: GET/PUT/POST to Device
+1. Subscribe to your board's simulated button presses by clicking on the checkbox next to **Subscribe** and then click **Get presses (GET)**
+1. Type `500:500:500:500` into the text box below **LED blink pattern**
+   - This pattern indicates that the LED on the board will turn on for 500 ms, turn off for 500 ms, turn on for 500 ms, and then turn off for 500 ms (and then stay off)
+1. Click **Update (PUT)**
+1. Now click **Blink (POST)** and verify that your board's LED blinked twice
Binary file img1.png has changed
Binary file img2.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,199 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "mbed.h"
+#include <stdio.h>
+#include <errno.h>
+
+#include "qspi_api.h"
+#include "QSPI.h"
+#include "qspi-blockdevice/QSPIFBlockDevice.h"
+#define DEVICE_QSPI
+
+#include "FATFileSystem.h"
+#include "LittleFileSystem.h"
+#include "simple-mbed-cloud-client.h"
+// #include "SDBlockDevice.h"
+#include "ISM43362Interface.h"
+// #include "SPIFBlockDevice.h" // to use onboard spi flash
+
+#define WIFI_SSID       "mbed"
+#define WIFI_PASSWORD   "workshop-password"
+
+
+
+
+// An event queue is a very useful structure to debounce information between contexts (e.g. ISR and normal threads)
+// This is great because things such as network operations are illegal in ISR, so updating a resource in a button's fall() function is not allowed
+EventQueue eventQueue;
+
+// Declaring net interface as a global variable instead of local to avoid stack overflow
+ISM43362Interface net;
+
+// Storage implementation definition, currently using SDBlockDevice (SPI flash, DataFlash, and internal flash are also available)
+// SDBlockDevice sd(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS);
+QSPIFBlockDevice sd(PE_12, PE_13, PE_14, PE_15,PE_10,PE_11,0,8000000);
+
+// FATFileSystem fs("sd", &bd);
+
+LittleFileSystem fs("sd");
+
+// Declaring pointers for access to Mbed Cloud Client resources outside of main()
+MbedCloudClientResource *button_res;
+MbedCloudClientResource *pattern_res;
+
+// This function gets triggered by the timer. It's easy to replace it by an InterruptIn and fall() mode on a real button
+void fake_button_press() {
+    int v = button_res->get_value_int() + 1;
+
+    button_res->set_value(v);
+
+    printf("Simulated button clicked %d times\n", v);
+}
+
+/**
+ * PUT handler
+ * @param resource The resource that triggered the callback
+ * @param newValue Updated value for the resource
+ */
+void pattern_updated(MbedCloudClientResource *resource, m2m::String newValue) {
+    printf("PUT received, new value: %s\n", newValue.c_str());
+}
+
+/**
+ * POST handler
+ * @param resource The resource that triggered the callback
+ * @param buffer If a body was passed to the POST function, this contains the data.
+ *               Note that the buffer is deallocated after leaving this function, so copy it if you need it longer.
+ * @param size Size of the body
+ */
+void blink_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
+    printf("POST received. Going to blink LED pattern: %s\n", pattern_res->get_value().c_str());
+
+    static DigitalOut augmentedLed(LED1); // LED that is used for blinking the pattern
+
+    // Parse the pattern string, and toggle the LED in that pattern
+    string s = std::string(pattern_res->get_value().c_str());
+    size_t i = 0;
+    size_t pos = s.find(':');
+    while (pos != string::npos) {
+        wait_ms(atoi(s.substr(i, pos - i).c_str()));
+        augmentedLed = !augmentedLed;
+
+        i = ++pos;
+        pos = s.find(':', pos);
+
+        if (pos == string::npos) {
+            wait_ms(atoi(s.substr(i, s.length()).c_str()));
+            augmentedLed = !augmentedLed;
+        }
+    }
+}
+
+/**
+ * Notification callback handler
+ * @param resource The resource that triggered the callback
+ * @param status The delivery status of the notification
+ */
+void button_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status) {
+    printf("Button notification, status %s (%d)\n", MbedCloudClientResource::delivery_status_to_string(status), status);
+}
+
+/**
+ * Registration callback handler
+ * @param endpoint Information about the registered endpoint such as the name (so you can find it back in portal)
+ */
+void registered(const ConnectorClientEndpointInfo *endpoint) {
+    printf("Connected to Mbed Cloud. Endpoint Name: %s\n", endpoint->internal_endpoint_name.c_str());
+}
+
+int main(void) {
+    printf("Starting Simple Mbed Cloud Client example\n");
+
+    printf("Checking SDCard is Formatted\r\n");
+    int err = fs.mount(&sd);
+    printf("%s\n", (err ? "Fail :(" : "OK"));
+    if (err) {
+        // Reformat if we can't mount the filesystem
+        // this should only happen on the first boot
+        printf("No filesystem found, formatting... ");
+        fflush(stdout);
+        err = fs.reformat(&sd);
+        printf("%s\n", (err ? "Fail :(" : "OK"));
+        if (err) {
+            error("error: %s (%d)\n", strerror(-err), err);
+        }
+    }
+    // err = fs.unmount();
+    // printf("%s\n", (err < 0 ? "Fail :(" : "OK"));
+    // if (err < 0) {
+    //     error("error: %s (%d)\n", strerror(-err), err);
+    // }
+
+    printf("Connecting to the network using Wifi...\n");
+
+    // Connect to the internet (DHCP is expected to be on)
+    nsapi_error_t status = net.connect(WIFI_SSID, WIFI_PASSWORD, (strlen(WIFI_PASSWORD) > 1) ? NSAPI_SECURITY_WPA_WPA2 : NSAPI_SECURITY_NONE);
+
+    if (status != 0) {
+        printf("Connecting to the network failed %d!\n", status);
+        return -1;
+    }
+
+    printf("Connected to the network successfully. IP address: %s\n", net.get_ip_address());
+
+    // SimpleMbedCloudClient handles registering over LwM2M to Mbed Cloud
+    SimpleMbedCloudClient client(&net, &sd, &fs);
+    int client_status = client.init();
+    if (client_status != 0) {
+        printf("Initializing Mbed Cloud Client failed (%d)\n", client_status);
+        return -1;
+    }
+
+    // Creating resources, which can be written or read from the cloud
+    button_res = client.create_resource("3200/0/5501", "button_count");
+    button_res->set_value(0);
+    button_res->methods(M2MMethod::GET);
+    button_res->observable(true);
+    button_res->attach_notification_callback(button_callback);
+
+    pattern_res = client.create_resource("3201/0/5853", "blink_pattern");
+    pattern_res->set_value("500:500:500:500:500:500:500:500");
+    pattern_res->methods(M2MMethod::GET | M2MMethod::PUT);
+    pattern_res->attach_put_callback(pattern_updated);
+
+    MbedCloudClientResource *blink_res = client.create_resource("3201/0/5850", "blink_action");
+    blink_res->methods(M2MMethod::POST);
+    blink_res->attach_post_callback(blink_callback);
+
+    printf("Initialized Mbed Cloud Client. Registering...\n");
+
+    // Callback that fires when registering is complete
+    client.on_registered(&registered);
+
+    // Register with Mbed Cloud
+    client.register_and_connect();
+
+    // Placeholder for callback to update local resource when GET comes.
+    // The timer fires on an interrupt context, but debounces it to the eventqueue, so it's safe to do network operations
+    Ticker timer;
+    timer.attach(eventQueue.event(&fake_button_press), 5.0);
+
+    // You can easily run the eventQueue in a separate thread if required
+    eventQueue.dispatch_forever();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#c53d51fe9220728bf8ed27afe7afc1ecc3f6f5d7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_app.json	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,73 @@
+{
+    "macros": [
+        "MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS.h\"",
+        "PAL_USER_DEFINED_CONFIGURATION=\"sotp_fs_config_MbedOS.h\"",
+        "MBED_CLIENT_USER_CONFIG_FILE=\"mbed_cloud_client_user_config.h\"",
+        "MBED_CLOUD_CLIENT_USER_CONFIG_FILE=\"mbed_cloud_client_user_config.h\"",
+        "PAL_DTLS_PEER_MIN_TIMEOUT=5000",
+        "MBED_CONF_APP_MAIN_STACK_SIZE=6000",
+        "ARM_UC_USE_PAL_BLOCKDEVICE=1",
+        "MBED_CLOUD_CLIENT_UPDATE_STORAGE=ARM_UCP_FLASHIAP_BLOCKDEVICE",
+        "RTX_NO_MULTITHREAD_CLIB"
+    ],
+    "target_overrides": {
+        "*": {
+            "platform.stdio-baud-rate": 9600,
+            "platform.stdio-convert-newlines": true,
+            "update-client.storage-address"  : "(1024*1024*64)",
+            "update-client.storage-size"     : "(1024*1024*2)",
+            "update-client.storage-locations": "1",
+            "mbed-trace.enable": false
+        },
+        "DISCO_L475VG_IOT01A": {
+            "sotp-section-1-address"           : "(0x08000000+((1024-32)*1024))",
+            "sotp-section-1-size"              : "(16*1024)",
+            "sotp-section-2-address"           : "(0x08000000+((1024-16)*1024))",
+            "sotp-section-2-size"              : "(16*1024)",
+            "sotp-num-sections"                : 2
+        },
+        "DISCO_F413ZH": {
+            "sotp-section-1-address"           : "(0x08000000+((1536-256)*1024))",
+            "sotp-section-1-size"              : "(128*1024)",
+            "sotp-section-2-address"           : "(0x08000000+((1536-128)*1024))",
+            "sotp-section-2-size"              : "(128*1024)",
+            "sotp-num-sections"                : 2
+        }
+
+    },
+    "config": {
+        "format-storage-layer-on-error": {
+            "help": "Whether to format the storage layer when it cannot be read - always disable for production devices!",
+            "value": 1
+        },
+        "developer-mode": {
+            "help": "Enable Developer mode to skip Factory enrollment",
+            "value": 1
+        },
+        "sotp-section-1-address": {
+            "help": "Flash sector address for SOTP sector 1",
+            "macro_name": "PAL_INTERNAL_FLASH_SECTION_1_ADDRESS",
+            "value": null
+        },
+        "sotp-section-1-size": {
+            "help": "Flash sector size for SOTP sector 1",
+            "macro_name": "PAL_INTERNAL_FLASH_SECTION_1_SIZE",
+            "value": null
+        },
+        "sotp-section-2-address": {
+            "help": "Flash sector address for SOTP sector 2",
+            "macro_name": "PAL_INTERNAL_FLASH_SECTION_2_ADDRESS",
+            "value": null
+        },
+        "sotp-section-2-size": {
+            "help": "Flash sector size for SOTP sector 2",
+            "macro_name": "PAL_INTERNAL_FLASH_SECTION_2_SIZE",
+            "value": null
+        },
+        "sotp-num-sections": {
+            "help": "Number of SOTP sections",
+            "macro_name": "PAL_INT_FLASH_NUM_SECTIONS",
+            "value": null
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_cloud_client_user_config.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,59 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+// This file is a template and it's intented to be copied to the application
+// Enable this configuration
+
+#ifndef MBED_CLOUD_CLIENT_USER_CONFIG_H
+#define MBED_CLOUD_CLIENT_USER_CONFIG_H
+
+#ifdef MBED_CONF_APP_ENDPOINT_TYPE
+#define MBED_CLOUD_CLIENT_ENDPOINT_TYPE         MBED_CONF_APP_ENDPOINT_TYPE
+#else
+#define MBED_CLOUD_CLIENT_ENDPOINT_TYPE         "default"
+#endif
+
+// Enable either TCP or UDP, but no both
+#define MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP
+// MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP
+
+#define MBED_CLOUD_CLIENT_LIFETIME              3600
+
+#define MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+#define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE       1024
+
+// set flag to enable update support in mbed Cloud client
+#define MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+
+// set download buffer size in bytes (min. 1024 bytes)
+
+// Use larger buffers in Linux //
+#ifdef __linux__
+#define MBED_CLOUD_CLIENT_UPDATE_BUFFER          (2 * 1024 * 1024)
+#else
+#define MBED_CLOUD_CLIENT_UPDATE_BUFFER          2048
+#endif
+
+// Developer flags for Update feature
+#if MBED_CONF_APP_DEVELOPER_MODE == 1
+    #define MBED_CLOUD_DEV_UPDATE_CERT
+    #define MBED_CLOUD_DEV_UPDATE_ID
+#endif // MBED_CONF_APP_DEVELOPER_MODE
+
+#endif // MBED_CLOUD_CLIENT_USER_CONFIG_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_cloud_dev_credentials.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef __MBED_CLOUD_DEV_CREDENTIALS_H__
+#define __MBED_CLOUD_DEV_CREDENTIALS_H__
+ 
+#if MBED_CONF_APP_DEVELOPER_MODE == 1
+#error "Replace mbed_cloud_dev_credentials.c with your own developer cert."
+#endif
+ 
+#include <inttypes.h>
+ 
+const char MBED_CLOUD_DEV_BOOTSTRAP_ENDPOINT_NAME[] = "";
+const char MBED_CLOUD_DEV_ACCOUNT_ID[] = "";
+const char MBED_CLOUD_DEV_BOOTSTRAP_SERVER_URI[] = "";
+ 
+const uint8_t MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_CERTIFICATE[] =
+{ 0x0 };
+ 
+const uint8_t MBED_CLOUD_DEV_BOOTSTRAP_SERVER_ROOT_CA_CERTIFICATE[] =
+{ 0x0 };
+ 
+const uint8_t MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_PRIVATE_KEY[] =
+{ 0x0 };
+ 
+const char MBED_CLOUD_DEV_MANUFACTURER[] = "dev_manufacturer";
+ 
+const char MBED_CLOUD_DEV_MODEL_NUMBER[] = "dev_model_num";
+ 
+const char MBED_CLOUD_DEV_SERIAL_NUMBER[] = "0";
+ 
+const char MBED_CLOUD_DEV_DEVICE_TYPE[] = "dev_device_type";
+ 
+const char MBED_CLOUD_DEV_HARDWARE_VERSION[] = "dev_hardware_version";
+ 
+const uint32_t MBED_CLOUD_DEV_MEMORY_TOTAL_KB = 0;
+const uint32_t MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_CERTIFICATE_SIZE = sizeof(MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_CERTIFICATE);
+const uint32_t MBED_CLOUD_DEV_BOOTSTRAP_SERVER_ROOT_CA_CERTIFICATE_SIZE = sizeof(MBED_CLOUD_DEV_BOOTSTRAP_SERVER_ROOT_CA_CERTIFICATE);
+const uint32_t MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_PRIVATE_KEY_SIZE = sizeof(MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_PRIVATE_KEY);
+ 
+#endif //__MBED_CLOUD_DEV_CREDENTIALS_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_settings.py	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,48 @@
+"""
+mbed SDK
+Copyright (c) 2016 ARM Limited
+
+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.
+"""
+
+from os.path import join, abspath, dirname
+
+#ROOT = abspath(join(dirname(__file__), "."))
+
+##############################################################################
+# Build System Settings
+##############################################################################
+#BUILD_DIR = abspath(join(ROOT, "build"))
+
+# ARM
+#ARM_PATH = "C:/Program Files/ARM"
+
+# GCC ARM
+#GCC_ARM_PATH = ""
+
+# GCC CodeRed
+#GCC_CR_PATH = "C:/code_red/RedSuite_4.2.0_349/redsuite/Tools/bin"
+
+# IAR
+#IAR_PATH = "C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.0/arm"
+
+# Goanna static analyser. Please overload it in private_settings.py
+#GOANNA_PATH = "c:/Program Files (x86)/RedLizards/Goanna Central 3.2.3/bin"
+
+#BUILD_OPTIONS = []
+
+# mbed.org username
+#MBED_ORG_USER = ""
+
+# Print compiler warnings and errors as link format
+#PRINT_COMPILER_OUTPUT_AS_LINK = False
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice.lib	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+https://github.com/BlackstoneEngineering/qspi-blockdevice/#a647214121d6495e870ea45951499bcac26b3c04
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/FETCH_HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+a647214121d6495e870ea45951499bcac26b3c04		branch 'master' of https://github.com/BlackstoneEngineering/qspi-blockdevice
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+ref: refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/ORIG_HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+a647214121d6495e870ea45951499bcac26b3c04
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/config	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,11 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote "origin"]
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	url = https://github.com/BlackstoneEngineering/qspi-blockdevice/
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/description	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/hooks/applypatch-msg.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/hooks/commit-msg.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
+	echo >&2 Duplicate Signed-off-by lines.
+	exit 1
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/hooks/post-update.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/hooks/pre-applypatch.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/hooks/pre-commit.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+	# Note that the use of brackets around a tr range is ok here, (it's
+	# even required, for portability to Solaris 10's /usr/bin/tr), since
+	# the square bracket bytes happen to fall in the designated range.
+	test $(git diff --cached --name-only --diff-filter=A -z $against |
+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+	echo "Error: Attempt to add a non-ascii file name."
+	echo
+	echo "This can cause problems if you want to work"
+	echo "with people on other platforms."
+	echo
+	echo "To be portable it is advisable to rename the file ..."
+	echo
+	echo "If you know what you are doing you can disable this"
+	echo "check using:"
+	echo
+	echo "  git config hooks.allownonascii true"
+	echo
+	exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/hooks/pre-rebase.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+	topic="refs/heads/$2"
+else
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+	;;
+*)
+	exit 0 ;# we do not interrupt others.
+	;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+	echo >&2 "$topic is fully merged to master; better remove it."
+	exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+	not_in_topic=`git rev-list "^$topic" master`
+	if test -z "$not_in_topic"
+	then
+		echo >&2 "$topic is already up-to-date with master"
+		exit 1 ;# we could allow it, but there is no point.
+	else
+		exit 0
+	fi
+else
+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+	/usr/bin/perl -e '
+		my $topic = $ARGV[0];
+		my $msg = "* $topic has commits already merged to public branch:\n";
+		my (%not_in_next) = map {
+			/^([0-9a-f]+) /;
+			($1 => 1);
+		} split(/\n/, $ARGV[1]);
+		for my $elem (map {
+				/^([0-9a-f]+) (.*)$/;
+				[$1 => $2];
+			} split(/\n/, $ARGV[2])) {
+			if (!exists $not_in_next{$elem->[0]}) {
+				if ($msg) {
+					print STDERR $msg;
+					undef $msg;
+				}
+				print STDERR " $elem->[1]\n";
+			}
+		}
+	' "$topic" "$not_in_next" "$not_in_master"
+	exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+		   o---o---o---o---o---o---o---o---o---o "next"
+		  /       /           /           /
+		 /   a---a---b A     /           /
+		/   /               /           /
+	       /   /   c---c---c---c B         /
+	      /   /   /             \         /
+	     /   /   /   b---b C     \       /
+	    /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+	git rev-list ^master ^topic next
+	git rev-list ^master        next
+
+	if these match, topic has not merged in next at all.
+
+To compute (2):
+
+	git rev-list master..topic
+
+	if this is empty, it is fully merged to "master".
+
+DOC_END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/hooks/prepare-commit-msg.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples.  The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+case "$2,$3" in
+  merge,)
+    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+#   /usr/bin/perl -i.bak -pe '
+#      print "\n" . `git diff --cached --name-status -r`
+#	 if /^#/ && $first++ == 0' "$1" ;;
+
+  *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/hooks/update.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+# hooks.denycreatebranch
+#   This boolean sets whether remotely creating branches will be denied
+#   in the repository.  By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+	echo "Don't run this script from the command line." >&2
+	echo " (if you want, you could supply GIT_DIR then run" >&2
+	echo "  $0 <ref> <oldrev> <newrev>)" >&2
+	exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+	echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+	exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+	echo "*** Project description file hasn't been set" >&2
+	exit 1
+	;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+	newrev_type=delete
+else
+	newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+	refs/tags/*,commit)
+		# un-annotated tag
+		short_refname=${refname##refs/tags/}
+		if [ "$allowunannotated" != "true" ]; then
+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,delete)
+		# delete tag
+		if [ "$allowdeletetag" != "true" ]; then
+			echo "*** Deleting a tag is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,tag)
+		# annotated tag
+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+		then
+			echo "*** Tag '$refname' already exists." >&2
+			echo "*** Modifying a tag is not allowed in this repository." >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,commit)
+		# branch
+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+			echo "*** Creating a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,delete)
+		# delete branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/remotes/*,commit)
+		# tracking branch
+		;;
+	refs/remotes/*,delete)
+		# delete tracking branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	*)
+		# Anything else (is there anything else?)
+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+		exit 1
+		;;
+esac
+
+# --- Finished
+exit 0
Binary file qspi-blockdevice/.git/index has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/info/exclude	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,25 @@
+.hg
+.git
+.svn
+.CVS
+.cvs
+*.orig
+.build
+.export
+.msub
+.meta
+.ctags*
+*.uvproj
+*.uvopt
+*.project
+*.cproject
+*.launch
+*.ewp
+*.eww
+Makefile
+Debug
+*.htm
+*.settings
+mbed_settings.py
+*.py[cod]
+# subrepo ignores
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/logs/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,3 @@
+0000000000000000000000000000000000000000 a647214121d6495e870ea45951499bcac26b3c04 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378395 +0000	clone: from https://github.com/BlackstoneEngineering/qspi-blockdevice/
+a647214121d6495e870ea45951499bcac26b3c04 a647214121d6495e870ea45951499bcac26b3c04 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378396 +0000	checkout: moving from master to a647214121d6495e870ea45951499bcac26b3c04
+a647214121d6495e870ea45951499bcac26b3c04 a647214121d6495e870ea45951499bcac26b3c04 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378396 +0000	checkout: moving from a647214121d6495e870ea45951499bcac26b3c04 to master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/logs/refs/heads/master	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 a647214121d6495e870ea45951499bcac26b3c04 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378395 +0000	clone: from https://github.com/BlackstoneEngineering/qspi-blockdevice/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/logs/refs/remotes/origin/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 a647214121d6495e870ea45951499bcac26b3c04 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378395 +0000	clone: from https://github.com/BlackstoneEngineering/qspi-blockdevice/
Binary file qspi-blockdevice/.git/objects/0d/c07f2fe61fed01cd18db482ffff23740de7cb6 has changed
Binary file qspi-blockdevice/.git/objects/1f/81351ca17ab112f74d118315f583ff89ac2c32 has changed
Binary file qspi-blockdevice/.git/objects/24/e7f0cb7a7cd71dcb14f2fbcfb39076cfff5424 has changed
Binary file qspi-blockdevice/.git/objects/26/1eeb9e9f8b2b4b0d119366dda99c6fd7d35c64 has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/objects/2b/8efb439a67aaa6915f99befd40d4e918a82c10	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+x‹½‚@­yŠ/±õL(4±56
Op{·6÷ƒ¯ØÍL2Ô+¡®¯‡#æ4‰¡^Ý×ó"Ž«ûÎxü>ÊÂA#>Åz´ï'dċأiq9ßNJÊ FI[üIîØæÙ̓€¢]
¶ÉhªV'‡)¼
\ No newline at end of file
Binary file qspi-blockdevice/.git/objects/3c/a4346dcf1c72e57e1e96c7949da51e98b61ce7 has changed
Binary file qspi-blockdevice/.git/objects/5a/015333ddcbcdbf68396216dc854a0f279fc050 has changed
Binary file qspi-blockdevice/.git/objects/80/0463e448cad5e8a7c356104d9b708ba763bae8 has changed
Binary file qspi-blockdevice/.git/objects/80/7cec9a3570e50ef724ef7bcbea256df2d1a0a1 has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/objects/8b/da207f635fa99cad8a683e43e5297d9a294bdb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+x­ŽKN1DYû}¢ögì	!„‚]'ðt·ƒÆFŽ“óÇÙäÔªTO*=ªÛ–;˜ŸzdL¯“0jb=óêf“FŒ
Y­^ýÅ&¥ƒ¥è¬óLIS02Ѳx
+‹[8N£Ï«×$AÅKÿ©
Þ#Î½rÌE¤år„—x9÷\vë¿Å¶í¨n¯ 'k,<ㄨÆ:œ»üϛŠÌw…¯ïÃçЫt‚½\3	ì[¾JS7“u\ç
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/objects/a6/47214121d6495e870ea45951499bcac26b3c04	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+x­ŽAN!E]sŠ:€Ó¡`&1câÒ¸ð]t“i`B3ñú¢Oàæ/ÞO^^¨9§õCoÌ0K88ÒÆJ6’£Uç1>x&ež–¨$I(nÔ¸tÀ8£6-yDíyAœ5šhfãì(¨ • {ßjƒ×Âõèµ0¼•5æ–Ê
+Ït?z*“ÿ»_¨å)Ô|4Úi+•Óp’FJ1èhîü?6‘éú“0¬7êÉï_©oPË>ò~qÚ¹=»ç>>!lTV>ÌäN3¡ß¡Ùg=
\ No newline at end of file
Binary file qspi-blockdevice/.git/objects/aa/110b91d4c5c37acfbeca6150d44c4605d34c75 has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/objects/d5/338770d8873cd612570d9ad98afdc7e1a44cac	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,3 @@
+x=ÁNÄ0D9÷+FâJÛ]`%8‚¸p@€–HZwk‘&mâvÕ¿ÇY
+RŽãyã‰uÁâîþpu)\Zšï–n¨xÎ5^.´‘ŠèBÄçlZ?^Áo–Z¼q¨o0ÌI`	sÒ晥GGFæHå42l4¾é:**C*Š¯žôïVHø×Î^Øý){¿ËS‘™ŒV߁u…”q»Û?TxJM”ì =ýÊ66°e8³sي½Ð)¹Õ=¯R½í¬;JkRÚ¶õ¤©õ‡`|ζbæ/ÆL‚A}5.x‚cÍ×
+?¥Ûz
\ No newline at end of file
Binary file qspi-blockdevice/.git/objects/e7/d3e2dde204ccfc574d163f13c396dddf5f4bf1 has changed
Binary file qspi-blockdevice/.git/objects/ff/29575af7e0d0074cbbf99ab9ed3354e9a81868 has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/packed-refs	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+# pack-refs with: peeled 
+a647214121d6495e870ea45951499bcac26b3c04 refs/remotes/origin/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/refs/heads/master	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+a647214121d6495e870ea45951499bcac26b3c04
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.git/refs/remotes/origin/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+ref: refs/remotes/origin/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/.meta	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<root>
+  <node _type="integer" _key="update">0</node>
+  <node _type="string" _key="repo_docs"></node>
+  <node _type="string" _key="repo_docs_id">https://github.com/BlackstoneEngineering/qspi-blockdevice/#a647214121d6495e870ea45951499bcac26b3c04</node>
+  <node _type="string" _key="repo_docs_ts"></node>
+  <node _type="NULL" _key="workspace_docs"></node>
+  <node _type="NULL" _key="workspace_docs_ts"></node>
+  <node _type="NULL" _key="workspace_docs_sync_id"></node>
+</root>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/QSPIFBlockDevice.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1316 @@
+
+/* mbed Microcontroller Library
+ * Copyright (c) 2016 ARM Limited
+ *
+ * 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.
+ */
+
+//#include "./mbed-os/drivers/qspi.h"
+
+#define DEVICE_QSPI 1
+
+#include "QSPIFBlockDevice.h"
+
+/* Default QSPIF Parameters */
+/****************************/
+#define QSPIF_DEFAULT_READ_SIZE  1
+#define QSPIF_DEFAULT_PROG_SIZE  1
+#define QSPIF_DEFAULT_SE_SIZE    4096
+#define QSPI_MAX_STATUS_REGISTER_SIZE 2
+#define QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC 50
+#define QSPIF_DEFAULT_TIMEOUT_MSEC    1
+
+
+/* SFDP Header Parsing */
+/***********************/
+#define QSPIF_SFDP_HEADER_SIZE 8
+#define QSPIF_PARAM_HEADER_SIZE 8
+
+/* Basic Parameters Table Parsing */
+/**********************************/
+#define SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES 64 /* 16 DWORDS */
+//READ Instruction support according to BUS Configuration
+#define QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE 2
+#define QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE 16
+#define QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE 27
+#define QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE 9
+#define QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE 11
+#define QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE 23
+#define QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE 15
+#define QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE 13
+#define QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE 40
+// Quad Enable Params
+#define QSPIF_BASIC_PARAM_TABLE_QER_BYTE 58
+#define QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE 56
+// Erase Types Params
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE 29
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_2_BYTE 31
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_3_BYTE 33
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_4_BYTE 35
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE 28
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_2_SIZE_BYTE 30
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_3_SIZE_BYTE 32
+#define QSPIF_BASIC_PARAM_ERASE_TYPE_4_SIZE_BYTE 34
+#define QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE 1
+
+// Debug Printouts
+#define QSPIF_DEBUG_ERROR     1
+#define QSPIF_DEBUG_WARNING 2
+#define QSPIF_DEBUG_INFO     3
+#define QSPIF_DEBUG_DEBUG     4
+#define QSPIF_DEBUG_TRACE     5
+// #define QSPIF_DEFAULT_DEBUG_LEVEL  QSPIF_DEBUG_INFO
+// #define QSPIF_DEFAULT_DEBUG_LEVEL  QSPIF_DEBUG_TRACE
+#define QSPIF_DEFAULT_DEBUG_LEVEL  QSPIF_DEBUG_WARNING
+
+
+enum qspif_default_instructions {
+    QSPIF_NOP  = 0x00, // No operation
+    QSPIF_PP = 0x02, // Page Program data
+    QSPIF_READ = 0x03, // Read data
+    QSPIF_SE   = 0x20, // 4KB Sector Erase
+    QSPIF_SFDP = 0x5a, // Read SFDP
+
+    QSPIF_WRSR = 0x01, // Write Status/Configuration Register
+    QSPIF_WRDI = 0x04, // Write Disable
+    QSPIF_RDSR = 0x05, // Read Status Register
+    QSPIF_WREN = 0x06, // Write Enable
+
+    QSPIF_RSTEN = 0x66, // Reset Enable
+    QSPIF_RST = 0x99, // Reset
+    QSPIF_RDID = 0x9f, // Read Manufacturer and JDEC Device ID
+};
+
+#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+
+#define QSPIF_LOG(level,...) {\
+    	if (level <= QSPIF_DEFAULT_DEBUG_LEVEL) {\
+    	  char str[256];\
+      	  sprintf(str, "\n[%s][%s:%d], ", __FILENAME__, __FUNCTION__, __LINE__);\
+            sprintf(str+strlen(str),__VA_ARGS__);\
+      	  printf(str);\
+    	}\
+    }
+
+// Mutex is used for some QSPI Driver commands that must be done sequentially with no other commands in between
+// e.g. (1)Set Write Enable, (2)Program, (3)Wait Memory Ready
+SingletonPtr<PlatformMutex> QSPIFBlockDevice::_mutex;
+
+
+/********* Public API Functions *********/
+/****************************************/
+
+QSPIFBlockDevice::QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel,
+                                   int clock_mode, int freq)
+    : _qspi(io0, io1, io2, io3, sclk, csel, clock_mode), _deviceSizeBytes(0)
+{
+    //_cs = 1;
+    is_initialized = false;
+    _minCommonEraseSize = 0;
+    _regions_count = 1;
+    _region_erase_types[0] = 0;
+
+    //Default Bus Setup 1_1_1 with 0 dummy and mode cycles
+    _inst_width = QSPI_CFG_BUS_SINGLE;
+    _address_width = QSPI_CFG_BUS_SINGLE;
+    _address_size = QSPI_CFG_ADDR_SIZE_24;
+    _alt_width = QSPI_CFG_BUS_SINGLE;
+    _alt_size = QSPI_CFG_ALT_SIZE_8;
+    _data_width = QSPI_CFG_BUS_SINGLE;
+    _dummy_and_mode_cycles = 0;
+
+    if (QSPI_STATUS_OK != _qspiSetFrequency(freq)) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Set Frequency Failed");
+    }
+}
+
+
+int QSPIFBlockDevice::init()
+{
+
+    uint8_t vendor_device_ids[4];
+    size_t data_length = 3;
+
+    _mutex->lock();
+    if (is_initialized == true) {
+        _mutex->unlock();
+        return 0;
+    }
+
+    // Soft Reset
+    if ( -1 == _resetFlashMem()) {
+        QSPIF_LOG(QSPIF_DEBUG_INFO, "ERROR: init - Unable to initialize flash memory, tests failed\n");
+        return -1;
+    } else {
+        QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: Initialize flash memory OK\n");
+    }
+
+
+
+    /* Read Manufacturer ID (1byte), and Device ID (2bytes)*/
+    int status = _qspiSendReadCommand(QSPIF_RDID, (char *)vendor_device_ids, 0x0 /*address*/, data_length);
+    if (status != QSPI_STATUS_OK) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read Vendor ID Failed");
+        return status;
+    }
+
+    switch (vendor_device_ids[0]) {
+        case 0xbf:
+            // SST devices come preset with block protection
+            // enabled for some regions, issue write disable instruction to clear
+            _setWriteEnable();
+            //_cmdwrite(0x98, 0, 0, 0x0, NULL);
+            _qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0);
+
+            break;
+    }
+
+    //Synchronize Device
+    if ( false == _isMemReady()) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - _isMemReady Failed");
+        return BD_ERROR_DEVICE_ERROR;
+    }
+
+
+    /**************************** Parse SFDP Header ***********************************/
+    uint32_t basic_table_addr = NULL;
+    size_t basic_table_size = 0;
+    uint32_t sector_map_table_addr = NULL;
+    size_t sector_map_table_size = 0;
+    if ( 0 != _sfdpParseSFDPHeaders(basic_table_addr, basic_table_size, sector_map_table_addr, sector_map_table_size)) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Parse SFDP Headers Failed");
+        return BD_ERROR_DEVICE_ERROR;
+    }
+
+
+    /**************************** Parse Basic Parameters Table ***********************************/
+    if ( 0 != _sfdpParseBasicParamTable(basic_table_addr, basic_table_size) ) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Parse Basic Param Table Failed");
+        return BD_ERROR_DEVICE_ERROR;
+    }
+
+
+    /**************************** Parse Sector Map Table ***********************************/
+    _region_size_bytes[0] =
+        _deviceSizeBytes; // If there's no region map, we have a single region sized the entire device size
+    _region_high_boundary[0] = _deviceSizeBytes - 1;
+
+    if ( (sector_map_table_addr != NULL) && (0 != sector_map_table_size) ) {
+        QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - Parsing Sector Map Table - addr: 0x%xh, Size: %d", sector_map_table_addr,
+                  sector_map_table_size);
+        if ( 0 != _sfdpParseSectorMapTable(sector_map_table_addr, sector_map_table_size) ) {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Parse Sector Map Table Failed");
+            return BD_ERROR_DEVICE_ERROR;
+        }
+    }
+
+
+    // Configure  BUS Mode to 1_1_1 for all commands other than Read
+    _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
+                         QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
+    /*// Soft Reset
+    if( -1 == _resetFlashMem()) {
+        QSPIF_LOG(QSPIF_DEBUG_INFO,"ERROR: init - Unable to initialize flash memory, tests failed\n");
+        return -1;
+    } else {
+        QSPIF_LOG(QSPIF_DEBUG_INFO,"INFO: Initialize flash memory OK\n");
+    }*/
+
+    is_initialized = true;
+    _mutex->unlock();
+
+    return 0;
+}
+
+int QSPIFBlockDevice::deinit()
+{
+    _mutex->lock();
+    if (is_initialized == false) {
+        _mutex->unlock();
+        return 0;
+    }
+    qspi_status_t status = _qspiSendGeneralCommand(QSPIF_WRDI, -1, NULL, 0, NULL, 0);
+    int result = 0;
+
+    if (status != QSPI_STATUS_OK)  {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write Disable failed");
+        result = -1;
+    }
+    is_initialized = false;
+    _mutex->unlock();
+
+    return result;
+}
+
+
+int QSPIFBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
+{
+
+
+    int status = 0;
+
+    QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO Inst: 0x%xh", _readInstruction);
+
+    _mutex->lock();
+
+    _qspiConfiureFormat(
+        _inst_width, //Bus width for Instruction phase
+        _address_width, //Bus width for Address phase
+        _address_size,
+        _alt_width, //Bus width for Alt phase
+        _alt_size,
+        _data_width, //Bus width for Data phase
+        _dummy_and_mode_cycles);
+    //_qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8);
+
+    if (QSPI_STATUS_OK != _qspiSendReadCommand(_readInstruction, buffer, addr, size)) {
+        status = -1;
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Read failed\n");
+    }
+
+    // All commands other than Read use default 1-1-1 Bus mode (Program/Erase are constrained by flash memory performance less than that of the bus)
+    _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
+                         QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 0);
+
+    _mutex->unlock();
+    return status;
+
+}
+
+
+
+
+int QSPIFBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
+{
+    qspi_status_t result = QSPI_STATUS_OK;
+    bool program_failed = false;
+    int status = 0;
+    uint32_t offset = 0;
+    uint32_t chunk = 0;
+    bd_size_t writtenBytes = 0;
+
+    while (size > 0) {
+
+        // Write on _pageSizeBytes boundaries (Default 256 bytes a page)
+        offset = addr % _pageSizeBytes;
+        chunk = (offset + size < _pageSizeBytes) ? size : (_pageSizeBytes - offset);
+        writtenBytes = chunk;
+
+        _mutex->lock();
+
+        //Send WREN
+        if (_setWriteEnable() != 0) {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write Enabe failed\n");
+            program_failed = true;
+            goto Exit_Point;
+        }
+
+        if ( false == _isMemReady()) {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready, write failed\n");
+            program_failed = true;
+            goto Exit_Point;
+        }
+
+        result = _qspiSendProgramCommand(_progInstruction, buffer, addr, &writtenBytes);
+        if ( (result != QSPI_STATUS_OK) || (chunk != writtenBytes) ) {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write failed");
+            program_failed = true;
+            goto Exit_Point;
+        }
+
+        buffer = static_cast<const uint8_t *>(buffer) + chunk;
+        addr += chunk;
+        size -= chunk;
+
+        wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC);
+
+        if ( false == _isMemReady()) {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready after write, failed\n");
+            program_failed = true;
+            goto Exit_Point;
+        }
+        _mutex->unlock();
+
+
+    }
+
+Exit_Point:
+    if (program_failed) {
+        _mutex->unlock();
+        status = -1;
+    }
+
+    return status;
+}
+
+
+int QSPIFBlockDevice::erase(bd_addr_t addr, bd_size_t inSize)
+{
+
+    int type = 0;
+    uint32_t chunk = 4096;
+    unsigned int curEraseInst = _eraseInstruction;
+    int size = (int)inSize;
+    bool erase_failed = false;
+    int status = 0;
+    // Find region of erased address
+    int region = _utilsFindAddrRegion((int)addr);
+    // Erase Types of selected region
+    uint8_t bitfield = _region_erase_types[region];
+
+
+    while (size > 0) {
+
+        // iterate to find next Largest erase type (1) supported by region, 2) smaller than size)
+        // find the matching instruction and erase size chunk for that type.
+        type = _utilsIterateNextLargestEraseType(bitfield, (int)size, (int)addr, _region_high_boundary[region]);
+        curEraseInst = _eraseTypeInstArr[type];
+        chunk = _eraseTypeSizeArr[type];
+
+        QSPIF_LOG(QSPIF_DEBUG_DEBUG, " Debug: addr: 0x%xh, size:%d, Inst: 0x%xh, chunk: %d , ",
+                  (int)addr, (int)size, curEraseInst, chunk);
+
+        _mutex->lock();
+
+        if (_setWriteEnable() != 0) {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase - Write Enable failed");
+            erase_failed = true;
+            goto Exit_Point;
+        }
+
+        if ( false == _isMemReady()) {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase Device not ready - failed");
+            erase_failed = true;
+            goto Exit_Point;
+        }
+
+        if (QSPI_STATUS_OK != _qspiSendEraseCommand(curEraseInst, addr, size) ) {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase command failed!");
+            erase_failed = true;
+            goto Exit_Point;
+        }
+
+        addr += chunk;
+        size -= chunk;
+
+        if ( (size > 0) && (addr > _region_high_boundary[region]) ) {
+            // erase crossed to next region
+            region++;
+            bitfield = _region_erase_types[region];
+        }
+        wait_ms(QSPIF_DEFAULT_TIMEOUT_MSEC);
+        if ( false == _isMemReady()) {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI After Erase Device not ready - failed\n");
+            erase_failed = true;
+            goto Exit_Point;
+        }
+        _mutex->unlock();
+
+    }
+
+
+Exit_Point:
+    if (erase_failed) {
+        _mutex->unlock();
+        status = -1;
+    }
+
+    return status;
+}
+
+
+
+bd_size_t QSPIFBlockDevice::get_read_size() const
+{
+    return QSPIF_DEFAULT_READ_SIZE;
+}
+
+bd_size_t QSPIFBlockDevice::get_program_size() const
+{
+    return QSPIF_DEFAULT_PROG_SIZE;
+}
+
+bd_size_t QSPIFBlockDevice::get_erase_size() const
+{
+    return _minCommonEraseSize;
+}
+
+
+// Find minimal erase size supported by address region
+bd_size_t QSPIFBlockDevice::get_erase_size(bd_addr_t addr)
+{
+    // Find region of current address
+    int region = _utilsFindAddrRegion((int)addr);
+
+    int minRegionEraseSize = _minCommonEraseSize;
+    int8_t type_mask = 0x01;
+    int i_ind = 0;
+
+    if (region != -1) {
+        type_mask = 0x01;
+
+        for (i_ind = 0; i_ind < 4; i_ind++) {
+            // loop through erase types supported by region
+            if (_region_erase_types[region] & type_mask) {
+
+                minRegionEraseSize = _eraseTypeSizeArr[i_ind];
+                break;
+            }
+            type_mask = type_mask << 1;
+        }
+
+        if (i_ind == 4) {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: no erase type was found for region addr");
+        }
+    }
+
+    return (bd_size_t)minRegionEraseSize;
+
+}
+
+bd_size_t QSPIFBlockDevice::size() const
+{
+    return _deviceSizeBytes;
+}
+
+
+/*********************************************************/
+/********** SFDP Parsing and Detection Functions *********/
+/*********************************************************/
+
+int QSPIFBlockDevice::_sfdpParseSectorMapTable(uint32_t sector_map_table_addr, size_t sector_map_table_size)
+{
+    uint8_t sector_map_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
+    uint32_t tmpRegionSize = 0;
+    int i_ind = 0;
+    int prevBoundary = 0;
+    // Default set to all type bits 1-4 are common
+    _minCommonEraseType = 0x0F;
+
+    qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sector_map_table, sector_map_table_addr /*address*/,
+                           sector_map_table_size);
+    if (status != QSPI_STATUS_OK) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read SFDP First Table Failed");
+        return -1;
+    }
+
+    //QSPIF_LOG(QSPIF_DEBUG_DEBUG,\nDEBUG: "Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n",sector_map_table[0],
+    //		sector_map_table[1],
+    //		sector_map_table[2],
+    //		sector_map_table[3],
+    //		sector_map_table[4],
+    //		sector_map_table[5],
+    //		sector_map_table[6],
+    //		sector_map_table[7], sector_map_table[56], sector_map_table[57], sector_map_table[58], sector_map_table[59], sector_map_table[52]);
+
+    // Currently we support only Single Map Descriptor
+    if (! ( (sector_map_table[0] & 0x3) == 0x03 ) && (sector_map_table[1]  == 0x0) ) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Sector Map - Supporting Only Single! Map Descriptor (not map commands)");
+        return -1;
+    }
+
+    _regions_count = sector_map_table[2] + 1;
+    if (_regions_count > QSPIF_MAX_REGIONS) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Supporting up to %d regions, current setup to %d regions - fail",
+                  QSPIF_MAX_REGIONS, _regions_count);
+        return -1;
+    }
+
+    // Loop through Regions and set for each one: size, supported erase types, high boundary offset
+    // Calculate minimum Common Erase Type for all Regions
+    for (i_ind = 0; i_ind < _regions_count; i_ind++) {
+        tmpRegionSize = ((*((uint32_t *)&sector_map_table[(i_ind + 1) * 4])) >> 8) & 0x00FFFFFF; // bits 9-32
+        _region_size_bytes[i_ind] = (tmpRegionSize + 1) * 256; // Region size is 0 based multiple of 256 bytes;
+        _region_erase_types[i_ind] = sector_map_table[(i_ind + 1) * 4] & 0x0F; // bits 1-4
+        _minCommonEraseType &= _region_erase_types[i_ind];
+        _region_high_boundary[i_ind] = (_region_size_bytes[i_ind] - 1) + prevBoundary;
+        prevBoundary = _region_high_boundary[i_ind] + 1;
+    }
+
+    // Calc minimum Common Erase Size from _minCommonEraseType
+    uint8_t type_mask = 0x01;
+    for (i_ind = 0; i_ind < 4; i_ind++) {
+        if (_minCommonEraseType & type_mask) {
+            _minCommonEraseType = i_ind;
+            _minCommonEraseSize = _eraseTypeSizeArr[i_ind];
+            break;
+        }
+        type_mask = type_mask << 1;
+    }
+
+    if (i_ind == 4) {
+        // No common erase type was found between regions
+        _minCommonEraseType = 0;
+        _minCommonEraseSize = -1;
+    }
+
+    return 0;
+}
+
+
+int QSPIFBlockDevice::_sfdpParseBasicParamTable(uint32_t basic_table_addr, size_t basic_table_size)
+{
+    uint8_t param_table[SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES]; /* Up To 16 DWORDS = 64 Bytes */
+
+    qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_table, basic_table_addr /*address*/,
+                           basic_table_size);
+    if (status != QSPI_STATUS_OK) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read SFDP First Table Failed, Status %d",status);
+        return -1;
+    }
+
+    QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Read table: %x %x %x %x %x %x %x %x %x[56] %x[57] %x[58] %x[59] %x[52]\n",
+              param_table[0],
+              param_table[1],
+              param_table[2],
+              param_table[3],
+              param_table[4],
+              param_table[5],
+              param_table[6],
+              param_table[7], param_table[56], param_table[57], param_table[58], param_table[59], param_table[52]);
+
+
+    // Check address size, currently only supports 3byte addresses
+    if ((param_table[2] & 0x4) != 0 || (param_table[7] & 0x80) != 0) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - verify 3byte addressing Failed");
+        return -1;
+    }
+
+    // Get device density (stored in bits - 1)
+    uint32_t density_bits = (
+                                (param_table[7] << 24) |
+                                (param_table[6] << 16) |
+                                (param_table[5] << 8 ) |
+                                param_table[4] );
+    _deviceSizeBytes = (density_bits + 1) / 8;
+
+    // Set Default read/program/erase Instructions
+    _readInstruction = QSPIF_READ;
+    _progInstruction = QSPIF_PP;
+    _eraseInstruction = QSPIF_SE;
+
+    // Set Page Size (QSPI write must be done on Page limits)
+    _pageSizeBytes = _sfdpDetectPageSize(param_table);
+
+    // Detect and Set Erase Types
+    bool shouldSetQuadEnable = false;
+    bool isQPIMode = false;
+    _sfdpDetectEraseTypesInstAndSize(param_table, _erase4KInst, _eraseTypeInstArr, _eraseTypeSizeArr);
+    _eraseInstruction = _erase4KInst;
+
+
+    // Detect and Set fastest Bus mode (default 1-1-1)
+    _sfdpDetectBestBusReadMode(param_table, shouldSetQuadEnable, isQPIMode, _readInstruction);
+
+    if (true == shouldSetQuadEnable) {
+        // Set Quad Enable and QPI Bus modes if Supported
+        QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - Setting Quad Enable");
+        _sfdpSetQuadEnabled(param_table);
+        if (true == isQPIMode) {
+            QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - Setting QPI mode");
+            _sfdpSetQPIEnabled(param_table);
+        }
+    }
+    return 0;
+}
+
+int QSPIFBlockDevice::_sfdpParseSFDPHeaders(uint32_t& basic_table_addr, size_t& basic_table_size,
+        uint32_t& sector_map_table_addr, size_t& sector_map_table_size)
+{
+    uint8_t sfdp_header[QSPIF_SFDP_HEADER_SIZE];
+    uint8_t param_header[QSPIF_PARAM_HEADER_SIZE];
+    size_t data_length = QSPIF_SFDP_HEADER_SIZE;
+    bd_addr_t addr = 0x0;
+
+    // Set 1-1-1 bus mode for SFDP header parsing
+    _qspiConfiureFormat( QSPI_CFG_BUS_SINGLE, QSPI_CFG_BUS_SINGLE, QSPI_CFG_ADDR_SIZE_24, QSPI_CFG_BUS_SINGLE,
+                         QSPI_CFG_ALT_SIZE_8, QSPI_CFG_BUS_SINGLE, 8);
+
+    qspi_status_t status = _qspiSendReadCommand(QSPIF_SFDP, (char *)sfdp_header, addr /*address*/, data_length);
+    if (status != QSPI_STATUS_OK) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read SFDP Failed");
+        return -1;
+    }
+
+
+    QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG11: Read SFDP Header: %x %x %x %x %x %x %x %x\n", sfdp_header[0],
+              sfdp_header[1],
+              sfdp_header[2],
+              sfdp_header[3],
+              sfdp_header[4],
+              sfdp_header[5],
+              sfdp_header[6],
+              sfdp_header[7]);
+
+
+    // Verify SFDP signature for sanity
+    // Also check that major/minor version is acceptable
+    if (!(memcmp(&sfdp_header[0], "SFDP", 4) == 0 && sfdp_header[5] == 1)) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - _verify SFDP signature and version Failed");
+        return -1;
+    } else {
+        QSPIF_LOG(QSPIF_DEBUG_INFO, "INFO: init - verified SFDP Signature and version Successfully");
+    }
+
+    // Discover Number of Parameter Headers
+    int number_of_param_headers = (int)(sfdp_header[6]) + 1;
+    QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: number of Param Headers: %d", number_of_param_headers);
+
+
+    addr += QSPIF_SFDP_HEADER_SIZE;
+    data_length = QSPIF_PARAM_HEADER_SIZE;
+
+    // Loop over Param Headers and parse them (currently supported Basic Param Table and Sector Region Map Table)
+    for (int i_ind = 0; i_ind < number_of_param_headers; i_ind++) {
+
+        status = _qspiSendReadCommand(QSPIF_SFDP, (char *)param_header, addr, data_length);
+        if (status != QSPI_STATUS_OK) {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: init - Read Param Table %d Failed", i_ind + 1);
+            return -1;
+        }
+        // The SFDP spec indicates the standard table is always at offset 0
+        // in the parameter headers, we check just to be safe
+        if (param_header[2] != 1) {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Param Table %d - Major Version should be 1!", i_ind + 1);
+            return -1;
+        }
+
+        if ((param_header[0] == 0) && (param_header[7] == 0xFF)) {
+            // Found Basic Params Table: LSB=0x00, MSB=0xFF
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Found Basic Param Table at Table: %d", i_ind + 1);
+            basic_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) );
+            // Supporting up to 64 Bytes Table (16 DWORDS)
+            basic_table_size = ((param_header[3] * 4) < SFDP_DEFAULT_BASIC_PARAMS_TABLE_SIZE_BYTES) ? (param_header[11] * 4) : 64;
+
+        } else if ((param_header[0] == 81) && (param_header[7] == 0xFF)) {
+            // Found Sector Map Table: LSB=0x81, MSB=0xFF
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Found Sector Map Table at Table: %d", i_ind + 1);
+            sector_map_table_addr = ( (param_header[6] << 16) | (param_header[5] << 8) | (param_header[4]) );
+
+            sector_map_table_size = param_header[3] * 4;
+
+        }
+        addr += QSPIF_PARAM_HEADER_SIZE;
+
+    }
+    return 0;
+}
+
+
+
+int QSPIFBlockDevice::_sfdpSetQPIEnabled(uint8_t *basicParamTablePtr)
+{
+    uint8_t config_reg[1];
+
+    // QPI 4-4-4 Enable Procedure is specified in 5 Bits
+    uint8_t en_seq_444_value = ( ((basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE] & 0xF0) >> 4) | ((
+                                     basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_MODE_EN_SEQ_BYTE + 1] & 0x01) << 4 ));
+
+    switch (en_seq_444_value) {
+        case 1:
+        case 2:
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - send command 38h");
+            /*if (_setWriteEnable() != 0) {
+            	printf("ERROR: Write Enabe failed\n");
+            	return -1;
+            }
+            if( false == _isMemReady()) {
+            	printf("ERROR: Device not ready, write failed\n");
+            	return -1;
+            }*/
+
+            _qspiSendGeneralCommand(0x38, -1, NULL, 0, NULL, 0);
+            /*wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
+            if( false == _isMemReady()) {
+            	printf("ERROR: Device not ready after write, failed\n");
+            	return -1;
+            }*/
+
+
+            break;
+
+        case 4:
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - send command 35h");
+            _qspiSendGeneralCommand(0x35, -1, NULL, 0, NULL, 0);
+            break;
+
+        case 8:
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - set config bit 6 and send command 71h");
+            _qspiSendGeneralCommand(0x65, 0x800003, NULL, 0, (char *)config_reg, 1);
+            config_reg[1] |= 0x40; //Set Bit 6
+            _qspiSendGeneralCommand(0x71, 0x800003, NULL, 0, (char *)config_reg, 1);
+            break;
+
+        case 16:
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQPIEnabled - reset config bits 0-7 and send command 61h");
+            _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1);
+            config_reg[1] &= 0x7F; //Reset Bit 7 of CR
+
+
+
+
+            /*
+            if (_setWriteEnable() != 0) {
+            	printf("ERROR: Write Enabe failed\n");
+            	return -1;
+            }
+            if( false == _isMemReady()) {
+            	printf("ERROR: Device not ready, write failed\n");
+            	return -1;
+            }*/
+
+            _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1);
+
+
+            /* wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
+            if( false == _isMemReady()) {
+            	printf("ERROR: Device not ready after write, failed\n");
+            	return -1;
+            }
+
+
+
+            _qspiSendGeneralCommand(0x65, -1, NULL, 0, (char *)config_reg, 1);
+
+            if (_setWriteEnable() != 0) {
+            	printf("ERROR: Write Enabe failed\n");
+            	return -1;
+            }
+            if( false == _isMemReady()) {
+            	printf("ERROR: Device not ready, write failed\n");
+            	return -1;
+            }
+            config_reg[1] = 0x00; //Reset Bits 0-7
+            _qspiSendGeneralCommand(0x61, -1, NULL, 0, (char *)config_reg, 1);
+            wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);*/
+            /*	if( false == _isMemReady()) {
+            	printf("ERROR: Device not ready after write, failed\n");
+            	return -1;
+            }*/
+
+            break;
+
+        default:
+            QSPIF_LOG(QSPIF_DEBUG_WARNING, "WARNING: _setQPIEnabled - Unsuported En Seq 444 configuration");
+            break;
+
+
+    }
+
+    return 0;
+}
+
+
+
+int QSPIFBlockDevice::_sfdpSetQuadEnabled(uint8_t *basicParamTablePtr)
+{
+
+    int sr_read_size = QSPI_MAX_STATUS_REGISTER_SIZE;
+    int sr_write_size = QSPI_MAX_STATUS_REGISTER_SIZE;
+
+    int status_reg_setup[QSPI_MAX_STATUS_REGISTER_SIZE];
+    uint8_t status_reg[QSPI_MAX_STATUS_REGISTER_SIZE];
+    unsigned int writeRegisterInst = QSPIF_WRSR;
+    unsigned int readRegisterInst = QSPIF_RDSR;
+
+    uint8_t qer_value = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QER_BYTE] & 0x70) >> 4;
+
+
+
+    switch (qer_value) {
+        case 0:
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Device Does not Have a QE Bit, continue based on Read Inst");
+            return 0;
+
+        case 1:
+        case 4:
+            status_reg_setup[0] = 0;
+            status_reg_setup[1] = 0x02;
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 1 of Status Reg 2");
+            break;
+
+        case 2:
+            status_reg_setup[0] = 0x40;
+            status_reg_setup[1] = 0;
+            sr_write_size = 1;
+            sr_read_size = 1;
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 6 of Status Reg 1");
+            break;
+
+        case 3:
+            status_reg_setup[0] = 0x80; // Bit 7 of Status Reg 1
+            status_reg_setup[1] = 0;
+            sr_write_size = 1;
+            sr_read_size = 1;
+            writeRegisterInst = 0x3E;
+            readRegisterInst = 0x3F;
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 7 of Status Reg 1");
+            break;
+        case 5:
+            status_reg_setup[0] = 0;
+            status_reg_setup[1] = 0x02;
+            readRegisterInst = 0x35;
+            sr_read_size = 1;
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Setting QE Bit, Bit 1 of Status Reg 2 -special read command");
+            break;
+        default:
+            QSPIF_LOG(QSPIF_DEBUG_WARNING, "WARNING: _setQuadEnable - Unsuported QER configuration");
+            break;
+
+
+    }
+
+    // Read Status Register
+    if (QSPI_STATUS_OK == _qspiSendGeneralCommand(readRegisterInst, -1, NULL, 0, (char *)status_reg,
+            sr_read_size) ) {  // store received values in status_value
+        QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]);
+    } else {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed");
+        return -1;
+    }
+
+    // Set Bits for Quad Enable
+    status_reg[0] |= status_reg_setup[0];
+    status_reg[1] |= status_reg_setup[1];
+
+
+    // Write new Status Register Setup
+    if (_setWriteEnable() != 0) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Write Enabe failed\n");
+        return -1;
+    }
+
+    if ( false == _isMemReady()) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready, write failed");
+        return -1;
+    }
+
+    if (QSPI_STATUS_OK == _qspiSendGeneralCommand(writeRegisterInst, -1, (char *)status_reg, sr_write_size, NULL,
+            0) ) {  // Write QE to status_register
+        QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _setQuadEnable - Writing Status Register Success: value = 0x%x",
+                  (int)status_reg[0]);
+    } else {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: _setQuadEnable - Writing Status Register failed");
+        return -1;
+    }
+
+    wait_ms(QSPI_STATUS_REGISTER_WRITE_TIMEOUT_MSEC);
+
+    if ( false == _isMemReady()) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Device not ready after write, failed");
+        return -1;
+    }
+
+
+    // For Debug
+    memset(status_reg, 0, QSPI_MAX_STATUS_REGISTER_SIZE);
+    if (QSPI_STATUS_OK == _qspiSendGeneralCommand(readRegisterInst, -1, NULL, 0, (char *)status_reg,
+            sr_read_size) ) {  // store received values in status_value
+        QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_reg[0]);
+    } else {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed");
+        return -1;
+    }
+
+
+    return 0;//((status_reg[0] & QSPI_STATUS_BIT_QE) != 0 ? 0 : -1);
+}
+
+
+int QSPIFBlockDevice::_sfdpDetectPageSize(uint8_t *basicParamTablePtr)
+{
+    int page2PowerSize = ( (int)basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_PAGE_SIZE_BYTE]) >> 4;
+    int pageSize = _utilsMathPower(2, page2PowerSize);
+    QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: _detectPageSize - Page Size: %d", pageSize);
+    return pageSize;
+}
+
+
+
+int QSPIFBlockDevice::_sfdpDetectEraseTypesInstAndSize(uint8_t *basicParamTablePtr, unsigned int& erase4KInst,
+        unsigned int *eraseTypeInstArr, unsigned int *eraseTypeSizeArr)
+{
+    erase4KInst = 0xff;
+    bool found4KEraseType = false;
+    uint8_t bitfield = 0x01;
+
+    // Erase 4K Inst is taken either from param table legacy 4K erase or superseded by erase Instruction for type of size 4K
+    erase4KInst = basicParamTablePtr[QSPIF_BASIC_PARAM_4K_ERASE_TYPE_BYTE];
+
+    // Loop Erase Types 1-4
+    for (int i_ind = 0; i_ind < 4; i_ind++) {
+        eraseTypeInstArr[i_ind] = 0xff; //0xFF default for unsupported type
+        eraseTypeSizeArr[i_ind] = _utilsMathPower(2, basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_SIZE_BYTE + 2 * i_ind]);
+        if (eraseTypeSizeArr[i_ind] > 1) {
+            // if size==1 type is not supported
+            eraseTypeInstArr[i_ind] = basicParamTablePtr[QSPIF_BASIC_PARAM_ERASE_TYPE_1_BYTE + 2 * i_ind];
+
+            if ((eraseTypeSizeArr[i_ind] < _minCommonEraseSize) || (_minCommonEraseSize == 0) ) {
+                //Set default minimal common erase for singal region
+                _minCommonEraseSize = eraseTypeSizeArr[i_ind];
+            }
+
+            if (eraseTypeSizeArr[i_ind] == 4096) {
+                found4KEraseType = true;
+                if (erase4KInst != eraseTypeInstArr[i_ind]) {
+                    //Verify 4KErase Type is identical to Legacy 4K erase type specified in Byte 1 of Param Table
+                    erase4KInst = eraseTypeInstArr[i_ind];
+                    QSPIF_LOG(QSPIF_DEBUG_WARNING,
+                              "WARNING: _detectEraseTypesInstAndSize - Default 4K erase Inst is different than erase type Inst for 4K");
+
+                }
+            }
+            _region_erase_types[0] |= bitfield; // If there's no region map, set region "0" types as defualt;
+        }
+
+        QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Erase Type %d - Inst: 0x%xh, Size: %d", (i_ind + 1), eraseTypeInstArr[i_ind],
+                  eraseTypeSizeArr[i_ind]);
+        bitfield = bitfield << 1;
+    }
+
+    if (false == found4KEraseType) {
+        QSPIF_LOG(QSPIF_DEBUG_WARNING, "WARNING: Couldn't find Erase Type for 4KB size");
+    }
+    return 0;
+}
+
+
+int QSPIFBlockDevice::_sfdpDetectBestBusReadMode(uint8_t *basicParamTablePtr, bool& setQuadEnable, bool& isQPIMode,
+        unsigned int& readInst)
+{
+
+    bool isDone = false;
+
+    setQuadEnable = false;
+    isQPIMode = false;
+    int dummyCycles = 0;
+    uint8_t examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE];
+
+    do { // compound statement is the loop body
+
+
+
+        if (examinedByte & 0x10) {
+            // QPI 4-4-4 Supported
+            readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE];
+            setQuadEnable = true;
+            isQPIMode = true;
+            _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE - 1] >> 5)
+                                     + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_444_READ_INST_BYTE - 1] & 0x1F);
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 4-4-4, Instruction: 0x%xh", _readInstruction);
+            //_inst_width = QSPI_CFG_BUS_QUAD;
+            _address_width = QSPI_CFG_BUS_QUAD;
+            _data_width = QSPI_CFG_BUS_QUAD;
+
+            break;
+        }
+
+
+        examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE];
+        if (examinedByte & 0x40) {
+            //  Fast Read 1-4-4 Supported
+            readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE];
+            setQuadEnable = true;
+            // dummy cycles + mode cycles = Dummy Cycles
+            _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE - 1] >> 5)
+                                     + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_144_READ_INST_BYTE - 1] & 0x1F);
+            _address_width = QSPI_CFG_BUS_QUAD;
+            _data_width = QSPI_CFG_BUS_QUAD;
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-4-4, Instruction: 0x%xh", _readInstruction);
+            break;
+        }
+        if (examinedByte & 0x80) {
+            //  Fast Read 1-1-4 Supported
+            readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE];
+            setQuadEnable = true;
+            _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE - 1] >> 5)
+                                     + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_114_READ_INST_BYTE - 1] & 0x1F);
+            _data_width = QSPI_CFG_BUS_QUAD;
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-1-4, Instruction: 0x%xh", _readInstruction);
+            break;
+        }
+        examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_QPI_READ_SUPPOR_BYTE];
+        if (examinedByte & 0x01) {
+            //  Fast Read 2-2-2 Supported
+            readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE];
+            _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] >> 5)
+                                     + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_222_READ_INST_BYTE - 1] & 0x1F);
+            _address_width = QSPI_CFG_BUS_DUAL;
+            _data_width = QSPI_CFG_BUS_DUAL;
+            QSPIF_LOG(QSPIF_DEBUG_INFO, "/nINFO: Read Bus Mode set to 2-2-2, Instruction: 0x%xh", _readInstruction);
+            break;
+        }
+
+        examinedByte = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_FAST_READ_SUPPORT_BYTE];
+        if (examinedByte & 0x20) {
+            //  Fast Read 1-2-2 Supported
+            readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE];
+            _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE - 1] >> 5)
+                                     + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_122_READ_INST_BYTE - 1] & 0x1F);
+            _address_width = QSPI_CFG_BUS_DUAL;
+            _data_width = QSPI_CFG_BUS_DUAL;
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-2-2, Instruction: 0x%xh", _readInstruction);
+            break;
+        }
+        if (examinedByte & 0x01) {
+            // Fast Read 1-1-2 Supported
+            readInst = basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE];
+            _dummy_and_mode_cycles = (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE - 1] >> 5)
+                                     + (basicParamTablePtr[QSPIF_BASIC_PARAM_TABLE_112_READ_INST_BYTE - 1] & 0x1F);
+            _data_width = QSPI_CFG_BUS_DUAL;
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-1-2, Instruction: 0x%xh", _readInstruction);
+            break;
+        }
+        QSPIF_LOG(QSPIF_DEBUG_DEBUG, "/nDEBUG: Read Bus Mode set to 1-1-1, Instruction: 0x%xh", _readInstruction);
+        isDone = true;
+    } while (isDone == false);
+
+    return 0;
+}
+
+
+int QSPIFBlockDevice::_resetFlashMem()
+{
+    int status = 0;
+    char status_value[2] = {0};
+    QSPIF_LOG(QSPIF_DEBUG_ERROR, "INFO: _resetFlashMem:\n");
+    //Read the Status Register from device
+    if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RDSR, -1, NULL, 0, status_value,
+            1) ) {  // store received values in status_value
+        QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Reading Status Register Success: value = 0x%x\n", (int)status_value[0]);
+    } else {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed\n");
+        status = -1;
+    }
+
+    if (0 == status) {
+        //Send Reset Enable
+        if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RSTEN, -1, NULL, 0, NULL,
+                0) ) {   // store received values in status_value
+            QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Sending RSTEN Success\n");
+        } else {
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Sending RSTEN failed\n");
+            status = -1;
+        }
+
+
+        if (0 == status) {
+            //Send Reset
+            if (QSPI_STATUS_OK == _qspiSendGeneralCommand(QSPIF_RST, -1, NULL, 0, NULL,
+                    0)) {   // store received values in status_value
+                QSPIF_LOG(QSPIF_DEBUG_DEBUG, "DEBUG: Sending RST Success\n");
+            } else {
+                QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Sending RST failed\n");
+                status = -1;
+            }
+
+            _isMemReady();
+        }
+    }
+
+    return status;
+}
+
+
+bool QSPIFBlockDevice::_isMemReady()
+{
+    char status_value[2];
+    int retries = 0;
+    bool memReady = true;
+
+    do {
+        retries++;
+        //Read the Status Register from device
+        if (QSPI_STATUS_OK != _qspiSendGeneralCommand(QSPIF_RDSR, -1, NULL, 0, status_value,
+                2)) {   // store received values in status_value
+            QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Reading Status Register failed\n");
+        }
+    } while ( (status_value[0] & 0x1) != 0 && retries < 10000 );
+
+    if ((status_value[0] & 0x1) != 0) {
+        QSPIF_LOG(QSPIF_DEBUG_DEBUG, "ERROR: _isMemReady FALSE\n");
+        memReady = false;
+    }
+    return memReady;
+}
+
+
+int QSPIFBlockDevice::_setWriteEnable()
+{
+    int status = 0;
+    if (QSPI_STATUS_OK !=  _qspiSendGeneralCommand(QSPIF_WREN, -1, NULL, 0, NULL, 0)) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR:Sending WREN command FAILED\n");
+        status = -1;
+    }
+    return status;
+}
+
+
+
+/*********************************************/
+/************* Utility Functions *************/
+/*********************************************/
+int QSPIFBlockDevice::_utilsMathPower(int base, int exp)
+{
+    int result = 1;
+    while (exp) {
+        result *= base;
+        exp--;
+    }
+    return result;
+}
+
+
+int QSPIFBlockDevice::_utilsFindAddrRegion(int offset)
+{
+    if ((offset > (int)_deviceSizeBytes) || (_regions_count == 0)) {
+        return -1;
+    }
+
+    if (_regions_count == 1) {
+        return 0;
+    }
+
+    for (int i_ind = _regions_count - 2; i_ind >= 0; i_ind--) {
+
+        if (offset > _region_high_boundary[i_ind]) {
+            return (i_ind + 1);
+        }
+    }
+    return -1;
+
+}
+
+
+int QSPIFBlockDevice::_utilsIterateNextLargestEraseType(uint8_t& bitfield, int size, int offset, int boundry)
+{
+    uint8_t type_mask = 0x08;
+    int i_ind  = 0;
+    int largestEraseType = 0;
+    for (i_ind = 3; i_ind >= 0; i_ind--) {
+        if (bitfield & type_mask) {
+            largestEraseType = i_ind;
+            if ( (size > _eraseTypeSizeArr[largestEraseType]) &&
+                    ((boundry - offset) > _eraseTypeSizeArr[largestEraseType]) ) {
+                break;
+            } else {
+                bitfield &= ~type_mask;
+            }
+        }
+        type_mask = type_mask >> 1;
+    }
+
+    if (i_ind == 4) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: no erase type was found for current region addr");
+    }
+    return largestEraseType;
+
+}
+
+
+/***************************************************/
+/*********** QSPI Driver API Functions *************/
+/***************************************************/
+
+qspi_status_t QSPIFBlockDevice::_qspiSetFrequency(int freq)
+{
+    return _qspi.set_frequency(freq);
+}
+
+
+qspi_status_t QSPIFBlockDevice::_qspiSendReadCommand(unsigned int readInst, void *buffer, bd_addr_t addr,
+        bd_size_t size)
+{
+    // Check the address and size fit onto the chip.
+
+    /* OFR_DBG */
+    //MBED_ASSERT(is_valid_read(addr, size));
+
+    size_t bufLen = size;
+
+    if (_qspi.read( readInst, -1, (unsigned int )addr, (char *)buffer, &bufLen) != QSPI_STATUS_OK ) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: Read failed");
+        return QSPI_STATUS_ERROR;
+    }
+
+    return QSPI_STATUS_OK;
+
+}
+
+
+qspi_status_t QSPIFBlockDevice::_qspiSendProgramCommand(unsigned int progInst, const void *buffer, bd_addr_t addr,
+        bd_size_t *size)
+{
+    // Check the address and size fit onto the chip.
+    //MBED_ASSERT(is_valid_program(addr, (*size)));
+    qspi_status_t result = QSPI_STATUS_OK;
+
+    result = _qspi.write( progInst, -1, addr/*(((unsigned int)addr) & 0x00FFFF00)*/, (char *)buffer, (size_t *)size);
+    if (result != QSPI_STATUS_OK) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Write failed");
+    }
+
+    return result;
+}
+
+
+qspi_status_t QSPIFBlockDevice::_qspiSendEraseCommand(unsigned int eraseInst, bd_addr_t addr, bd_size_t size)
+{
+    // Check the address and size fit onto the chip.
+    //MBED_ASSERT(is_valid_erase(addr, size));
+
+    qspi_status_t result = QSPI_STATUS_OK;
+
+    result = _qspi.command_transfer(eraseInst, // command to send
+                                    (((int)addr) & 0x00FFF000), // Align addr to 4096
+                                    NULL,                 // do not transmit
+                                    0,              // do not transmit
+                                    NULL,                 // just receive two bytes of data
+                                    0); // store received values in status_value
+    if (QSPI_STATUS_OK != result) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR: QSPI Erase failed");
+    }
+
+    return result;
+
+}
+
+
+qspi_status_t QSPIFBlockDevice::_qspiSendGeneralCommand(unsigned int instruction, bd_addr_t addr, const char *tx_buffer,
+        size_t tx_length, const char *rx_buffer, size_t rx_length)
+{
+
+
+    qspi_status_t status = _qspi.command_transfer(instruction, (int)addr, tx_buffer, tx_length, rx_buffer, rx_length);
+
+    if (QSPI_STATUS_OK != status) {
+        QSPIF_LOG(QSPIF_DEBUG_ERROR, "ERROR:Sending Generic command: %x", instruction);
+    }
+
+    return status;
+}
+
+
+qspi_status_t QSPIFBlockDevice::_qspiConfiureFormat(qspi_bus_width_t inst_width, qspi_bus_width_t address_width,
+        qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width,
+        int dummy_cycles)
+{
+    _qspi.configure_format( inst_width, address_width, address_size, alt_width, alt_size, data_width, dummy_cycles);
+
+    return QSPI_STATUS_OK;
+}
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/QSPIFBlockDevice.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,232 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2016 ARM Limited
+ *
+ * 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.
+ */
+#ifndef MBED_QSPIF_BLOCK_DEVICE_H
+#define MBED_QSPIF_BLOCK_DEVICE_H
+
+
+#define DEVICE_QSPI 1
+
+#include <mbed.h>
+#include "BlockDevice.h"
+#include "QSPI.h"
+
+#define QSPIF_MAX_REGIONS	4
+
+class QSPIFBlockDevice : public BlockDevice {
+public:
+    /** Creates a QSPIFBlockDevice on a SPI bus specified by pins
+     *
+     *  @param mosi     SPI master out, slave in pin
+     *  @param miso     SPI master in, slave out pin
+     *  @param sclk     SPI clock pin
+     *  @param csel     SPI chip select pin
+     *  @param freq     Clock speed of the SPI bus (defaults to 40MHz)
+     */
+
+    /** Creates a QSPIFBlockDevice on an SPI bus specified by pins
+     *
+     *  io0-io3 is used to specify the Pins used for Quad SPI mode
+     *
+     *  @param io0 1st IO pin used for sending/receiving data during data phase of a transaction
+     *  @param io1 2nd IO pin used for sending/receiving data during data phase of a transaction
+     *  @param io2 3rd IO pin used for sending/receiving data during data phase of a transaction
+     *  @param io3 4th IO pin used for sending/receiving data during data phase of a transaction
+     *  @param sclk QSPI Clock pin
+     *  @param csel QSPI chip select pin
+     *  @param clock_mode specifies the SPI Clock Polarity mode(Mode=0 uses CPOL=0, CPHA=0, Mode=1 uses CPOL=1, CPHA=1)
+     *         default value = 0
+     *  @param freq Clock frequency of the SPI bus (defaults to 40MHz)
+     *
+     */
+    QSPIFBlockDevice(PinName io0, PinName io1, PinName io2, PinName io3, PinName sclk, PinName csel, int clock_mode,
+                     int freq = 40000000);
+
+    /** Initialize a block device
+     *
+     *  @return         0 on success or a negative error code on failure
+     */
+    virtual int init();
+
+    /** Deinitialize a block device
+     *
+     *  @return         0 on success or a negative error code on failure
+     */
+    virtual int deinit();
+
+    /** Read blocks from a block device
+     *
+     *  @param buffer   Buffer to write blocks to
+     *  @param addr     Address of block to begin reading from
+     *  @param size     Size to read in bytes, must be a multiple of read block size
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
+
+    /** Program blocks to a block device
+     *
+     *  The blocks must have been erased prior to being programmed
+     *
+     *  @param buffer   Buffer of data to write to blocks
+     *  @param addr     Address of block to begin writing to
+     *  @param size     Size to write in bytes, must be a multiple of program block size
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
+
+    /** Erase blocks on a block device
+     *
+     *  The state of an erased block is undefined until it has been programmed
+     *
+     *  @param addr     Address of block to begin erasing
+     *  @param size     Size to erase in bytes, must be a multiple of erase block size
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int erase(bd_addr_t addr, bd_size_t size);
+
+    /** Get the size of a readable block
+     *
+     *  @return         Size of a readable block in bytes
+     */
+    virtual bd_size_t get_read_size() const;
+
+    /** Get the size of a programable block
+     *
+     *  @return         Size of a programable block in bytes
+     *  @note Must be a multiple of the read size
+     */
+    virtual bd_size_t get_program_size() const;
+
+    /** Get the size of a eraseable block
+     *
+     *  @return         Size of a eraseable block in bytes
+     *  @note Must be a multiple of the program size
+     */
+    virtual bd_size_t get_erase_size() const;
+
+    /** Get the size of a eraseable block
+     *
+     *  @param addr     Address of block queried for erase sector size
+     *  @return         Size of a eraseable sector in bytes
+     *  @note Must be a multiple of the program size
+     */
+    bd_size_t get_erase_size(bd_addr_t addr);
+
+    /** Get the total size of the underlying device
+     *
+     *  @return         Size of the underlying device in bytes
+     */
+    virtual bd_size_t size() const;
+
+private:
+    // Internal functions
+
+    /********************************/
+    /*   Calls to QSPI Driver APIs  */
+    /********************************/
+    // Send Program => Write command to Driver
+    qspi_status_t _qspiSendProgramCommand(unsigned int progInstruction, const void *buffer, bd_addr_t addr,
+                                          bd_size_t *size);
+
+    // Send Read command to Driver
+    qspi_status_t _qspiSendReadCommand(unsigned int readInstruction, void *buffer, bd_addr_t addr, bd_size_t size);
+
+    // Send Erase => command_transfer command to Driver
+    qspi_status_t _qspiSendEraseCommand(unsigned int eraseInstruction, bd_addr_t addr, bd_size_t size);
+
+    // Send Generic command_transfer command to Driver
+    qspi_status_t _qspiSendGeneralCommand(unsigned int instructionint, bd_addr_t addr, const char *tx_buffer,
+                                          size_t tx_length, const char *rx_buffer, size_t rx_length);
+
+    // Send Bus configure_format command to Driver
+    qspi_status_t _qspiConfiureFormat(qspi_bus_width_t inst_width, qspi_bus_width_t address_width,
+                                      qspi_address_size_t address_size, qspi_bus_width_t alt_width, qspi_alt_size_t alt_size, qspi_bus_width_t data_width,
+                                      int dummy_cycles);
+
+    // Send set_frequency command to Driver
+    qspi_status_t _qspiSetFrequency(int freq);
+    /********************************/
+
+
+    // Verify registers and Reset Flash Memory
+    int _resetFlashMem();
+
+    // Configure Write Enable in Status Register
+    int _setWriteEnable();
+
+    // Wait on status register until write not-in-progress
+    bool _isMemReady();
+
+
+    /* SFDP Detection and Parsing Functions */
+    /****************************************/
+    int _sfdpParseSFDPHeaders(uint32_t& basic_table_addr, size_t& basic_table_size,
+                              uint32_t& sector_map_table_addr, size_t& sector_map_table_size);
+    int _sfdpParseBasicParamTable(uint32_t basic_table_addr, size_t basic_table_size);
+    int _sfdpParseSectorMapTable(uint32_t sector_map_table_addr, size_t sector_map_table_size);
+    int _sfdpDetectBestBusReadMode(uint8_t *basicParamTablePtr, bool& setQuadEnable, bool& isQPIMode,
+                                   unsigned int& readInst);
+    int _sfdpSetQuadEnabled(uint8_t *basicParamTablePtr);
+    int _sfdpSetQPIEnabled(uint8_t *basicParamTablePtr);
+    int _sfdpDetectPageSize(uint8_t *basicParamTablePtr);
+    int _sfdpDetectEraseTypesInstAndSize(uint8_t *basicParamTablePtr, unsigned int& erase4KInst,
+                                         unsigned int *eraseTypeInstArr, unsigned int *eraseTypeSizeArr);
+
+    /* Utilities Functions */
+    /***********************/
+    int _utilsFindAddrRegion(int offset);
+    int _utilsIterateNextLargestEraseType(uint8_t& bitfield, int size, int offset, int boundry);
+    int _utilsMathPower(int base, int exp);
+
+private:
+
+    // QSPI Driver Object
+    QSPI _qspi;
+    //DigitalOut _cs;
+    bool is_initialized;
+    static SingletonPtr<PlatformMutex> _mutex;
+
+    // Command Instructions
+    unsigned int _readInstruction;
+    unsigned int _progInstruction;
+    unsigned int _eraseInstruction;
+    unsigned int _erase4KInst;
+    unsigned int _eraseTypeInstArr[4];
+    unsigned int _eraseTypeSizeArr[4];
+
+    // Sector Regions Map
+    int _regions_count; //number of regions
+    int _region_size_bytes[QSPIF_MAX_REGIONS]; //regions size
+    int _region_high_boundary[QSPIF_MAX_REGIONS]; //region high address offset boundary
+    uint8_t _region_erase_types[QSPIF_MAX_REGIONS]; //region erase type
+    int _minCommonEraseType; // minimal common erase size for all regions (-1 if none)
+    int _minCommonEraseSize; // minimal common erase size for all regions
+
+    int _pageSizeBytes; // Page size - 256 Bytes default
+    bd_size_t _deviceSizeBytes;
+
+    // Bus speed configuration
+    qspi_bus_width_t _inst_width; //Bus width for Instruction phase
+    qspi_bus_width_t _address_width; //Bus width for Address phase
+    qspi_address_size_t _address_size;
+    qspi_bus_width_t _alt_width; //Bus width for Alt phase
+    qspi_alt_size_t _alt_size;
+    qspi_bus_width_t _data_width; //Bus width for Data phase
+    int _dummy_and_mode_cycles;
+
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qspi-blockdevice/README.md	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,4 @@
+# qspi-blockdevice
+Block Device driver for Quad SPI in Mbed OS 5.9, must be used with feature-qpi branch of mbed-os
+
+This is only to be used until mbed-os 5.10 is released in mid September 2018. As part of the 5.10 release this driver will be integrated into mbedos/features/filesystem/bd/quadspi and will be irrelevant as a standalone library. 
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client.lib	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+https://github.com/armmbed/simple-mbed-cloud-client/#10f9337a6b66e11783ee6b16abd6a64eb917ce3e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/FETCH_HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+10f9337a6b66e11783ee6b16abd6a64eb917ce3e		tag 'v1.4.0' of https://github.com/armmbed/simple-mbed-cloud-client
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+10f9337a6b66e11783ee6b16abd6a64eb917ce3e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/ORIG_HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+10f9337a6b66e11783ee6b16abd6a64eb917ce3e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/config	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,11 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote "origin"]
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	url = https://github.com/armmbed/simple-mbed-cloud-client/
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/description	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/hooks/applypatch-msg.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/hooks/commit-msg.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
+	echo >&2 Duplicate Signed-off-by lines.
+	exit 1
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/hooks/post-update.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/hooks/pre-applypatch.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/hooks/pre-commit.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+	# Note that the use of brackets around a tr range is ok here, (it's
+	# even required, for portability to Solaris 10's /usr/bin/tr), since
+	# the square bracket bytes happen to fall in the designated range.
+	test $(git diff --cached --name-only --diff-filter=A -z $against |
+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+	echo "Error: Attempt to add a non-ascii file name."
+	echo
+	echo "This can cause problems if you want to work"
+	echo "with people on other platforms."
+	echo
+	echo "To be portable it is advisable to rename the file ..."
+	echo
+	echo "If you know what you are doing you can disable this"
+	echo "check using:"
+	echo
+	echo "  git config hooks.allownonascii true"
+	echo
+	exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/hooks/pre-rebase.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+	topic="refs/heads/$2"
+else
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+	;;
+*)
+	exit 0 ;# we do not interrupt others.
+	;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+	echo >&2 "$topic is fully merged to master; better remove it."
+	exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+	not_in_topic=`git rev-list "^$topic" master`
+	if test -z "$not_in_topic"
+	then
+		echo >&2 "$topic is already up-to-date with master"
+		exit 1 ;# we could allow it, but there is no point.
+	else
+		exit 0
+	fi
+else
+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+	/usr/bin/perl -e '
+		my $topic = $ARGV[0];
+		my $msg = "* $topic has commits already merged to public branch:\n";
+		my (%not_in_next) = map {
+			/^([0-9a-f]+) /;
+			($1 => 1);
+		} split(/\n/, $ARGV[1]);
+		for my $elem (map {
+				/^([0-9a-f]+) (.*)$/;
+				[$1 => $2];
+			} split(/\n/, $ARGV[2])) {
+			if (!exists $not_in_next{$elem->[0]}) {
+				if ($msg) {
+					print STDERR $msg;
+					undef $msg;
+				}
+				print STDERR " $elem->[1]\n";
+			}
+		}
+	' "$topic" "$not_in_next" "$not_in_master"
+	exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+		   o---o---o---o---o---o---o---o---o---o "next"
+		  /       /           /           /
+		 /   a---a---b A     /           /
+		/   /               /           /
+	       /   /   c---c---c---c B         /
+	      /   /   /             \         /
+	     /   /   /   b---b C     \       /
+	    /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+	git rev-list ^master ^topic next
+	git rev-list ^master        next
+
+	if these match, topic has not merged in next at all.
+
+To compute (2):
+
+	git rev-list master..topic
+
+	if this is empty, it is fully merged to "master".
+
+DOC_END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/hooks/prepare-commit-msg.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples.  The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+case "$2,$3" in
+  merge,)
+    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+#   /usr/bin/perl -i.bak -pe '
+#      print "\n" . `git diff --cached --name-status -r`
+#	 if /^#/ && $first++ == 0' "$1" ;;
+
+  *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/hooks/update.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+# hooks.denycreatebranch
+#   This boolean sets whether remotely creating branches will be denied
+#   in the repository.  By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+	echo "Don't run this script from the command line." >&2
+	echo " (if you want, you could supply GIT_DIR then run" >&2
+	echo "  $0 <ref> <oldrev> <newrev>)" >&2
+	exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+	echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+	exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+	echo "*** Project description file hasn't been set" >&2
+	exit 1
+	;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+	newrev_type=delete
+else
+	newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+	refs/tags/*,commit)
+		# un-annotated tag
+		short_refname=${refname##refs/tags/}
+		if [ "$allowunannotated" != "true" ]; then
+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,delete)
+		# delete tag
+		if [ "$allowdeletetag" != "true" ]; then
+			echo "*** Deleting a tag is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,tag)
+		# annotated tag
+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+		then
+			echo "*** Tag '$refname' already exists." >&2
+			echo "*** Modifying a tag is not allowed in this repository." >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,commit)
+		# branch
+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+			echo "*** Creating a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,delete)
+		# delete branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/remotes/*,commit)
+		# tracking branch
+		;;
+	refs/remotes/*,delete)
+		# delete tracking branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	*)
+		# Anything else (is there anything else?)
+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+		exit 1
+		;;
+esac
+
+# --- Finished
+exit 0
Binary file simple-mbed-cloud-client/.git/index has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/info/exclude	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,26 @@
+.hg
+.git
+.svn
+.CVS
+.cvs
+*.orig
+.build
+.export
+.msub
+.meta
+.ctags*
+*.uvproj
+*.uvopt
+*.project
+*.cproject
+*.launch
+*.ewp
+*.eww
+Makefile
+Debug
+*.htm
+*.settings
+mbed_settings.py
+*.py[cod]
+# subrepo ignores
+mbed-cloud-client
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/logs/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+0000000000000000000000000000000000000000 f904798403e0e7d848a04dd83a392dfad6a571ec www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378398 +0000	clone: from https://github.com/armmbed/simple-mbed-cloud-client/
+f904798403e0e7d848a04dd83a392dfad6a571ec 10f9337a6b66e11783ee6b16abd6a64eb917ce3e www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378398 +0000	checkout: moving from master to 10f9337a6b66e11783ee6b16abd6a64eb917ce3e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/logs/refs/heads/master	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 f904798403e0e7d848a04dd83a392dfad6a571ec www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378398 +0000	clone: from https://github.com/armmbed/simple-mbed-cloud-client/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/logs/refs/remotes/origin/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 f904798403e0e7d848a04dd83a392dfad6a571ec www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378398 +0000	clone: from https://github.com/armmbed/simple-mbed-cloud-client/
Binary file simple-mbed-cloud-client/.git/objects/pack/pack-5f23bb76255af64b64a8bf318da40d818b23acdc.idx has changed
Binary file simple-mbed-cloud-client/.git/objects/pack/pack-5f23bb76255af64b64a8bf318da40d818b23acdc.pack has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/packed-refs	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,12 @@
+# pack-refs with: peeled 
+739057d2d5a4a1ace7209eaf89722a74f6abf43d refs/remotes/origin/dev
+f904798403e0e7d848a04dd83a392dfad6a571ec refs/remotes/origin/master
+664d33b248f856e2de73aae997674079ed70af57 refs/remotes/origin/mcc-2.0.0
+af3958d518aadb0a599659d0fcdb1240ab9cfb0a refs/remotes/origin/mcc-2.0.1
+4ad472819a315ce78ce48d5c0b6d5722b7c61209 refs/tags/v1.3.0
+^3b72d712ccdb1fbdfa1bdec5209b52f5b813d819
+b1308c14348b42208adf995dcf60ce9a242396ba refs/tags/v1.3.3
+^9f05156e8386f7ef27a0194d12546b8397c0c564
+10f9337a6b66e11783ee6b16abd6a64eb917ce3e refs/tags/v1.4.0
+dba970a2e2323fe6506378b6ad0e1a6a69d70e5d refs/tags/v1.4.1
+^a885642da37e1343e248730e7110f3ef0b3db4c9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/refs/heads/master	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+f904798403e0e7d848a04dd83a392dfad6a571ec
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.git/refs/remotes/origin/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+ref: refs/remotes/origin/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.meta	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<root>
+  <node _type="integer" _key="update">0</node>
+</root>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/.msub	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+mbed-cloud-client = https://github.com/ARMmbed/mbed-cloud-client/#8:9b0bc6a2f3f1f5dbb5be1827db83004d531b99c9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/LICENSE.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/README.md	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,61 @@
+## Simple Mbed Cloud Client
+
+A simple way of connecting Mbed OS 5 devices to Mbed Cloud. It's designed to:
+
+* Enable Mbed Cloud Connect and mbed Cloud Update to applications in few lines of code.
+* Run separate from your main application, it does not take over your main loop.
+* Provide LWM2M resources, essentially variables that are automatically synced through Mbed Cloud Connect.
+* Help users avoid doing blocking network operations in interrupt contexts, by automatically defering actions to a separate thread.
+
+This library is a simpler interface to Mbed Cloud Client, making it trivial to expose sensors, actuators and other variables to the cloud. For a full Mbed Cloud CLient API, check our [documentation](https://cloud.mbed.com/docs/current/mbed-cloud-client/index.html).
+
+### Usage to Connect to Mbed Cloud
+
+1. Add this library to your Mbed OS project:
+
+    ```
+    $ mbed add https://github.com/ARMmbed/simple-mbed-cloud-client
+    ```
+    
+1. Add your Mbed Cloud developer certificate to your project (`mbed_cloud_dev_credentials.c` file).
+
+1. Reference the library from your main.cpp file, add network and storage drivers; finally initialize the Simple Mbed Cloud Client library.
+
+    ```cpp
+    #include "simple-mbed-cloud-client.h"
+    #include <Block device>
+    #include <Filesystem>
+    #include <Network>
+
+    int main() {
+    
+        /* Initialize connectivity */
+        <Network> net;
+        net.connect();
+    
+        /* Initialize storage */
+        <Block device> sd(...);
+        <Filesystem> fs("sd", &sd);
+
+        /* Initialize Simple Mbed Cloud Client */
+        SimpleMbedCloudClient client(&net, &sd, &fs);
+        client.init();
+
+        /* Create resource */        
+        MbedCloudClientResource *variable;
+        variable = client.create_resource("3201/0/5853", "variable");
+        variable->set_value("assign new value");
+        variable->methods(M2MMethod::GET | M2MMethod::PUT);
+
+    }
+    ```
+   
+### Example applications
+  
+  There are a number of applications that make usage of the Simple Mbed Cloud Client library.
+  
+  The Mbed Cloud [Quick-Start](https://cloud.mbed.com/quick-start) is an initiative to support Mbed Partner's platforms while delivering a great User Experience to Mbed Developers.  
+
+### Known issues
+
+None
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client.lib	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-cloud-client/#9b0bc6a2f3f1f5dbb5be1827db83004d531b99c9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/FETCH_HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+08eee48131989f6d93bbade0e660b18740f2f723		tag '1.4.0' of https://github.com/ARMmbed/mbed-cloud-client
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+9b0bc6a2f3f1f5dbb5be1827db83004d531b99c9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/ORIG_HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+9b0bc6a2f3f1f5dbb5be1827db83004d531b99c9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/config	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,11 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote "origin"]
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	url = https://github.com/ARMmbed/mbed-cloud-client/
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/description	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/applypatch-msg.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/commit-msg.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
+	echo >&2 Duplicate Signed-off-by lines.
+	exit 1
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/post-update.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/pre-applypatch.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/pre-commit.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+	# Note that the use of brackets around a tr range is ok here, (it's
+	# even required, for portability to Solaris 10's /usr/bin/tr), since
+	# the square bracket bytes happen to fall in the designated range.
+	test $(git diff --cached --name-only --diff-filter=A -z $against |
+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+	echo "Error: Attempt to add a non-ascii file name."
+	echo
+	echo "This can cause problems if you want to work"
+	echo "with people on other platforms."
+	echo
+	echo "To be portable it is advisable to rename the file ..."
+	echo
+	echo "If you know what you are doing you can disable this"
+	echo "check using:"
+	echo
+	echo "  git config hooks.allownonascii true"
+	echo
+	exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/pre-rebase.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+	topic="refs/heads/$2"
+else
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+	;;
+*)
+	exit 0 ;# we do not interrupt others.
+	;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+	echo >&2 "$topic is fully merged to master; better remove it."
+	exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+	not_in_topic=`git rev-list "^$topic" master`
+	if test -z "$not_in_topic"
+	then
+		echo >&2 "$topic is already up-to-date with master"
+		exit 1 ;# we could allow it, but there is no point.
+	else
+		exit 0
+	fi
+else
+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+	/usr/bin/perl -e '
+		my $topic = $ARGV[0];
+		my $msg = "* $topic has commits already merged to public branch:\n";
+		my (%not_in_next) = map {
+			/^([0-9a-f]+) /;
+			($1 => 1);
+		} split(/\n/, $ARGV[1]);
+		for my $elem (map {
+				/^([0-9a-f]+) (.*)$/;
+				[$1 => $2];
+			} split(/\n/, $ARGV[2])) {
+			if (!exists $not_in_next{$elem->[0]}) {
+				if ($msg) {
+					print STDERR $msg;
+					undef $msg;
+				}
+				print STDERR " $elem->[1]\n";
+			}
+		}
+	' "$topic" "$not_in_next" "$not_in_master"
+	exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+		   o---o---o---o---o---o---o---o---o---o "next"
+		  /       /           /           /
+		 /   a---a---b A     /           /
+		/   /               /           /
+	       /   /   c---c---c---c B         /
+	      /   /   /             \         /
+	     /   /   /   b---b C     \       /
+	    /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+	git rev-list ^master ^topic next
+	git rev-list ^master        next
+
+	if these match, topic has not merged in next at all.
+
+To compute (2):
+
+	git rev-list master..topic
+
+	if this is empty, it is fully merged to "master".
+
+DOC_END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/prepare-commit-msg.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples.  The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+case "$2,$3" in
+  merge,)
+    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+#   /usr/bin/perl -i.bak -pe '
+#      print "\n" . `git diff --cached --name-status -r`
+#	 if /^#/ && $first++ == 0' "$1" ;;
+
+  *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/hooks/update.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+# hooks.denycreatebranch
+#   This boolean sets whether remotely creating branches will be denied
+#   in the repository.  By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+	echo "Don't run this script from the command line." >&2
+	echo " (if you want, you could supply GIT_DIR then run" >&2
+	echo "  $0 <ref> <oldrev> <newrev>)" >&2
+	exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+	echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+	exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+	echo "*** Project description file hasn't been set" >&2
+	exit 1
+	;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+	newrev_type=delete
+else
+	newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+	refs/tags/*,commit)
+		# un-annotated tag
+		short_refname=${refname##refs/tags/}
+		if [ "$allowunannotated" != "true" ]; then
+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,delete)
+		# delete tag
+		if [ "$allowdeletetag" != "true" ]; then
+			echo "*** Deleting a tag is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,tag)
+		# annotated tag
+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+		then
+			echo "*** Tag '$refname' already exists." >&2
+			echo "*** Modifying a tag is not allowed in this repository." >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,commit)
+		# branch
+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+			echo "*** Creating a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,delete)
+		# delete branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/remotes/*,commit)
+		# tracking branch
+		;;
+	refs/remotes/*,delete)
+		# delete tracking branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	*)
+		# Anything else (is there anything else?)
+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+		exit 1
+		;;
+esac
+
+# --- Finished
+exit 0
Binary file simple-mbed-cloud-client/mbed-cloud-client/.git/index has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/info/exclude	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,25 @@
+.hg
+.git
+.svn
+.CVS
+.cvs
+*.orig
+.build
+.export
+.msub
+.meta
+.ctags*
+*.uvproj
+*.uvopt
+*.project
+*.cproject
+*.launch
+*.ewp
+*.eww
+Makefile
+Debug
+*.htm
+*.settings
+mbed_settings.py
+*.py[cod]
+# subrepo ignores
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/logs/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+0000000000000000000000000000000000000000 f80f2047657a316fe0f334081f030c6825612afc www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378404 +0000	clone: from https://github.com/ARMmbed/mbed-cloud-client/
+f80f2047657a316fe0f334081f030c6825612afc 9b0bc6a2f3f1f5dbb5be1827db83004d531b99c9 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378415 +0000	checkout: moving from master to 9b0bc6a2f3f1f5dbb5be1827db83004d531b99c9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/logs/refs/heads/master	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 f80f2047657a316fe0f334081f030c6825612afc www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378404 +0000	clone: from https://github.com/ARMmbed/mbed-cloud-client/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/logs/refs/remotes/origin/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 f80f2047657a316fe0f334081f030c6825612afc www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378404 +0000	clone: from https://github.com/ARMmbed/mbed-cloud-client/
Binary file simple-mbed-cloud-client/mbed-cloud-client/.git/objects/pack/pack-22d710d32ce3109292bb30df9fe28d05ce0430fd.idx has changed
Binary file simple-mbed-cloud-client/mbed-cloud-client/.git/objects/pack/pack-22d710d32ce3109292bb30df9fe28d05ce0430fd.pack has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/packed-refs	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,22 @@
+# pack-refs with: peeled 
+f80f2047657a316fe0f334081f030c6825612afc refs/remotes/origin/master
+11d9ea6fa83cf570766aa5d5bd238b4eb1bdccc0 refs/tags/1.3.0
+^ce9b8d23217bd5885c95d2d0ec6962272c82f5be
+20107b2fd061d8767a1d79d0861c88ddf33ed9a3 refs/tags/1.3.0-GA
+^ce9b8d23217bd5885c95d2d0ec6962272c82f5be
+fceb669c6ac51434300f9d5301701df70af57c6f refs/tags/1.3.1
+^bfdb3a2c89ceca1de7cbab266d3a3b1976dd2017
+432cb2e8f9caa95d92ef1fe4e5ec309e87b3a73c refs/tags/1.3.1.1
+^88d63622c4a3c521a22803a4847930c0ee217c84
+e7f953ee1e354f75f47a51e820dc008486f5cf78 refs/tags/1.3.2
+^d37a136be84216afb90f1bd3b00b1ac9d33d52a1
+008be546c2fb34c143c383f88ad3562b0d032ddc refs/tags/1.3.3
+^3137b3d7c8da10bae38749a9384e5e5c77a55012
+08eee48131989f6d93bbade0e660b18740f2f723 refs/tags/1.4.0
+^9b0bc6a2f3f1f5dbb5be1827db83004d531b99c9
+1fbca1f3ff241109283a0f0c62e6707432d55a38 refs/tags/1.5.0
+^13e0cef7f9508c10d50f3beb049eafea2af6f17b
+8088460105e92e91d4d30c58d4b56500697fb04b refs/tags/2.0.0
+^d20ede92236598b03f61e51207a3f3789858805c
+a55a1ffa15775a23e4540a447cbecc9313af0011 refs/tags/2.0.1
+^f80f2047657a316fe0f334081f030c6825612afc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/refs/heads/master	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+f80f2047657a316fe0f334081f030c6825612afc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.git/refs/remotes/origin/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+ref: refs/remotes/origin/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.gitattributes	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,37 @@
+# Set the default behavior, in case people don't have core.autocrlf set.
+* text=auto
+
+# Explicitly declare text files you want to always be normalized and converted
+# to native line endings on checkout.
+*.c text
+*.h text
+*.cpp text
+*.sh text
+*.py text
+*.md text
+*.java text
+*.yml text
+*.cmake text
+*.lib text
+*.ref text
+
+# Declare files that will always have CRLF line endings on checkout.
+*.sln text eol=crlf
+*.bat text eol=crlf
+
+# Denote all files that are truly binary and should not be modified.
+*.png binary
+*.jpg binary
+*.pdf binary
+*.mpp binary
+*.doc binary
+*.docx binary
+*.xls binary
+*.xlsx binary
+*.ppt binary
+*.pptx binary
+*.tar binary
+*.gzip binary
+*.zip binary
+*.7z binary
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,8 @@
+mbed-client-randlib/*
+mbed-coap/*
+mbed-trace/*
+nanostack-libservice/*
+ns-hal-pal/*
+sal-stack-nanostack-eventloop/*
+unittests/*
+test_modules/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/.meta	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<root>
+  <node _type="integer" _key="update">0</node>
+</root>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/CHANGELOG.md	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+## Changelog for Mbed Cloud Client
+
+### Release 1.4.0 (13.07.2018)
+* Fixed a timer initialization bug under connection handler.
+* Linux: Updated mbed-coap to 4.5.0.
+* This version of Cloud Client has been tested with Mbed OS 5.9.2.
+
+#### Platform Adaptation Layer (PAL)
+
+* Introduced support for ARIA cipher suite introduced in mbedTLS 2.10.0.
+* Introduced MbedTLS configuration support for non-TRNG boards like NUCLEO-F411RE.
+* Hook-up point for allowing application to provide its own reboot function.
+  * Defining `PAL_USE_APPLICATION_REBOOT` activates this feature.
+  * You must define the function `void pal_plat_osApplicationReboot(void)` in your application to provide the required functionality.
+* Introduced the feature flag `PAL_USE_APPLICATION_REBOOT` for application to override generic reboot functionality, which is useful for different Linux flavors.
+* New asynchronous DNS API (activated in application mbed_app.json via `mbed-client-pal.pal-dns-api-version : 2`) with Mbed OS 5.9.x.
+
+#### Factory configurator client
+
+* Chain verification failure will result in `KCM_STATUS_CERTIFICATE_CHAIN_VERIFICATION_FAILED` error instead of `FCC_STATUS_CERTIFICATE_CHAIN_VERIFICATION_FAILED`.
+* Improved robustness of factory serial communication layer.
+* Define `KCM_MAX_NUMBER_OF_CERTITICATES_IN_CHAIN` was renamed to `KCM_MAX_NUMBER_OF_CERTIFICATES_IN_CHAIN`.
+
+#### Mbed Cloud Update
+
+* Improved Linux shell scripts for compatibility and robustness.
+* Fixed an issue in `ARM_UC_HUB_Initialize()` and `ARM_UC_HUB_Uninitialize()` to prevent these functions being called when Update client is in the wrong state.
+* Fixed compiler warnings.
+* Removed designated initialisers from C++ code.
+* Update results are now sent synchronously to ensure that the Update Client hub is in the correct state if several LWM2M operations are performed in rapid succession.
+* Added error messages for missing commands in `arm_update_activate.sh`.
+* Added error reporting when there is not enough space on the device to store the firmware image candidate.
+* Added registration for the scheduler error handler.
+
+#### PAL Platform
+
+* Introducing mbedTLS 2.10.0 support for ARIA cipher suite.
+
+### Release 1.3.3 (08.06.2018)
+
+#### Mbed Cloud Client
+
+* Fixed issue: Wrong CoAP ping message. CoAP ping must be sent as an empty confirmable message.
+* In the previous versions, the client in queue mode went to sleep while in reconnection mode. Now, it completes the connection before going to sleep.
+* This version of Cloud Client supports Mbed OS 5.8.5 and onwards patch releases.
+* Improvements for connection handler, removed usage of static pointer to class. There is now possible to allocate more than one class M2MConnectionSecurityPimpl pareller.
+* Support for new asynchronous DNS API ("mbed-client-pal.pal-dns-api-version : 2") with Mbed OS 5.9.x. 
+
+#### Factory configurator client
+
+* Full support for the `device generated keys` mode. You can activate the mode using the factory configurator utility (FCU) or the KCM APIs.
+
+    <span class="notes">**Note:** Cloud Client and Mbed Cloud do not yet support this mode.</span>
+* A certificate signed request (CSR) that is generated on the device, can be created with the `Extended key usage` extension.
+* A new KCM API introduced:
+  * `kcm_certificate_verify_with_private_key` - a self-generated certificate can be checked against a stored private key.
+* Fixed the `FtcdCommBase::wait_for_message` function to receive multiple messages.
+
+#### Platform Adaptation Layer (PAL)
+
+* The u-blox ODIN-W2 board now requires support for RSA crypto from Mbed TLS. RSA crypto has been enabled by default for the target `MODULE_UBLOX_ODIN_W2`. Enabling RSA crypto increases the flash size by 20KB. More details in Mbed OS PR [#6963](https://github.com/ARMmbed/mbed-os/pull/6963).
+
+### Release 1.3.2 (22.05.2018)
+
+#### Mbed Cloud Client
+
+* Fixed issue: Resource does not notify with content format requested in observation.
+* New internal API: `check_config_parameter()`, returns SUCCESS if parameter exits in KCM.
+* Do not try to store Timezone/UTC data, if there is no data.
+* A separate CoAP response is used only for POST operation, other ones are using piggybacked responses.
+* Send only one notification at a time.
+  * Fixes the issue with an application changing multiple resource values at a same time causing the client to lose notifications from earlier resources. This change ensures that the latest value is always sent to the server.
+* Introducing Mbed Edge specific features:
+  * M2MEndpoint class for describing endpoints behind Mbed Edge device.
+  * Allow registering M2MEndpoints and M2MObjects using the registration API.
+  * Added the `endpoint_type` attribute to the registration update message.
+  * Added the `endpoint name` attribute to the registration and registration update messages.
+* Improved Edge performance for registration update.
+  * This optimization speeds up the registration update. It monitors which endpoints have changed and updates only
+    them.
+  * The bandwitdth of the CoAP messages is reduced. Endpoint data for the unchanged endpoints is not sent in the
+    registration update.
+
+#### Factory configurator client
+
+* New APIs introduced for keys and CSR generation on the device:
+  * `kcm_key_pair_generate_and_store`
+  * `kcm_csr_generate`
+  * `kcm_generate_keys_and_csr`
+* Chain validations added.
+  * A chain is validated when it is stored. Each certificate in the chain is validated against its issuer. An error is returned if the chain is not valid.
+  * If the device certificate (bootstrap or LwM2M) or the update authentication certificate is saved as a chain, the expiration of all certificates is checked in the `fcc_verify_device_configured_4mbed_cloud` function.
+
+#### Platform Adaptation Layer (PAL)
+
+* Linux: Converted all timers to use signal-based timer (SIGEV_SIGNAL) instead of (SIGEV_THREAD).
+  * This fixes the Valgrind warnings for possible memory leaks caused by LIBC's internal timer helper thread.
+
+    <span class="notes">**Note**: If the client application is creating a pthread before instantiating MbedCloudClient,
+    it needs to block the PAL_TIMER_SIGNAL from it. Otherwise the thread may get an exception caused
+    by the default signal handler with a message such as "Process terminating with default action
+    of signal 34 (SIGRT2)". For a suggested way to handle this please see `mcc_platform_init()` in [here](https://github.com/ARMmbed/mbed-cloud-client-example/blob/master/source/platform/Linux/common_setup.c).</span>
+* Linux: Fixed the Linux-specific version of `pal_accept()'s` `addressLen` parameter which previously required a platform-specific socket address structure size, not a platform independent one.
+* Fixed a hard fault issue that occurred when calling `pal_ECKeyGenerateKey`.
+* Return PAL_ERR_BUFFER_TOO_SMALL if the output buffer is too small for write in `pal_writePrivateKeyToDer`, `pal_writePublicKeyToDer`  and `pal_x509CSRWriteDER APIs`.
+* Fixed the missing handling for initialization failure of SOTP.
+* New API `pal_x509CertGetHTBS`: Calculate the hash of the _To Be Signed_ part of an X509 certificate.
+
+#### Mbed Cloud Update
+
+* Improvements to the scheduler to ensure that events are not lost. The scheduler now uses a pool allocation mechanism and queue element locks.
+* Implemented an API to get the active firmware details.
+* A rollback protection error will now be reported as "Firmware update failed" (8) when MCCP=1.
+* An error is issued when the firmware payload exceeds the maximum storage-size limit.
+* Mbed Cloud Update now uses a constant time binary compare function.
+* Fixed a build error for Cortex-A9 target when retrieving the current interrupt enabled state.
+
+### Release 1.3.1.1 (27.04.2018)
+
+#### Mbed Cloud Client
+
+* Fixed POST response handling: The client was sending multiple responses for the POST request received from Cloud, which would sometimes cause undefined behaviour for the POST callback on the webservice.
+
+#### Mbed Cloud Update
+
+* In Linux builds, Update related callbacks are now called in the context of the Update thread. Previously, it was
+  possible to call some of these callbacks in a different thread.
+* In Linux builds, if tracing is enabled, the update scheduler will display an error if a callback can't
+  be added to the scheduler queue.
+
+#### Platform Adaptation Layer (PAL)
+
+* Linux: Replaced `fflush(NULL)` with `sync()` in `pal_osReboot` which was causing deadlock in Raspberry Pi3.
+
+### Release 1.3.1 (19.04.2018)
+
+#### Mbed Cloud Client
+
+* Improve tracing of CoAP packages.
+* Added an API to enable sending of the resource value as a part of the registration message.
+  * Only the following value types are allowed:
+    * STRING
+    * INTEGER
+    * FLOAT
+    * BOOLEAN
+* A fix for sending an empty ACK with blockwise messages.
+* Replaced TCP_KEEPALIVE with CoAP PING.
+* Fixed the possible overflow in bootstrap errors.
+* Now, a token is used to verify BS, register, update register and unregister responses.
+* A fix for sending empty CoAP requests.
+* A fix for the internal timer.
+* PAL is used for asyncronous handling of DNS.
+
+#### Mbed Cloud Update
+
+Using PAL for asyncronous handling of DNS enables firmware update with mesh.
+
+#### Platform Adaptation Layer (PAL)
+
+* A fix to crash when enabling mbed-tls traces.
+* Removed the thread-priority requirement.
+* Fixed the compatibility issues with Mbed OS 5.8/5.9.
+
+### Release 1.3.0 (27.3.2018)
+* Initial public release.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/CMakeLists.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,236 @@
+INCLUDE(CMakeForceCompiler)
+# CROSS COMPILER SETTING
+cmake_minimum_required (VERSION 2.8)
+SET(CMAKE_SYSTEM_NAME Generic)
+
+add_definitions(-DTARGET_LIKE_POSIX)
+
+if (${OS_BRAND} MATCHES Linux)
+    add_definitions(-DMBED_CONF_NS_HAL_PAL_EVENT_LOOP_THREAD_STACK_SIZE=102400)
+else()
+    add_definitions(-DMBED_CONF_NS_HAL_PAL_EVENT_LOOP_THREAD_STACK_SIZE=8000)
+endif()
+
+
+SET(MBED_CLOUD_CLIENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/mbed-cloud-client)
+
+add_definitions(-DMBED_CONF_NANOSTACK_EVENTLOOP_EXCLUDE_HIGHRES_TIMER)
+add_definitions(-DMBED_CONF_NANOSTACK_EVENTLOOP_USE_PLATFORM_TICK_TIMER)
+
+project(mbedCloudClient)
+
+# mbed-cloud-client
+
+ADD_GLOBALDIR( ${CMAKE_CURRENT_SOURCE_DIR})
+ADD_GLOBALDIR( ${CMAKE_CURRENT_SOURCE_DIR}/source)
+ADD_GLOBALDIR( ${CMAKE_CURRENT_SOURCE_DIR}/source/include)
+ADD_GLOBALDIR( ${CMAKE_CURRENT_SOURCE_DIR}/mbed-cloud-client)
+ADD_GLOBALDIR( ${CMAKE_CURRENT_SOURCE_DIR}/mbed-client)
+
+# mbed-client
+
+SET(MBED_CLIENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/mbed-client)
+
+ADD_GLOBALDIR(${MBED_CLIENT_SOURCE_DIR})
+ADD_GLOBALDIR(${MBED_CLIENT_SOURCE_DIR}/source)
+ADD_GLOBALDIR(${MBED_CLIENT_SOURCE_DIR}/source/include)
+ADD_GLOBALDIR(${MBED_CLIENT_SOURCE_DIR}/mbed-client)
+ADD_GLOBALDIR(${MBED_CLIENT_SOURCE_DIR}/mbed-client-c)
+ADD_GLOBALDIR(${MBED_CLIENT_SOURCE_DIR}/mbed-client-c/nsdl-c)
+ADD_GLOBALDIR(${MBED_CLIENT_SOURCE_DIR}/mbed-client-c/source/include)
+ADD_GLOBALDIR(${MBED_CLIENT_SOURCE_DIR}/mbed-client-classic)
+ADD_GLOBALDIR(${MBED_CLIENT_SOURCE_DIR}/mbed-client-classic/mbed-client-classic)
+ADD_GLOBALDIR(${MBED_CLIENT_SOURCE_DIR}/mbed-client-mbed-tls)
+ADD_GLOBALDIR(${MBED_CLIENT_SOURCE_DIR}/mbed-client-mbed-tls/mbed-client-mbedtls)
+
+# pal headers
+
+SET(PAL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/mbed-client-pal/Source)
+ADD_GLOBALDIR(${PAL_SOURCE_DIR}/PAL-Impl/Services-API)
+ADD_GLOBALDIR(${PAL_SOURCE_DIR}/Port/Platform-API)
+
+# common components
+
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/mbed-coap)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/mbed-coap/mbed-coap)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/mbed-coap/source/include)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/mbed-trace)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/mbed-trace/mbed-trace)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/mbed-client-randlib)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/mbed-client-randlib/mbed-client-randlib)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/mbed-client-randlib/mbed-client-randlib/platform)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/nanostack-libservice)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/nanostack-libservice/mbed-client-libservice)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/nanostack-libservice/mbed-client-libservice/platform)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/sal-stack-nanostack-eventloop)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/sal-stack-nanostack-eventloop/nanostack-event-loop)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/ns-hal-pal)
+
+# factory-client
+
+SET(FACTORY_CLIENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/factory-configurator-client)
+ADD_GLOBALDIR(${FACTORY_CLIENT_SOURCE_DIR}/factory-configurator-client)
+
+SET(FCC_MODULES
+    ftcd-comm-base
+    ftcd-comm-socket
+    crypto-service
+    key-config-manager
+    factory-configurator-client
+    fcc-bundle-handler
+    secsrv-cbor
+    logger
+    storage
+    utils
+    mbed-trace-helper
+    fcc-output-info-handler
+    mbed-client-esfs
+)
+
+# includes
+FOREACH(module ${FCC_MODULES})
+    ADD_GLOBALDIR(${FACTORY_CLIENT_SOURCE_DIR}/${module}/${module})
+    ADD_GLOBALDIR(${FACTORY_CLIENT_SOURCE_DIR}/${module}/source/include)
+ENDFOREACH()
+
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/factory-configurator-client/source/include)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/factory-configurator-client/factory-configurator-client)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/fc_protocol_handler/fc_protocol_handler)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/fc_protocol_handler/source/include)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/secure_store)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/secure_store/secure_store)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/storage)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/storage/storage)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/key-config-manager)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/key-config-manager/source/include)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/utils)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/utils/utils)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/logger)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/logger/logger)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/mbed-client-esfs/source/include)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/mbed-client-esfs/source-pal/api)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/mbed-client-esfs/source-pal/linux)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/crypto-service/crypto-service)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/crypto-service/source/include)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/secsrv-cbor/secsrv-cbor)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/fcc-bundle-handler/fcc-bundle-handler)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/fcc-bundle-handler/source/include)
+include_directories(${FACTORY_CLIENT_SOURCE_DIR}/fcc-output-info-handler/fcc-output-info-handler)
+
+# update-client
+
+SET(UPDATE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/update-client-hub)
+
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR})
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/update-client-hub)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/atomic-queue)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/atomic-queue/atomic-queue)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/common)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/common/update-client-common)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/resume-engine)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/resume-engine/resume-engine)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/control-center)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/control-center/update-client-control-center)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/device-identity)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/device-identity/pal4life-device-identity)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/firmware-manager)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/firmware-manager/update-client-firmware-manager)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/lwm2m-mbed)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/lwm2m-mbed/update-client-lwm2m)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/manifest-manager)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/manifest-manager/update-client-manifest-manager)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/manifest-manager/source)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/monitor)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/monitor/update-client-monitor)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/paal-update-api)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/paal-update-api/paal-update-api)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/source)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/source/update-client-source)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/source-http)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/source-http/update-client-source-http)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/source-http-socket)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/source-http-socket/update-client-source-http-socket)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/source-manager)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/source-manager/update-client-source-manager)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/paal)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/paal/update-client-paal)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/pal-filesystem)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/pal-filesystem/update-client-pal-filesystem)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/pal-flashiap)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/pal-flashiap/update-client-pal-flashiap)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/pal-linux)
+ADD_GLOBALDIR(${UPDATE_SOURCE_DIR}/modules/pal-linux/update-client-pal-linux)
+
+FILE(GLOB MBED_CLOUD_CLIENT_SRC
+    "${CMAKE_CURRENT_SOURCE_DIR}/source/*.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp"
+    "${MBED_CLIENT_SOURCE_DIR}/source/*.cpp"
+    "${MBED_CLIENT_SOURCE_DIR}/source/*.c"
+    "${MBED_CLIENT_SOURCE_DIR}/mbed-client-c/source/*.c"
+    "${MBED_CLIENT_SOURCE_DIR}/mbed-client-classic/source/*.cpp"
+    "${MBED_CLIENT_SOURCE_DIR}/mbed-client-mbed-tls/source/*.cpp"
+
+    "${CMAKE_CURRENT_SOURCE_DIR}/mbed-coap/source/*.c"
+
+    "${CMAKE_CURRENT_SOURCE_DIR}/mbed-client-randlib/source/*.c"
+
+    "${CMAKE_CURRENT_SOURCE_DIR}/sal-stack-nanostack-eventloop/source/*.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/sal-stack-nanostack-eventloop/source/*.h"
+    "${CMAKE_CURRENT_SOURCE_DIR}/sal-stack-nanostack-eventloop/source/*.cpp"
+
+    "${CMAKE_CURRENT_SOURCE_DIR}/nanostack-libservice/source/libBits/common_functions.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/nanostack-libservice/source/libList/*.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/nanostack-libservice/source/nsdynmemLIB/*.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/nanostack-libservice/source/libip6string/ip6tos.c"
+
+    "${CMAKE_CURRENT_SOURCE_DIR}/ns-hal-pal/ns_event_loop.c"
+if ((${OS_BRAND} MATCHES "FreeRTOS"))
+    "${CMAKE_CURRENT_SOURCE_DIR}/ns-hal-pal/arm_hal_random.c"
+endif()
+    "${CMAKE_CURRENT_SOURCE_DIR}/ns-hal-pal/ns_hal_init.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/ns-hal-pal/arm_hal_interrupt.c"
+    "${CMAKE_CURRENT_SOURCE_DIR}/ns-hal-pal/arm_hal_timer.cpp"
+    "${FACTORY_CLIENT_SOURCE_DIR}/source/*.c"
+    "${FACTORY_CLIENT_SOURCE_DIR}/storage/source/*.c"
+    "${FACTORY_CLIENT_SOURCE_DIR}/secure_store/source/*.c"
+    "${FACTORY_CLIENT_SOURCE_DIR}/key-config-manager/source/*.c"
+    "${FACTORY_CLIENT_SOURCE_DIR}/utils/source/*.c"
+    "${FACTORY_CLIENT_SOURCE_DIR}/logger/source/*.c"
+    "${FACTORY_CLIENT_SOURCE_DIR}/mbed-client-esfs/source/*.c"
+    "${FACTORY_CLIENT_SOURCE_DIR}/mbed-client-esfs/source-pal/linux/*.c"
+    "${FACTORY_CLIENT_SOURCE_DIR}/mbed-client-esfs/source-pal/linux/*.cpp"
+    "${FACTORY_CLIENT_SOURCE_DIR}/crypto-service/source/*.c"
+    "${FACTORY_CLIENT_SOURCE_DIR}/fcc-bundle-handler/source/*.c"
+    "${FACTORY_CLIENT_SOURCE_DIR}/fcc-output-info-handler/source/*.c"
+    )
+
+if ((${OS_BRAND} MATCHES "Linux"))
+    FILE(GLOB UPDATE_SRC
+    "${UPDATE_SOURCE_DIR}/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/atomic-queue/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/common/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/resume-engine/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/control-center/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/device-identity/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/firmware-manager/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/lwm2m-mbed/source/*.cpp"
+    "${UPDATE_SOURCE_DIR}/modules/lwm2m-mbed/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/manifest-manager/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/source-http/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/source-http-socket/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/source-manager/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/paal/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/pal-filesystem/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/pal-flashiap/source/*.c"
+    "${UPDATE_SOURCE_DIR}/modules/pal-flashiap/source/*.cpp"
+    "${UPDATE_SOURCE_DIR}/modules/pal-linux/source/*.c"
+    )
+endif()
+
+list(APPEND MBED_CLOUD_CLIENT_SRC ${UPDATE_SRC})
+message(status "Mbed Cloud Client sources = \n ${MBED_CLOUD_CLIENT_SRC}")
+
+CREATE_LIBRARY(mbedCloudClient "${MBED_CLOUD_CLIENT_SRC}" "")
+add_dependencies(mbedCloudClient mbedtls)
+
+ADDSUBDIRS()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/DOXYGEN_FRONTPAGE.md	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,17 @@
+Mbed Cloud Client API
+=====================
+
+This is the Doxygen generated API documentation of Mbed Cloud Client. See the [Files](files.html) section to find the documentation about a specific API. It should be used together with the [Mbed Cloud documentation](https://cloud.mbed.com/docs/current).
+
+The Mbed Cloud Client high-level APIs allow mbed Cloud developers to create client side applications that connect to the Mbed Cloud service, with LwM2M features as described in the [Lightweight Machine to Machine Technical Specification](http://technical.openmobilealliance.org/Technical/technical-information/release-program/current-releases/oma-lightweightm2m-v1-0).
+
+Mbed Cloud Client is an extension of the existing [Mbed Client API](http://cloud.mbed.com/docs/current/mbed-client/index.html). It provides an additional feature of creating a unique identity for the client on the Cloud service and also provides functionality to update the client's software through the Mbed Cloud service.
+
+- Use a factory flashed or developer credentials to create a unique device identity.
+- Securely communicate with internet services over the industry standard TLS/DTLS.
+- Manage devices on the Mbed Cloud service.
+- Fully control the endpoint and application logic from the service side. 
+- Provide functionality to update the devices over the air remotely controlled from the service side.
+- Have a unified porting layer for porting to different platforms.
+
+The API is in C++ to allow quick application development.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/README.md	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,5 @@
+# Mbed Cloud Client
+This repository contains ARM Mbed Cloud Client: a library that connects devices to Mbed Cloud service and to Mbed-enabled cloud services from our partners.
+
+The documentation is collected under the docs directory and it is also hosted [here](https://cloud.mbed.com/docs/current/connecting/index.html).
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/contributions.md	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,12 @@
+# How to contribute and report issues
+
+This directory structure contains sources that are copied from internal development source repositories.
+
+## Pull Request policy
+Pull Requests against this repository will be evaluated and the decision to take the change in will be communicated through the same PR.
+However, it will not be merged directly but will enter into subsequent release through internal repositories and the tagged release will be updated in PR before closing it.
+
+## Issue tracking
+You can create Github issues directly againt the repository, the resolution of the issue will be tracked under it.
+If the issue requires code fix it will be provided through subsequent releases and the release tag will be updated there.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/doxygen/mbedcloudclient_doxy	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1846 @@
+# Doxyfile 1.8.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should 
+# identify the project. Note that if you do not use Doxywizard you need 
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME           = mbed-cloud-client
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description 
+# for a project that appears at the top of each page and should give viewer 
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = "mbed Cloud Client C++ library"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is 
+# included in the documentation. The maximum height of the logo should not 
+# exceed 55 pixels and the maximum width should not exceed 200 pixels. 
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO           = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = ../api_docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, 
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English 
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, 
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip. Note that you specify absolute paths here, but also 
+# relative paths, which will be relative from the directory where doxygen is 
+# started.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful if your file system 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 16
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only). 
+# A mapping has the form "name=value". For example adding 
+# "class=itcl::class" will allow you to use the command class in the 
+# itcl::class meaning.
+
+TCL_SUBST              = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it 
+# parses. With this tag you can assign which parser to use for a given 
+# extension. Doxygen has a built-in mapping, but you can override or extend it 
+# using this tag. The format is ext=language, where ext is a file extension, 
+# and language is one of the parsers supported by doxygen: IDL, Java, 
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, 
+# C++. For instance to make doxygen treat .inc files as Fortran files (default 
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note 
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the 
+# files are not read by doxygen.
+
+EXTENSION_MAPPING      = 
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all 
+# comments according to the Markdown format, which allows for more readable 
+# documentation. See http://daringfireball.net/projects/markdown/ for details. 
+# The output of markdown processing is further processed by doxygen, so you 
+# can mix doxygen, HTML, and XML commands with Markdown formatting. 
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes, 
+# or namespaces to their corresponding documentation. Such a link can be 
+# prevented in individual cases by by putting a % sign in front of the word or 
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also makes the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to 
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES (the
+# default) will make doxygen replace the get and set methods by a property in
+# the documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and 
+# unions are shown inside the group in which they are included (e.g. using 
+# @ingroup) instead of on a separate page (for HTML and Man pages) or 
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and 
+# unions with only public data fields will be shown inline in the documentation 
+# of the scope in which they are defined (i.e. file, namespace, or group 
+# documentation), provided this scope is documented. If set to NO (the default), 
+# structs, classes, and unions are shown on a separate page (for HTML and Man 
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to 
+# determine which symbols to keep in memory and which to flush to disk. 
+# When the cache is full, less often used symbols will be written to disk. 
+# For small to medium size projects (<1000 input files) the default value is 
+# probably good enough. For larger projects a too small cache size can cause 
+# doxygen to be busy swapping symbols to and from disk most of the time 
+# causing a significant performance penalty. 
+# If the system has enough physical memory increasing the cache will improve the 
+# performance by keeping more symbols in memory. Note that the value works on 
+# a logarithmic scale so increasing the size by one will roughly double the 
+# memory usage. The cache size is given by this formula: 
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE      = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be 
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given 
+# their name and scope. Since this can be an expensive process and often the 
+# same symbol appear multiple times in the code, doxygen keeps a cache of 
+# pre-resolved symbols. If the cache is too small doxygen will become slower. 
+# If the cache is too large, memory is wasted. The cache size is given by this 
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal 
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = NO
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = YES
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen 
+# will list include files with double quotes in the documentation 
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen 
+# will sort the (brief and detailed) documentation of class members so that 
+# constructors and destructors are listed first. If set to NO (the default) 
+# the constructors will appear in the respective orders defined by 
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. 
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO 
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. 
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to 
+# do proper type resolution of all parameters of a function it will reject a 
+# match between the prototype and the implementation of a member function even 
+# if there is only one candidate or it is obvious which candidate to choose 
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen 
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or macro consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and macros in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 18
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. 
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page.  This will remove the Namespaces entry from the Quick Index 
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed 
+# by doxygen. The layout file controls the global structure of the generated 
+# output files in an output format independent way. To create the layout file 
+# that represents doxygen's defaults, run doxygen with the -l option. 
+# You can optionally specify a file name after the option, if omitted 
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE            = 
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files 
+# containing the references data. This must be a list of .bib files. The 
+# .bib extension is automatically appended if omitted. Using this command 
+# requires the bibtex tool to be installed. See also 
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style 
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this 
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES         = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = ../mbed-cloud-client
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh 
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py 
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.d \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.idl \
+                         *.odl \
+                         *.cs \
+                         *.php \
+                         *.php3 \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.f90 \
+                         *.f \
+                         *.for \
+                         *.vhd \
+                         *.vhdl
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag. 
+# Note that relative paths are relative to the directory from which doxygen is 
+# run.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or 
+# directories that are symbolic links (a Unix file system feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty or if 
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file 
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) 
+# and it is also possible to disable source filtering for a specific pattern 
+# using *.ext= (so without naming a filter). This option only has effect when 
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS = 
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 
+# link to the source code.  Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header. Note that when using a custom header you are responsible  
+# for the proper inclusion of any scripts and style sheets that doxygen 
+# needs, which is dependent on the configuration options used. 
+# It is advised to generate a default header using "doxygen -w html 
+# header.html footer.html stylesheet.css YourConfigFile" and then modify 
+# that header. Note that the header is subject to change so you typically 
+# have to redo this when upgrading to a newer version of doxygen or when 
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If left blank doxygen will 
+# generate a default style sheet. Note that it is recommended to use 
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this 
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET        = 
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional 
+# user-defined cascading style sheet that is included after the standard 
+# style sheets created by doxygen. Using this option one can overrule 
+# certain style aspects. This is preferred over using HTML_STYLESHEET 
+# since it does not replace the standard style sheet and is therefor more 
+# robust against future updates. Doxygen will copy the style sheet file to 
+# the output directory.
+
+HTML_EXTRA_STYLESHEET  = 
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or 
+# other source files which should be copied to the HTML output directory. Note 
+# that these files will be copied to the base HTML output directory. Use the 
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these 
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that 
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES       = 
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. 
+# Doxygen will adjust the colors in the style sheet and background images 
+# according to this color. Hue is specified as an angle on a colorwheel, 
+# see http://en.wikipedia.org/wiki/Hue for more information. 
+# For instance the value 0 represents red, 60 is yellow, 120 is green, 
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. 
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of 
+# the colors in the HTML output. For a value of 0 the output will use 
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to 
+# the luminance component of the colors in the HTML output. Values below 
+# 100 gradually make the output lighter, whereas values above 100 make 
+# the output darker. The value divided by 100 is the actual gamma applied, 
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, 
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML 
+# page will contain the date and time when the page was generated. Setting 
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of 
+# entries shown in the various tree structured indices initially; the user 
+# can expand and collapse entries dynamically later on. Doxygen will expand 
+# the tree to such a level that at most the specified number of entries are 
+# visible (unless a fully collapsed tree already exceeds this amount). 
+# So setting the number of entries 1 will produce a full collapsed tree by 
+# default. 0 is a special value representing an infinite number of entries 
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup. 
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html 
+# for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely 
+# identify the documentation publisher. This should be a reverse domain-name 
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING 
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file 
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and 
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated 
+# that can be used as input for Qt's qhelpgenerator to generate a 
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can 
+# be used to specify the file name of the resulting .qch file. 
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               = 
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to 
+# add. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   = 
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the 
+# custom filter to add. For more information please see 
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> 
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  = 
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this 
+# project's 
+# filter section matches. 
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> 
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  = 
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can 
+# be used to specify the location of Qt's qhelpgenerator. 
+# If non-empty doxygen will try to run qhelpgenerator on the generated 
+# .qhp file.
+
+QHG_LOCATION           = 
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files  
+# will be generated, which together with the HTML files, form an Eclipse help 
+# plugin. To install this plugin and make it available under the help contents 
+# menu in Eclipse, the contents of the directory containing the HTML and XML 
+# files needs to be copied into the plugins directory of eclipse. The name of 
+# the directory within the plugins directory should be the same as 
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before 
+# the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin 
+# the directory name containing the HTML and XML files should also have 
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) 
+# at top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it. Since the tabs have the same information as the 
+# navigation tree you can set this option to NO if you already set 
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 
+# structure should be generated to display hierarchical information. 
+# If the tag value is set to YES, a side panel will be generated 
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). 
+# Windows users are probably better off using the HTML help feature. 
+# Since the tree basically has the same information as the tab index you 
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values 
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML 
+# documentation. Note that a value of 0 will completely suppress the enum 
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open 
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images 
+# generated for formulas are transparent PNGs. Transparent PNGs are 
+# not supported properly for IE 6.0, but are supported on all modern browsers. 
+# Note that when changing this option you need to delete any form_*.png files 
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax 
+# (see http://www.mathjax.org) which uses client side Javascript for the 
+# rendering instead of using prerendered bitmaps. Use this if you do not 
+# have LaTeX installed or if you want to formulas look prettier in the HTML 
+# output. When enabled you may also need to install MathJax separately and 
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you need to specify the location relative to the 
+# HTML output directory using the MATHJAX_RELPATH option. The destination 
+# directory should contain the MathJax.js script. For instance, if the mathjax 
+# directory is located at the same level as the HTML output directory, then 
+# MATHJAX_RELPATH should be ../mathjax. The default value points to 
+# the MathJax Content Delivery Network so you can quickly see the result without 
+# installing MathJax.  However, it is strongly recommended to install a local 
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension 
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS     = 
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box 
+# for the HTML output. The underlying search engine uses javascript 
+# and DHTML and should work on any modern browser. Note that when using 
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets 
+# (GENERATE_DOCSET) there is already a search function so this one should 
+# typically be disabled. For large projects the javascript based search engine 
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be 
+# implemented using a PHP enabled web server instead of at the web client 
+# using Javascript. Doxygen will generate the search PHP script and index 
+# file to put on the web server. The advantage of the server 
+# based approach is that it scales better to large projects and allows 
+# full text search. The disadvantages are that it is more difficult to setup 
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name. 
+# Note that when enabling USE_PDFLATEX this option is only used for 
+# generating bitmaps for formulas in the HTML output, but not in the 
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for 
+# the generated latex document. The footer should contain everything after 
+# the last chapter. If it is left blank doxygen will generate a 
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include 
+# source code with syntax highlighting in the LaTeX output. 
+# Note that which sources are shown also depends on other settings 
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the 
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See 
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition that 
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all references to function-like macros 
+# that are alone on a line, have an all uppercase name, and do not end with a 
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each 
+# tag file the location of the external documentation should be added. The 
+# format of a tag file without this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths 
+# or URLs. Note that each tag file must have a unique name (where the name does 
+# NOT include the path). If a tag file is not located in the directory in which 
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option also works with HAVE_DOT disabled, but it is recommended to 
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = NO
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is 
+# allowed to run in parallel. When set to 0 (the default) doxygen will 
+# base this on the number of processors available in the system. You can set it 
+# explicitly to a value larger than 0 to get control over the balance 
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS        = 0
+
+# By default doxygen will use the Helvetica font for all dot files that 
+# doxygen generates. When you want a differently looking font you can specify 
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find 
+# the font, which can be done by putting it in a standard location or by setting 
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the 
+# directory containing the font.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. 
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the Helvetica font. 
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to 
+# set the path where dot can find it.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside 
+# the class node. If there are many fields or methods and many nodes the 
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS 
+# threshold limits the number of items for each type to make the size more 
+# managable. Set this to 0 for no limit. Note that the threshold may be 
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = YES
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include 
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are svg, png, jpg, or gif. 
+# If left blank png will be used. If you choose svg you need to set 
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files 
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to 
+# enable generation of interactive SVG images that allow zooming and panning. 
+# Note that this requires a modern browser other than Internet Explorer. 
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you 
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files 
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG        = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that 
+# contain msc files that are included in the documentation (see the 
+# \mscfile command).
+
+MSCFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 44
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, because dot on Windows does not 
+# seem to support this out of the box. Warning: Depending on the platform used, 
+# enabling this option may lead to badly anti-aliased labels on the edges of 
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/CMakeLists.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 2.6)
+project("fcc")
+
+include(common_includes.cmake)
+
+# esfs
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mbed-client-esfs/source-pal/api)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mbed-client-esfs/source-pal/linux)
+
+# mbed-tace
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mbed-trace)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mbed-trace/mbed-trace)
+
+# nanostack
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/nanostack-libservice)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/nanostack-libservice/mbed-client-libservice)
+
+SET(SOURCE_LIST "")
+
+FOREACH(module ${MODULES})
+	# sources
+	LIST(APPEND SOURCE_LIST "${CMAKE_CURRENT_SOURCE_DIR}/${module}/${module}/*.h")
+	LIST(APPEND SOURCE_LIST "${CMAKE_CURRENT_SOURCE_DIR}/${module}/source/*.c")
+	LIST(APPEND SOURCE_LIST "${CMAKE_CURRENT_SOURCE_DIR}/${module}/source/*.cpp")
+ENDFOREACH()
+
+FILE(GLOB factory-configurator-client ${SOURCE_LIST})
+
+message("*********************************************************************")
+message("factory-configurator-client = [[${factory-configurator-client}]]")
+message("*********************************************************************")
+
+CREATE_LIBRARY(factory-configurator-client "${factory-configurator-client}" "")
+
+ADDSUBDIRS()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/DOXYGEN_FRONTPAGE.md	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,34 @@
+Factory Configurator Client API
+===============================
+
+This is the Doxygen generated documentation of Factory Configurator Client (FCC) and Key and Configuration Manager (KCM).
+It should be used together with the [Mbed Cloud documentation](https://cloud.mbed.com/docs/latest). See the [Files](files.html) section to find documentation about a specific API.
+
+## FCC
+
+The FCC APIs initialize the factory flow, store the factory configurations using KCM APIs or FCC bundle handler and
+verify that the device is ready for mbed Cloud connection.
+ 
+The FCC APIs allow the following operations:
+
+- Initiating and finalizing of the FCC flow. 
+- After items injection, verifying that the device is ready for Mbed Cloud connection.
+- Retrieving errors and warnings during the injection process.
+- Cleaning all data that was injected to the device.
+
+In developer mode, you do not need to use the Factory Configurator Utility (FCU).
+
+## FCC bundle handler
+
+The FCC bundle handler processes the bundle (in CBOR format) created by Factory Client Utility (FCU) and transferred to the device by the Factory Tool. The device creates a response CBOR message with status and warning details and sends it back to the Factory Tool and the FCU. During the processing, the device stores all relevant factory configuration data to the device's storage.
+
+## KCM
+
+The KCM APIs store parameters, keys and certificates (items) in the device's secure storage and allows other applications (customer or mbed) to access these parameters. 
+
+The KCM APIs allow the following operations on items:
+
+ - Verification and storing items into a secure storage.
+ - Retrieving the item data size from the secure storage.
+ - Retrieving item data from the secure storage.
+ - Deleting items from the secure storage.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/common_includes.cmake	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,41 @@
+
+
+SET(MODULES
+	ftcd-comm-base
+	ftcd-comm-socket
+	crypto-service		
+	key-config-manager
+	factory-configurator-client
+	fcc-bundle-handler	
+	secsrv-cbor
+	logger
+	storage
+	utils
+	mbed-trace-helper
+	fcc-output-info-handler
+)
+
+
+# includes
+FOREACH(module ${MODULES})
+	ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/${module}/${module})
+ENDFOREACH()
+
+# factory-configurator-client internal includes
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/crypto/source/include)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/crypto-service/source/include)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/key-config-manager/source/include)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/mbed-client-esfs/source/include)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/mbed-client-esfs/source/sotp)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/factory-configurator-client/source/include)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/logger/source/include)
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/fcc-bundle-handler/source/include)
+
+# mbed-client-pal
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mbed-client-pal/Source/PAL-Impl/Services-API)
+
+# mbed-trace
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mbed-trace)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mbed-trace/mbed-trace)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/nanostack-libservice/mbed-client-libservice)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/logger/logger)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/crypto-service/cs_der_certs.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,181 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __CS_DER_CERTS_H__
+#define __CS_DER_CERTS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include "kcm_status.h"
+#include "kcm_internal.h"
+#include "cs_hash.h"
+
+/*
+* Types certificate's attributes
+*/
+typedef enum cs_certificate_attribute_type_ {
+    CS_CN_ATTRIBUTE_TYPE,
+    CS_VALID_FROM_ATTRIBUTE_TYPE,
+    CS_VALID_TO_ATTRIBUTE_TYPE,
+    CS_OU_ATTRIBUTE_TYPE,
+    CS_SUBJECT_ATTRIBUTE_TYPE,
+    CS_ISSUER_ATTRIBUTE_TYPE,
+    CS_CERT_ID_ATTR,
+    CS_MAX_ATTRIBUTE_TYPE
+} cs_certificate_attribute_type_e;
+
+
+/** Parameters of the previous certificate in the chain required to verify that the current cert actually signed the previous one.
+*/
+typedef kcm_cert_chain_prev_params_int_s cs_child_cert_params_s;
+
+
+/** Verify handle of x509 formatted certificate using certificate chain handle.
+*
+* In case one of certificate handle is NULLPTR the API returns an error.
+*
+* @param[in] x509_cert -  A handle holding the parsed certificate.
+* @param[in] x509_cert_chain - The pointer to the handle of chain to verify the X509 certificate : Optional
+*
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+kcm_status_e cs_verify_x509_cert(palX509Handle_t x509_cert, palX509Handle_t x509_cert_chain);
+
+/**Parse x509 certificate in DER format.
+* The API parses der certificate and during the parsing checks basic fields structure of the certificate.
+*
+*@cert[in] - DER format certificate.
+*@cert_length[in] - certificate length
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+kcm_status_e cs_check_der_x509_format(const uint8_t *cert, size_t cert_length);
+
+/**Parse and create handle for x509 der certificate.
+* In case certificate is NULL , return empty initialized handle.
+*
+*@cert[in] - DER format certificate.
+*@cert_length[in] - certificate length
+*@x509_cert_handle[out] - certificate handle
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+kcm_status_e cs_create_handle_from_der_x509_cert(const uint8_t *cert, size_t cert_length, palX509Handle_t *x509_cert_handle);
+
+
+/**Add certificate to chain handle.
+* Parse x509 der certificate and add to the chain handle.
+*
+*@cert[in] - DER format certificate.
+*@cert_length[in] - certificate length
+*@x509_chain_handle[out] - certificate chain handle
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+kcm_status_e cs_add_to_chain_x509_cert(const uint8_t *cert, size_t cert_length, palX509Handle_t x509_chain_handle);
+
+/**Close created x509 handle certificate.
+*
+*@x509_cert_handle[in/out] – handle of parsed x509 certificate.
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+kcm_status_e cs_close_handle_x509_cert(palX509Handle_t *x509_cert_handle);
+
+/**Verify that x509 certificate is self-signed.
+*
+*@x509_cert[in] - x509 certificate handle.
+*@is_self_signed[out] - if the value is true the certificate is self-signed, otherwise not self-signed
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+kcm_status_e cs_is_self_signed_x509_cert(palX509Handle_t x509_cert, bool* is_self_signed);
+
+
+/**Gets current attribute from certificate
+*
+*@x509_cert[in] - x509 certificate handle.
+*@cs_attribute_type[in] - certificate attribute type
+*@attribute_output_buffer[out] -pointer to output attribute buffer.
+*@max_size_of_attribute_output_buffer[in] -size of output attribute buffer.
+*@actual_size_of_attribute_output_buffer[out] -actual size of attribute.
+*
+* note in case of "KCM_STATUS_INSUFFICIENT_BUFFER" error the required size will be assigned into the "actual_size_of_output" parameter.
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+kcm_status_e  cs_attr_get_data_x509_cert(palX509Handle_t x509_cert,
+                                         cs_certificate_attribute_type_e cs_attribute_type,
+                                         uint8_t *attribute_output_buffer,
+                                         size_t max_size_of_attribute_output_buffer,
+                                         size_t *actual_size_of_attribute_output_buffer);
+
+/**Gets current attribute size from certificate
+*
+*@x509_cert[in] - x509 certificate handle.
+*@cs_attribute_type[in] - certificate attribute type
+*@size_of_attribute[out] - size of attribute.
+*
+*@return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+kcm_status_e  cs_attr_get_data_size_x509_cert(palX509Handle_t x509_cert,
+                                              cs_certificate_attribute_type_e cs_attribute_type,
+                                              size_t *size_of_attribute);
+
+/**Checks signature using x509 certificate
+*
+*@x509_cert[in] - handle of  x509 certificate.
+*@hash[in] - hash digest for verification
+*@hash_size[in] - size of hash digest.
+*@signature[in] - pointer to signature.
+*@signature_size[in] -signature size.
+*
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+
+kcm_status_e  cs_x509_cert_verify_signature(palX509Handle_t x509_cert,
+                                            const unsigned char *hash,
+                                            size_t hash_size,
+                                            const unsigned char *signature,
+                                            size_t signature_size);
+
+/** Retrieve all the parameters of a child X509 (signed by a parent) certificate, required for validation by the parent (signer) certificate
+*
+* Once these parameters are retrieved, The validity of the child certificate may be checked with the public key of the signer (the pal_verifySignature() API)
+*
+* @param[in] x509_cert Handle to an X509 certificate
+* @param[out] params_out pointer to a cs_child_cert_params_s structure which the relevant data will be filled
+*
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+kcm_status_e cs_child_cert_params_get(palX509Handle_t x509_cert, cs_child_cert_params_s *params_out);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // __CS_DER_CERTS_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/crypto-service/cs_der_keys_and_csrs.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,149 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __CS_DER_KEYS_H__
+#define __CS_DER_KEYS_H__
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "kcm_status.h"
+#include "kcm_defs.h"
+
+/**Verify private Key In DER format. For now only EC keys supported
+*
+*@key_data – DER format private key data.
+*@key_data_length – key data size
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+
+kcm_status_e cs_der_priv_key_verify(const uint8_t* key, size_t key_length);
+
+/**Verify public Key In DER format. For now only EC keys supported
+*
+*@key_data – DER format puclic key data.
+*@key_data_length – key data size
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+
+kcm_status_e cs_der_public_key_verify(const uint8_t* key, size_t key_length);
+
+/**Calculate signature on hash digest using ecdsa private key.
+*
+*@der_priv_key[in] - DER private key data.
+*@der_priv_key_length[in] - key data size
+*@hash_dgst[in] - hash digest buffer
+*@size_of_hash_dgst[in] - size of hash digest buffer
+*@out_sign[in/out] - output buffer for calculated signature
+*@signature_data_max_size[in] - size of signature buffer
+*@signature_data_act_size_out[out] - actual size of output signature buffer
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+kcm_status_e cs_ecdsa_sign(const uint8_t *der_priv_key, size_t der_priv_key_length, const uint8_t *hash_dgst, size_t size_of_hash_dgst, uint8_t *out_sign, size_t  signature_data_max_size, size_t * signature_data_act_size_out);
+
+/**Extracts public raw key data from public der key
+*
+*@der_key[in] - DER public key data.
+*@der_key_length[in] - public key data size
+*@raw_key_data_out[out] - raw key out buffer
+*@raw_key_data_max_size[in] - size of raw key out buffer
+*@raw_key_data_act_size_out[out] - actual output size of raw key
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+kcm_status_e cs_get_pub_raw_key_from_der(const uint8_t *der_key, size_t der_key_length, uint8_t *raw_key_data_out, size_t raw_key_data_max_size, size_t *raw_key_data_act_size_out);
+
+/** Generate a key pair complying the given crypto scheme DER.
+*
+* @param curve_name The curve name
+* @param priv_key_out Out buffer for private key to generate in DER format.
+* @param priv_key_max_size Size of the private key buffer
+* @param priv_key_act_size_out Actual private key size in bytes.
+* @param pub_key_out Out buffer for public key to generate in DER format. Send NULL if no public key needed.
+* @param pub_key_max_size Size of the public key buffer
+* @param pub_key_act_size_out Actual public key size in bytes.
+*
+* @returns
+* Operation status.
+*/
+kcm_status_e cs_key_pair_generate(kcm_crypto_key_scheme_e curve_name,
+                                  uint8_t *priv_key_out,
+                                  size_t priv_key_max_size,
+                                  size_t *priv_key_act_size_out,
+                                  uint8_t *pub_key_out,
+                                  size_t pub_key_max_size,
+                                  size_t *pub_key_act_size_out);
+
+/** Generate a general CSR from the given private key.
+* @param priv_key The private key buffer in DER format.
+* @param priv_key_size The private key buffer size.
+* @param csr_params Pointer to CSR request params struct.
+* @param csr_buff_out Out buffer for CSR to generate in DER format.
+* @param csr_buff_max_size Size of the CSR buffer
+* @param csr_buff_act_size_out Actual CSR size in bytes.
+*
+* @returns
+* Operation status.
+*/
+kcm_status_e cs_csr_generate(const uint8_t *priv_key,
+                             size_t priv_key_size,
+                             const kcm_csr_params_s *csr_params,
+                             uint8_t *csr_buff_out,
+                             size_t csr_buff_max_size,
+                             size_t *csr_buff_act_size_out);
+
+/** Generate private key and CSR from the given crypto scheme DER.
+* @param curve_name The curve name
+* @param csr_params Pointer to CSR request params struct.
+* @param priv_key_out Out buffer for private key to generate in DER format.
+* @param priv_key_max_size Size of the private key buffer
+* @param priv_key_act_size_out Actual private key size in bytes.
+* @param pub_key_out Out buffer for public key to generate in DER format. Send NULL if no public key needed.
+* @param pub_key_max_size Size of the public key buffer
+* @param pub_key_act_size_out Actual public key size in bytes.
+* @param csr_buff_out Out buffer for CSR to generate in DER format.
+* @param csr_buff_max_size Size of the CSR buffer
+* @param csr_buff_act_size_out Actual CSR size in bytes.
+*
+* @returns
+* Operation status.
+*/
+kcm_status_e cs_generate_keys_and_csr(kcm_crypto_key_scheme_e curve_name,
+                                      const kcm_csr_params_s *csr_params,
+                                      uint8_t *priv_key_out,
+                                      size_t priv_key_max_size,
+                                      size_t *priv_key_act_size_out,
+                                      uint8_t *pub_key_out,
+                                      size_t pub_key_max_size,
+                                      size_t *pub_key_act_size_out,
+                                      uint8_t *csr_buff_out,
+                                      const size_t csr_buff_max_size,
+                                      size_t *csr_buff_act_size_out);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  //__CS_DER_KEYS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/crypto-service/cs_hash.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,61 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __CS_HASH_H__
+#define __CS_HASH_H__
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "kcm_status.h"
+#include "pal_Crypto.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    CS_SHA256,//not supported : MD2, MD5, SHA, SHA512, SHA384,SHA512
+} cs_hash_mode_e;
+
+typedef enum {
+    CS_SHA256_SIZE = PAL_SHA256_SIZE,
+} cs_hash_size_e;
+
+#define CS_MAX_HASH_SIZE CS_SHA256_SIZE
+
+/**Calculate hash on input data
+*
+
+*@mode – hash mode as defined in hash_mode enum.
+*@data – data to calculate hash on it
+*@data_size – data size
+*@digest – calculated digest output
+*@digest_size – the size of hash output buffer, should be equal or bigger than current mode hash size in
+*                    hash_size enum.The actual size of hash result is as defined in hash_size enum.
+* @return
+*     KCM_STATUS_SUCCESS on success, otherwise appropriate error from  kcm_status_e.
+*/
+
+kcm_status_e cs_hash(cs_hash_mode_e mode, const uint8_t *data, size_t data_size, uint8_t *digest, size_t digest_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // __CS_HASH_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/source/cs_der_certs.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,293 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "pv_error_handling.h"
+#include "cs_der_certs.h"
+#include "cs_der_keys_and_csrs.h"
+#include "cs_hash.h"
+#include "pal.h"
+#include "cs_utils.h"
+#include "stdbool.h"
+#include "fcc_malloc.h"
+
+
+static kcm_status_e cs_get_x509_cert_attribute_type(cs_certificate_attribute_type_e cs_attribute_type, palX509Attr_t *attribute_type)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+
+
+    switch (cs_attribute_type) {
+        case CS_CN_ATTRIBUTE_TYPE:
+            *attribute_type = PAL_X509_CN_ATTR;
+            break;
+        case CS_VALID_TO_ATTRIBUTE_TYPE:
+            *attribute_type = PAL_X509_VALID_TO;
+            break;
+        case CS_VALID_FROM_ATTRIBUTE_TYPE:
+            *attribute_type = PAL_X509_VALID_FROM;
+            break;
+        case CS_OU_ATTRIBUTE_TYPE:
+            *attribute_type = PAL_X509_OU_ATTR;
+            break;
+        case CS_SUBJECT_ATTRIBUTE_TYPE:
+            *attribute_type = PAL_X509_SUBJECT_ATTR;
+            break;
+        case CS_ISSUER_ATTRIBUTE_TYPE:
+            *attribute_type = PAL_X509_ISSUER_ATTR;
+            break;
+        case CS_CERT_ID_ATTR:
+            *attribute_type = PAL_X509_CERT_ID_ATTR;
+            break;
+        default:
+            SA_PV_ERR_RECOVERABLE_RETURN_IF((true), KCM_CRYPTO_STATUS_INVALID_X509_ATTR, "Invalid cert attribute");
+    }
+
+    return kcm_status;
+}
+
+kcm_status_e cs_is_self_signed_x509_cert(palX509Handle_t x509_cert, bool *is_self_signed)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+
+    uint8_t *cert_subject = NULL;
+    uint8_t *cert_issuer = NULL;
+    size_t subject_size = 0, issuer_size = 0;
+
+    //Self-signed certificate is certificate with subject attribute = issuer attribute
+    //get and check issuer and subject sizes
+    kcm_status = cs_attr_get_data_size_x509_cert(x509_cert, CS_SUBJECT_ATTRIBUTE_TYPE, &subject_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "get size PAL_X509_SUBJECT_ATTR failed");
+
+    kcm_status = cs_attr_get_data_size_x509_cert(x509_cert, CS_ISSUER_ATTRIBUTE_TYPE, &issuer_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "get size PAL_X509_ISSUER_ATTR failed");
+
+    //If issuer and subject attributes have different length it is not self-signed certificate
+    if (subject_size != issuer_size) {
+        *is_self_signed = false;
+        return KCM_STATUS_SUCCESS;
+    }
+
+    //Get and check attributes values
+    cert_subject = fcc_malloc(subject_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((cert_subject == NULL), kcm_status = KCM_STATUS_OUT_OF_MEMORY, exit, "Allocate subject attribute failed");
+
+    pal_status = pal_x509CertGetAttribute(x509_cert, PAL_X509_SUBJECT_ATTR, cert_subject, subject_size, &subject_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), exit,"pal_x509CertGetAttribute PAL_X509_SUBJECT_ATTR failed %d ", (int)cs_error_handler(pal_status));
+
+    cert_issuer = fcc_malloc(issuer_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((cert_subject == NULL), kcm_status = KCM_STATUS_OUT_OF_MEMORY, exit, "Allocate issuer attribute failed");
+
+    pal_status = pal_x509CertGetAttribute(x509_cert, PAL_X509_ISSUER_ATTR, cert_issuer, issuer_size, &issuer_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), exit, "pal_x509CertGetAttribute PAL_X509_ISSUER_ATTR failed %d", (int)kcm_status);
+
+    if (memcmp(cert_issuer, cert_subject, issuer_size) == 0) {
+        *is_self_signed = true;
+    } else {
+        *is_self_signed = false;
+    }
+
+exit:
+    fcc_free(cert_subject);
+    fcc_free(cert_issuer);
+
+    return kcm_status;
+}
+
+kcm_status_e cs_create_handle_from_der_x509_cert(const uint8_t *cert, size_t cert_length, palX509Handle_t *x509_cert_handle)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cert != NULL && cert_length == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid cert_length");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid x509_cert_handler");
+
+    //Allocate and Init certificate handler
+    pal_status = pal_x509Initiate(x509_cert_handle);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), cs_error_handler(pal_status), "pal_x509Initiate failed");
+
+    if (cert != NULL) {
+        //Parse Certificate.
+        pal_status = pal_x509CertParse(*x509_cert_handle, cert, cert_length);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), exit, "pal_x509CertParse failed");
+    }
+
+exit:
+    if (pal_status != PAL_SUCCESS) {
+        pal_x509Free(x509_cert_handle);
+    }
+
+    return kcm_status;
+}
+kcm_status_e cs_add_to_chain_x509_cert(const uint8_t *cert, size_t cert_length, palX509Handle_t x509_chain_handle)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cert == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid cert pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cert_length <= 0), KCM_STATUS_INVALID_PARAMETER, "Invalid cert_length");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_chain_handle == NULLPTR), KCM_STATUS_INVALID_PARAMETER, "Invalid x509_chain_handle");
+
+    //Parse Certificate.
+    pal_status = pal_x509CertParse(x509_chain_handle, cert, cert_length);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), "pal_x509CertParse failed");
+
+    return kcm_status;
+}
+kcm_status_e cs_close_handle_x509_cert(palX509Handle_t *x509_cert_handle)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+
+    pal_status =  pal_x509Free(x509_cert_handle);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), "pal_x509Free failed");
+
+    return kcm_status;
+}
+kcm_status_e cs_check_der_x509_format(const uint8_t *cert, size_t cert_length)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+    palX509Handle_t x509_cert = NULLPTR;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cert == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid cert pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cert_length <= 0), KCM_STATUS_INVALID_PARAMETER, "Invalid cert_length");
+
+    //Allocate and Init certificate handler
+    pal_status = pal_x509Initiate(&x509_cert);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), cs_error_handler(pal_status), "pal_x509Initiate failed");
+
+    //Parse Certificate.
+    pal_status = pal_x509CertParse(x509_cert, cert, cert_length);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), exit, "pal_x509CertParse failed");
+
+exit:
+    pal_x509Free(&x509_cert);
+    return kcm_status;
+}
+
+kcm_status_e cs_verify_x509_cert(palX509Handle_t x509_cert,palX509Handle_t x509_cert_chain)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+    bool is_self_signed = false;
+    palX509Handle_t x509_ca_cert = NULLPTR;
+
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert == NULLPTR), KCM_STATUS_INVALID_PARAMETER, "Invalid cert handle");
+
+    kcm_status = cs_is_self_signed_x509_cert(x509_cert, &is_self_signed);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Self signed verification failed");
+
+    if (is_self_signed && x509_cert_chain == NULLPTR) { // Send the certificate itself as trusted chain
+        x509_ca_cert = x509_cert;
+    } else {
+            x509_ca_cert = x509_cert_chain;
+    }
+
+    //Verify certificate using created certificate chain
+    pal_status = pal_x509CertVerify(x509_cert, x509_ca_cert);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), exit, "pal_x509CertVerify failed %" PRIu32 "", pal_status);
+
+exit:
+    return kcm_status;
+}
+
+kcm_status_e  cs_attr_get_data_size_x509_cert(palX509Handle_t x509_cert,
+                                              cs_certificate_attribute_type_e cs_attribute_type,
+                                              size_t *size_of_attribute)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palX509Attr_t attribute_type;
+    palStatus_t pal_status = PAL_SUCCESS;
+    uint8_t output_buffer;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert == NULLPTR), KCM_STATUS_INVALID_PARAMETER, "Invalid x509_cert");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((size_of_attribute == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid size_of_attribute pointer");
+
+    kcm_status = cs_get_x509_cert_attribute_type(cs_attribute_type, &attribute_type);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "cs_get_x509_cert_attribute_type failed");
+
+    //Get the attribute size
+    pal_status = pal_x509CertGetAttribute(x509_cert, attribute_type, &output_buffer, 0, size_of_attribute);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status == PAL_SUCCESS), KCM_STATUS_ERROR, "Attribute size is 0");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_ERR_BUFFER_TOO_SMALL), kcm_status = cs_error_handler(pal_status), "Failed to get attribute size");
+
+    return KCM_STATUS_SUCCESS;
+};
+
+kcm_status_e  cs_attr_get_data_x509_cert(palX509Handle_t x509_cert,
+                                         cs_certificate_attribute_type_e cs_attribute_type,
+                                         uint8_t *attribute_output_buffer,
+                                         size_t max_size_of_attribute_output_buffer,
+                                         size_t *actual_size_of_attribute_output_buffer)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palX509Attr_t attribute_type;
+    palStatus_t pal_status = PAL_SUCCESS;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert == NULLPTR), KCM_STATUS_INVALID_PARAMETER, "Invalid x509_cert");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((attribute_output_buffer == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid output pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((actual_size_of_attribute_output_buffer == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid actual_size_of_output pointer");
+
+    kcm_status = cs_get_x509_cert_attribute_type(cs_attribute_type, &attribute_type);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "cs_get_x509_cert_attribute_type failed");
+
+    //Get the attribute
+    pal_status = pal_x509CertGetAttribute(x509_cert, attribute_type, attribute_output_buffer, max_size_of_attribute_output_buffer, actual_size_of_attribute_output_buffer);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), "pal_x509CertGetAttribute failed");
+
+    return kcm_status;
+};
+
+kcm_status_e  cs_x509_cert_verify_signature(palX509Handle_t x509_cert, const unsigned char *hash, size_t hash_size, const unsigned char *signature, size_t signature_size)
+{
+
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert == NULLPTR), KCM_STATUS_INVALID_PARAMETER, "Invalid x509_cert");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((hash == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid hash pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((hash_size != CS_SHA256_SIZE), KCM_STATUS_INVALID_PARAMETER, "Invalid hash digest size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((signature == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid signature pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((signature_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid signature size");
+
+    //Verify signature
+    pal_status = pal_verifySignature(x509_cert, PAL_SHA256, hash, hash_size, signature, signature_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), kcm_status = cs_error_handler(pal_status), "pal_verifySignature failed");
+
+    return kcm_status;
+}
+
+kcm_status_e cs_child_cert_params_get(palX509Handle_t x509_cert, cs_child_cert_params_s *params_out)
+{
+    palStatus_t pal_status = PAL_SUCCESS;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert == NULLPTR), KCM_STATUS_INVALID_PARAMETER, "Invalid x509_cert");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((params_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer params_out");
+
+    // Retrieve the signature
+    pal_status = pal_x509CertGetAttribute(x509_cert, PAL_X509_SIGNATUR_ATTR, params_out->signature, sizeof(params_out->signature), &params_out->signature_actual_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), cs_error_handler(pal_status), "Failed getting signature");
+
+    // Hash a SHA256 of the To Be Signed part of the X509 certificate
+    // If we end up using more than on hash type we may retrieve it from x509_cert instead of hard coded PAL_SHA256
+    pal_status = pal_x509CertGetHTBS(x509_cert, PAL_SHA256, params_out->htbs, sizeof(params_out->htbs), &params_out->htbs_actual_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), cs_error_handler(pal_status), "Failed Hashing TBS");
+
+    return KCM_STATUS_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/source/cs_der_keys_and_csrs.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,408 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "pv_error_handling.h"
+#include "cs_der_keys_and_csrs.h"
+#include "pal.h"
+#include "cs_utils.h"
+#include "cs_hash.h"
+#include "pk.h"
+#include "kcm_internal.h"
+
+//For now only EC keys supported!!!
+static kcm_status_e der_key_verify(const uint8_t *der_key, size_t der_key_length, palKeyToCheck_t key_type)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+    palECKeyHandle_t key_handle = NULLPTR;
+    palCurveHandle_t grp = NULLPTR;
+    palGroupIndex_t pal_grp_idx;
+    bool verified = false;
+
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((der_key == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid der_key pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((der_key_length <= 0), KCM_STATUS_INVALID_PARAMETER, "Invalid der_key_length");
+
+    //Create new key handler
+    pal_status = pal_ECKeyNew(&key_handle);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((PAL_SUCCESS != pal_status), cs_error_handler(pal_status), "pal_ECKeyNew failed ");
+
+    //Parse the key from DER format
+    if (key_type == PAL_CHECK_PRIVATE_KEY) {
+        pal_status = pal_parseECPrivateKeyFromDER(der_key, der_key_length, key_handle);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "pal_parseECPrivateKeyFromDER failed ");
+    } else {
+        pal_status = pal_parseECPublicKeyFromDER(der_key, der_key_length, key_handle);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "pal_parseECPublicKeyFromDER failed ");
+    }
+
+    //retrieve key curve from key handle
+    pal_status = pal_ECKeyGetCurve(key_handle, &pal_grp_idx);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "pal_ECKeyGetCurve failed ");
+
+    //Allocate curve handler
+    pal_status = pal_ECGroupInitAndLoad(&grp, pal_grp_idx);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "pal_parseECPrivateKeyFromDER failed ");
+
+    //Perform key verification
+    pal_status = pal_ECCheckKey(grp, key_handle, key_type, &verified);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF(((PAL_SUCCESS != pal_status) || (verified != true)), kcm_status = cs_error_handler(pal_status), exit, "pal_ECCheckKey failed ");
+
+
+exit:
+    //Free curve handle
+    (void)pal_ECGroupFree(&grp);
+    //Free key handler
+    (void)pal_ECKeyFree(&key_handle);
+
+    if (kcm_status == KCM_STATUS_SUCCESS) {
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((grp != NULLPTR || key_handle != NULLPTR), KCM_STATUS_ERROR, "Free handle failed ");
+    }
+
+    return kcm_status;
+}
+//For now only EC SECP256R keys supported!!!
+kcm_status_e cs_get_pub_raw_key_from_der(const uint8_t *der_key, size_t der_key_length, uint8_t *raw_key_data_out, size_t raw_key_data_max_size, size_t *raw_key_data_act_size_out)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+    int mbdtls_result = 0;
+    palECKeyHandle_t key_handle = NULLPTR;
+    mbedtls_pk_context* localECKey;
+    mbedtls_ecp_keypair *ecp_key_pair;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((der_key == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid der_key pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((der_key_length != KCM_EC_SECP256R1_MAX_PUB_KEY_DER_SIZE), KCM_STATUS_INVALID_PARAMETER, "Invalid der_key_length");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((raw_key_data_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid raw_key_data_out");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((raw_key_data_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid raw_key_data_act_size_out pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((raw_key_data_max_size < KCM_EC_SECP256R1_MAX_PUB_KEY_RAW_SIZE), KCM_STATUS_INVALID_PARAMETER, "Invalid raw_key_size_out value");
+
+    //Create new key handler
+    pal_status = pal_ECKeyNew(&key_handle);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((PAL_SUCCESS != pal_status), cs_error_handler(pal_status), "pal_ECKeyNew failed ");
+
+    pal_status = pal_parseECPublicKeyFromDER(der_key, der_key_length, key_handle);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "pal_parseECPublicKeyFromDER failed ");
+
+    localECKey = (mbedtls_pk_context*)key_handle;
+    ecp_key_pair = (mbedtls_ecp_keypair*)localECKey->pk_ctx;
+
+    //Get raw public key data
+    mbdtls_result = mbedtls_ecp_point_write_binary(&ecp_key_pair->grp, &ecp_key_pair->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, raw_key_data_act_size_out, raw_key_data_out, raw_key_data_max_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((mbdtls_result != 0), kcm_status = KCM_CRYPTO_STATUS_INVALID_PK_PUBKEY, exit, "mbedtls_ecp_point_write_binary failed ");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((raw_key_data_max_size != KCM_EC_SECP256R1_MAX_PUB_KEY_RAW_SIZE), kcm_status = KCM_CRYPTO_STATUS_INVALID_PK_PUBKEY, exit, "Wrong raw_key_data_max_size ");
+
+exit:
+    //Free key handler
+    (void)pal_ECKeyFree(&key_handle);
+    return kcm_status;
+}
+
+
+kcm_status_e cs_der_priv_key_verify(const uint8_t *key, size_t key_length)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+
+    kcm_status = der_key_verify(key, key_length, PAL_CHECK_PRIVATE_KEY);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Private key verification failed");
+
+    return kcm_status;
+}
+
+kcm_status_e cs_der_public_key_verify(const uint8_t *der_key, size_t der_key_length)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+
+    kcm_status = der_key_verify(der_key, der_key_length, PAL_CHECK_PUBLIC_KEY);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Public key verification failed");
+
+    return kcm_status;
+}
+
+kcm_status_e cs_ecdsa_sign(const uint8_t *der_priv_key, size_t der_priv_key_length, const uint8_t *hash_dgst, size_t size_of_hash_dgst, uint8_t *out_sign, size_t  signature_data_max_size, size_t * signature_data_act_size_out)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+    palECKeyHandle_t key_handle = NULLPTR;
+    palCurveHandle_t grp = NULLPTR;
+    palGroupIndex_t pal_grp_idx;
+    palMDType_t md_type = PAL_SHA256;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((der_priv_key == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid private key pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((der_priv_key_length <= 0), KCM_STATUS_INVALID_PARAMETER, "Invalid private key length");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((hash_dgst == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid hash digest pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((size_of_hash_dgst != CS_SHA256_SIZE), KCM_STATUS_INVALID_PARAMETER, "Invalid hash digest size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((out_sign == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid out signature pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((signature_data_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid signature_data_act_size_out pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((signature_data_max_size < KCM_ECDSA_SECP256R1_MAX_SIGNATURE_SIZE_IN_BYTES), KCM_STATUS_INVALID_PARAMETER, "Invalid size of signature buffer");
+
+
+    //Create new key handler
+    pal_status = pal_ECKeyNew(&key_handle);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((PAL_SUCCESS != pal_status), cs_error_handler(pal_status), "pal_ECKeyNew failed ");
+
+    //Parse der private key
+    pal_status = pal_parseECPrivateKeyFromDER(der_priv_key, der_priv_key_length, key_handle);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "pal_parseECPrivateKeyFromDER failed ");
+
+    //retrieve key curve from key handle
+    pal_status = pal_ECKeyGetCurve(key_handle, &pal_grp_idx);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "pal_ECKeyGetCurve failed ");
+
+    //Load the key curve
+    pal_status = pal_ECGroupInitAndLoad(&grp, pal_grp_idx);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "pal_ECGroupInitAndLoad failed ");
+
+    *signature_data_act_size_out = signature_data_max_size;
+    //Sign on hash digest
+    pal_status = pal_ECDSASign(grp, md_type, key_handle, (unsigned char*)hash_dgst, (uint32_t)size_of_hash_dgst, out_sign, signature_data_act_size_out);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "pal_ECDSASign failed ");
+
+exit:
+
+    //Free curve handler
+    (void)pal_ECGroupFree(&grp);
+    //Free key handler
+    (void)pal_ECKeyFree(&key_handle);
+
+    if (kcm_status == KCM_STATUS_SUCCESS) {
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((grp != NULLPTR || key_handle != NULLPTR), KCM_STATUS_ERROR, "Free handle failed ");
+    }
+    return kcm_status;
+}
+
+static kcm_status_e cs_key_pair_generate_int(palECKeyHandle_t key_handle, kcm_crypto_key_scheme_e curve_name, uint8_t *priv_key_out, size_t priv_key_max_size,
+                                             size_t *priv_key_act_size_out, uint8_t *pub_key_out, size_t pub_key_max_size, size_t *pub_key_act_size_out)
+{
+    palStatus_t pal_status = PAL_SUCCESS;
+    palGroupIndex_t pal_group_id;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((priv_key_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid out private key buffer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((priv_key_max_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid max private key size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((priv_key_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid out private key size");
+    if (pub_key_out != NULL) {
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((pub_key_max_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid max public key size");
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((pub_key_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid out public key size");
+    }
+
+    // convert curve_name to pal_group_id
+    switch (curve_name) {
+        case KCM_SCHEME_EC_SECP256R1:
+            pal_group_id = PAL_ECP_DP_SECP256R1;
+            break;
+        default:
+            SA_PV_ERR_RECOVERABLE_RETURN_IF(true, KCM_CRYPTO_STATUS_UNSUPPORTED_CURVE, "unsupported curve name");
+    }
+
+    // Generate keys
+    pal_status = pal_ECKeyGenerateKey(pal_group_id, key_handle);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((PAL_SUCCESS != pal_status), cs_error_handler(pal_status), "Failed to generate keys");
+
+    // Save private key to out buffer
+    pal_status = pal_writePrivateKeyToDer(key_handle, priv_key_out, priv_key_max_size, priv_key_act_size_out);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((PAL_SUCCESS != pal_status), cs_error_handler(pal_status), "Failed to write private key to out buffer");
+
+    if (pub_key_out != NULL) {
+        // Save public key to out buffer
+        pal_status = pal_writePublicKeyToDer(key_handle, pub_key_out, pub_key_max_size, pub_key_act_size_out);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((PAL_SUCCESS != pal_status), cs_error_handler(pal_status), "Failed to write public key to out buffer");
+    }
+
+    return KCM_STATUS_SUCCESS;
+}
+
+kcm_status_e cs_key_pair_generate(kcm_crypto_key_scheme_e curve_name, uint8_t *priv_key_out, size_t priv_key_max_size, size_t *priv_key_act_size_out, uint8_t *pub_key_out,
+                                  size_t pub_key_max_size, size_t *pub_key_act_size_out)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+    palECKeyHandle_t key_handle = NULLPTR;
+
+    // Create new key handler
+    pal_status = pal_ECKeyNew(&key_handle);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((PAL_SUCCESS != pal_status), cs_error_handler(pal_status), "pal_ECKeyNew failed");
+
+    // Call to internal key_pair_generate
+    kcm_status = cs_key_pair_generate_int(key_handle, curve_name, priv_key_out, priv_key_max_size, priv_key_act_size_out,
+                                          pub_key_out, pub_key_max_size, pub_key_act_size_out);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Failed to generate keys");
+
+exit:
+    //Free key handler
+    if (key_handle != NULLPTR) {
+        pal_ECKeyFree(&key_handle);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((key_handle != NULLPTR && kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_ERROR, "Free key handle failed ");
+    }
+    return kcm_status;
+}
+
+static kcm_status_e cs_csr_generate_int(palECKeyHandle_t key_handle, const kcm_csr_params_s *csr_params,
+                                        uint8_t *csr_buff_out, size_t csr_buff_max_size, size_t *csr_buff_act_size_out)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+    palx509CSRHandle_t x509CSR_handle = NULLPTR;
+    palMDType_t pal_md_type;
+    uint32_t pal_key_usage = 0;
+    uint32_t pal_ext_key_usage = 0;
+    uint32_t eku_all_bits = KCM_CSR_EXT_KU_ANY | KCM_CSR_EXT_KU_SERVER_AUTH | KCM_CSR_EXT_KU_CLIENT_AUTH |
+        KCM_CSR_EXT_KU_CODE_SIGNING | KCM_CSR_EXT_KU_EMAIL_PROTECTION | KCM_CSR_EXT_KU_TIME_STAMPING | KCM_CSR_EXT_KU_OCSP_SIGNING;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_params pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->subject == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid subject pointer in csr_params");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid out csr buffer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_max_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid max csr buffer size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid out csr buffer size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->ext_key_usage & (~eku_all_bits)), KCM_STATUS_INVALID_PARAMETER, "Invalid extended key usage options");
+
+    // Initialize x509 CSR handle 
+    pal_status = pal_x509CSRInit(&x509CSR_handle);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((PAL_SUCCESS != pal_status), cs_error_handler(pal_status), "Failed to initialize x509 CSR handle");
+
+    // Set CSR Subject
+    pal_status = pal_x509CSRSetSubject(x509CSR_handle, csr_params->subject);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "Failed to set CSR Subject");
+
+    // Set MD algorithm to SHA256 for the signature
+    switch (csr_params->md_type) {
+        case KCM_MD_SHA256:
+            pal_md_type = PAL_SHA256;
+            break;
+        default:
+            SA_PV_ERR_RECOVERABLE_GOTO_IF(true, kcm_status = KCM_CRYPTO_STATUS_INVALID_MD_TYPE, exit, "MD type not supported");
+    }
+    pal_status = pal_x509CSRSetMD(x509CSR_handle, pal_md_type);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "Failed to set MD algorithm");
+
+    // Set keys into CSR
+    pal_status = pal_x509CSRSetKey(x509CSR_handle, key_handle, NULLPTR);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "Failed to Set keys into CSR");
+
+    // Set CSR key usage
+    if (csr_params->key_usage != KCM_CSR_KU_NONE) {
+        if (csr_params->key_usage & KCM_CSR_KU_DIGITAL_SIGNATURE) {
+            pal_key_usage |= PAL_X509_KU_DIGITAL_SIGNATURE;
+        }
+        if (csr_params->key_usage & KCM_CSR_KU_NON_REPUDIATION) {
+            pal_key_usage |= PAL_X509_KU_NON_REPUDIATION;
+        }
+        if (csr_params->key_usage & KCM_CSR_KU_KEY_CERT_SIGN) {
+            pal_key_usage |= PAL_X509_KU_KEY_CERT_SIGN;
+        }
+        pal_status = pal_x509CSRSetKeyUsage(x509CSR_handle, pal_key_usage);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "Failed to set CSR key usage");
+    }
+
+    // Set CSR extended key usage
+    if (csr_params->ext_key_usage != KCM_CSR_EXT_KU_NONE) {
+        if (csr_params->ext_key_usage & KCM_CSR_EXT_KU_ANY) {
+            pal_ext_key_usage |= PAL_X509_EXT_KU_ANY;
+        }
+        if (csr_params->ext_key_usage & KCM_CSR_EXT_KU_SERVER_AUTH) {
+            pal_ext_key_usage |= PAL_X509_EXT_KU_SERVER_AUTH;
+        }
+        if (csr_params->ext_key_usage & KCM_CSR_EXT_KU_CLIENT_AUTH) {
+            pal_ext_key_usage |= PAL_X509_EXT_KU_CLIENT_AUTH;
+        }
+        if (csr_params->ext_key_usage & KCM_CSR_EXT_KU_CODE_SIGNING) {
+            pal_ext_key_usage |= PAL_X509_EXT_KU_CODE_SIGNING;
+        }
+        if (csr_params->ext_key_usage & KCM_CSR_EXT_KU_EMAIL_PROTECTION) {
+            pal_ext_key_usage |= PAL_X509_EXT_KU_EMAIL_PROTECTION;
+        }
+        if (csr_params->ext_key_usage & KCM_CSR_EXT_KU_TIME_STAMPING) {
+            pal_ext_key_usage |= PAL_X509_EXT_KU_TIME_STAMPING;
+        }
+        if (csr_params->ext_key_usage & KCM_CSR_EXT_KU_OCSP_SIGNING) {
+            pal_ext_key_usage |= PAL_X509_EXT_KU_OCSP_SIGNING;
+        }
+        pal_status = pal_x509CSRSetExtendedKeyUsage(x509CSR_handle, pal_ext_key_usage);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "Failed to set CSR extended key usage");
+    }
+
+    // Write the CSR to out buffer in DER format
+    pal_status = pal_x509CSRWriteDER(x509CSR_handle, csr_buff_out, csr_buff_max_size, csr_buff_act_size_out);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "Failed to write the CSR to out buffer");
+
+exit:
+    //Free CSR handler
+    if (x509CSR_handle != NULLPTR) {
+        pal_x509CSRFree(&x509CSR_handle);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((x509CSR_handle != NULLPTR && kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_ERROR, "Free CSR handle failed ");
+    }
+
+    return kcm_status;
+}
+
+kcm_status_e cs_csr_generate(const uint8_t *priv_key, size_t priv_key_size, const kcm_csr_params_s *csr_params, uint8_t *csr_buff_out,
+                             size_t csr_buff_max_size, size_t *csr_buff_act_size_out)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+    palECKeyHandle_t key_handle = NULLPTR;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((priv_key == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid private key pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((priv_key_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid private key size");
+
+    // Create new key handler
+    pal_status = pal_ECKeyNew(&key_handle);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((PAL_SUCCESS != pal_status), cs_error_handler(pal_status), "pal_ECKeyNew failed");
+
+    // Parse private key from DER format
+    pal_status = pal_parseECPrivateKeyFromDER(priv_key, priv_key_size, key_handle);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((PAL_SUCCESS != pal_status), kcm_status = cs_error_handler(pal_status), exit, "Failed to parse private key from DER format");
+
+    // Call to internal csr_generate
+    kcm_status = cs_csr_generate_int(key_handle, csr_params, csr_buff_out, csr_buff_max_size, csr_buff_act_size_out);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Failed to generate csr");
+
+exit:
+    //Free key handler
+    if (key_handle != NULLPTR) {
+        pal_ECKeyFree(&key_handle);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((key_handle != NULLPTR && kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_ERROR, "Free key handle failed ");
+    }
+    return kcm_status;
+}
+kcm_status_e cs_generate_keys_and_csr(kcm_crypto_key_scheme_e curve_name, const kcm_csr_params_s *csr_params, uint8_t *priv_key_out,
+                                      size_t priv_key_max_size, size_t *priv_key_act_size_out, uint8_t *pub_key_out,
+                                      size_t pub_key_max_size, size_t *pub_key_act_size_out, uint8_t *csr_buff_out,
+                                      const size_t csr_buff_max_size, size_t *csr_buff_act_size_out)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palStatus_t pal_status = PAL_SUCCESS;
+    palECKeyHandle_t key_handle = NULLPTR;
+
+    // Create new key handler
+    pal_status = pal_ECKeyNew(&key_handle);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((PAL_SUCCESS != pal_status), cs_error_handler(pal_status), "pal_ECKeyNew failed");
+
+    // Call to internal key_pair_generate
+    kcm_status = cs_key_pair_generate_int(key_handle, curve_name, priv_key_out, priv_key_max_size, priv_key_act_size_out, pub_key_out, pub_key_max_size, pub_key_act_size_out);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Failed to generate keys");
+
+    // Call to internal csr_generate
+    kcm_status = cs_csr_generate_int(key_handle, csr_params, csr_buff_out, csr_buff_max_size, csr_buff_act_size_out);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Failed to generate csr");
+
+exit:
+    //Free key handler
+    if (key_handle != NULLPTR) {
+        pal_ECKeyFree(&key_handle);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((key_handle != NULLPTR && kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_ERROR, "Free key handle failed ");
+    }
+    return kcm_status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/source/cs_hash.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,39 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "pv_error_handling.h"
+#include "cs_hash.h"
+#include "pal_Crypto.h"
+#include "cs_utils.h"
+
+kcm_status_e cs_hash(cs_hash_mode_e mode, const uint8_t *data, size_t data_size, uint8_t *digest, size_t digest_size)
+{
+    palStatus_t pal_status = PAL_SUCCESS;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((data == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid data pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((digest == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid digest pointer");
+  
+    switch (mode) {
+        case CS_SHA256:
+            SA_PV_ERR_RECOVERABLE_RETURN_IF((digest_size != CS_SHA256_SIZE), KCM_STATUS_INVALID_PARAMETER, "Invalid digest size");
+            pal_status = pal_sha256(data, data_size, digest);
+            break;
+        default:
+            SA_PV_ERR_RECOVERABLE_RETURN_IF((true), KCM_CRYPTO_STATUS_UNSUPPORTED_HASH_MODE, "Hash mode not supported");
+    }
+
+    return cs_error_handler(pal_status);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/source/cs_utils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,125 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+#include <stdio.h>
+#include "pv_log.h"
+#include "cs_hash.h"
+#include "cs_der_keys_and_csrs.h"
+#include "cs_der_certs.h"
+#include "pal_Crypto.h"
+#include "pal_errors.h"
+#include "pv_error_handling.h"
+#include "kcm_internal.h"
+
+
+kcm_status_e cs_error_handler(palStatus_t pal_status)
+{
+    switch (pal_status) {
+        case PAL_SUCCESS:
+            return KCM_STATUS_SUCCESS;
+        case PAL_ERR_NOT_SUPPORTED_CURVE:
+            return KCM_CRYPTO_STATUS_UNSUPPORTED_CURVE;
+        case PAL_ERR_INVALID_ARGUMENT:
+            return KCM_STATUS_INVALID_PARAMETER;
+        case PAL_ERR_CREATION_FAILED:
+            return KCM_STATUS_OUT_OF_MEMORY;
+        case PAL_ERR_CERT_PARSING_FAILED:
+            return KCM_CRYPTO_STATUS_PARSING_DER_CERT;
+        case PAL_ERR_X509_BADCERT_EXPIRED:
+            return KCM_CRYPTO_STATUS_CERT_EXPIRED;
+        case PAL_ERR_X509_BADCERT_FUTURE:
+            return KCM_CRYPTO_STATUS_CERT_FUTURE;
+        case PAL_ERR_X509_BADCERT_BAD_MD:
+            return KCM_CRYPTO_STATUS_CERT_MD_ALG;
+        case PAL_ERR_X509_BADCERT_BAD_PK:
+            return KCM_CRYPTO_STATUS_CERT_PUB_KEY_TYPE;
+        case PAL_ERR_X509_BADCERT_NOT_TRUSTED:
+            return KCM_CRYPTO_STATUS_CERT_NOT_TRUSTED;
+        case PAL_ERR_X509_BADCERT_BAD_KEY:
+            return KCM_CRYPTO_STATUS_CERT_PUB_KEY;
+        case PAL_ERR_PARSING_PUBLIC_KEY:
+            return KCM_CRYPTO_STATUS_PARSING_DER_PUBLIC_KEY;
+        case PAL_ERR_PARSING_PRIVATE_KEY:
+            return KCM_CRYPTO_STATUS_PARSING_DER_PRIVATE_KEY;
+        case PAL_ERR_PRIVATE_KEY_VARIFICATION_FAILED:
+            return KCM_CRYPTO_STATUS_PRIVATE_KEY_VERIFICATION_FAILED;
+        case PAL_ERR_PUBLIC_KEY_VARIFICATION_FAILED:
+             return KCM_CRYPTO_STATUS_PUBLIC_KEY_VERIFICATION_FAILED;
+        case PAL_ERR_PK_UNKNOWN_PK_ALG:
+            return KCM_CRYPTO_STATUS_PK_UNKNOWN_PK_ALG;
+        case PAL_ERR_PK_KEY_INVALID_FORMAT:
+            return KCM_CRYPTO_STATUS_PK_KEY_INVALID_FORMAT;
+        case PAL_ERR_PK_INVALID_PUBKEY_AND_ASN1_LEN_MISMATCH:
+            return KCM_CRYPTO_STATUS_INVALID_PK_PUBKEY;
+        case PAL_ERR_ECP_INVALID_KEY:
+            return KCM_CRYPTO_STATUS_ECP_INVALID_KEY;
+        case  PAL_ERR_PK_KEY_INVALID_VERSION:
+            return KCM_CRYPTO_STATUS_PK_KEY_INVALID_VERSION;
+        case PAL_ERR_PK_PASSWORD_REQUIRED:
+            return KCM_CRYPTO_STATUS_PK_PASSWORD_REQUIRED;
+        case PAL_ERR_NO_MEMORY:
+            return KCM_STATUS_OUT_OF_MEMORY;
+        case PAL_ERR_BUFFER_TOO_SMALL:
+            return KCM_STATUS_INSUFFICIENT_BUFFER;
+        case PAL_ERR_INVALID_X509_ATTR:
+            return KCM_CRYPTO_STATUS_INVALID_X509_ATTR;
+        case PAL_ERR_PK_SIG_VERIFY_FAILED:
+            return KCM_CRYPTO_STATUS_VERIFY_SIGNATURE_FAILED;
+        case PAL_ERR_FAILED_TO_COPY_KEYPAIR:
+            return KCM_CRYPTO_STATUS_ECP_INVALID_KEY;
+        case PAL_ERR_FAILED_TO_COPY_GROUP:
+            return KCM_CRYPTO_STATUS_UNSUPPORTED_CURVE;
+        case PAL_ERR_INVALID_MD_TYPE:
+            return KCM_CRYPTO_STATUS_INVALID_MD_TYPE;
+        case PAL_ERR_FAILED_TO_WRITE_SIGNATURE:
+            return KCM_CRYPTO_STATUS_FAILED_TO_WRITE_SIGNATURE;
+        case PAL_ERR_FAILED_TO_WRITE_PRIVATE_KEY:
+            return KCM_CRYPTO_STATUS_FAILED_TO_WRITE_PRIVATE_KEY;
+        case PAL_ERR_FAILED_TO_WRITE_PUBLIC_KEY:
+            return KCM_CRYPTO_STATUS_FAILED_TO_WRITE_PUBLIC_KEY;
+        case PAL_ERR_CSR_WRITE_DER_FAILED:
+            return KCM_CRYPTO_STATUS_FAILED_TO_WRITE_CSR;
+        case PAL_ERR_X509_UNKNOWN_OID:
+            return KCM_CRYPTO_STATUS_INVALID_OID;
+        case PAL_ERR_X509_INVALID_NAME:
+            return KCM_CRYPTO_STATUS_INVALID_NAME_FORMAT;
+        default:
+           return  KCM_STATUS_ERROR;
+    }
+}
+
+/* The function checks private and certificate's public key correlation
+*/
+kcm_status_e cs_check_certifcate_public_key(palX509Handle_t x509_cert, const uint8_t *private_key_data, size_t size_of_private_key_data)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    uint8_t out_sign[KCM_ECDSA_SECP256R1_MAX_SIGNATURE_SIZE_IN_BYTES] = { 0 };
+    size_t size_of_sign = sizeof(out_sign);
+    size_t act_size_of_sign = 0;
+    const uint8_t hash_digest[] =
+    { 0x34, 0x70, 0xCD, 0x54, 0x7B, 0x0A, 0x11, 0x5F, 0xE0, 0x5C, 0xEB, 0xBC, 0x07, 0xBA, 0x91, 0x88,
+        0x27, 0x20, 0x25, 0x6B, 0xB2, 0x7A, 0x66, 0x89, 0x1A, 0x4B, 0xB7, 0x17, 0x11, 0x04, 0x86, 0x6F };
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    kcm_status = cs_ecdsa_sign(private_key_data, size_of_private_key_data, hash_digest, sizeof(hash_digest), out_sign, size_of_sign, &act_size_of_sign);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "cs_ecdsa_sign failed");
+
+    kcm_status = cs_x509_cert_verify_signature(x509_cert, hash_digest, sizeof(hash_digest), out_sign, act_size_of_sign);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "cs_x509_cert_verify_signature failed");
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return kcm_status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/crypto-service/source/include/cs_utils.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,58 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __CS_UTILS_H__
+#define __CS_UTILS_H__
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include "pal.h"
+#include "kcm_status.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**Convert pal status to crypto service status
+*
+*@pal_status – pal status as returned from PAL API.
+*
+*@return
+*    Status from  kcm_status_e corresponding to pal status.
+*/
+kcm_status_e cs_error_handler(palStatus_t pal_status);
+
+/**Checks correlation between certificate's public key and private key
+*
+*@x509_cert[in] - handle of x509 certificate.
+*@size_of_device_cert[in] - size of certificate data.
+*@private_key_data[in] - pointer to private key der data.
+*@size_of_private_key_data[in] - size of private key data.
+*
+*@return
+*    Status from  kcm_status_e corresponding to pal status.
+*/
+kcm_status_e cs_check_certifcate_public_key(palX509Handle_t x509_cert,
+    const uint8_t *private_key_data,
+    size_t size_of_private_key_data);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  //__CS_UTILS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/factory-configurator-client/factory_configurator_client.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,216 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FACTORY_CONFIGURATOR_CLIENT_H__
+#define __FACTORY_CONFIGURATOR_CLIENT_H__
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include "fcc_status.h"
+#include "fcc_output_info_handler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* @file factory_configurator_client.h
+*  \brief factory configurator client APIs.
+*/
+
+/* === Initialization and Finalization === */
+
+/** Initiates the FCC module. Must be called before any other fcc's APIs. Otherwise relevant error will be returned.
+*
+*   @returns
+*       FCC_STATUS_SUCCESS in case of success or one of the `::fcc_status_e` errors otherwise.
+*/
+fcc_status_e fcc_init(void);
+
+
+/** Finalizes the FCC module.
+*   Finalizes and frees file storage resources.
+*
+*    @returns
+*       FCC_STATUS_SUCCESS in case of success or one of the `::fcc_status_e` errors otherwise.
+*/
+
+fcc_status_e fcc_finalize(void);
+
+/* === Factory clean operation === */
+
+/** Cleans from the device all data that was saved during the factory process.
+*  Should be called if the process failed and needs to be executed again.
+*
+*   @returns
+*       FCC_STATUS_SUCCESS in case of success or one of the `::fcc_status_e` errors otherwise.
+*/
+fcc_status_e fcc_storage_delete(void);
+
+
+/* === Warning and errors data operations === */
+
+/** The function retrieves pointer to warning and errors structure.
+*  Should be called after fcc_verify_device_configured_4mbed_cloud, when possible warning and errors was
+*  stored in the structure.
+*  The structure contains data of last fcc_verify_device_configured_4mbed_cloud run.*
+*   @returns pointer to fcc_output_info_s structure.
+*
+*  Example:
+*  @code
+*  void print_fcc_output_info(fcc_output_info_s *output_info)
+*  {
+*      fcc_warning_info_s *warning_list = NULL;
+*
+*      if (output_info != NULL) {
+*          // Check if there is an error
+*          if (output_info->error_string_info != NULL) {
+*              // Print the error string
+*              printf("fcc output error: %s", output_info->error_string_info);
+*          }
+*          // Check if there are warnings
+*          if (output_info->size_of_warning_info_list > 0) {
+*              // Set warning_list to point on the head of the list
+*              warning_list = output_info->head_of_warning_list;
+*
+*              // Iterate the list
+*              while (warning_list != NULL) {
+*                  // Print the warning string
+*                  printf("fcc output warning: %s", warning_list->warning_info_string);
+*                  // Move warning_list to point on the next warning in he list
+*                  warning_list = warning_list->next;
+*              }
+*          }
+*      }
+*  }
+*  @endcode
+*
+*/
+fcc_output_info_s* fcc_get_error_and_warning_data(void);
+
+/** The function returns status of current session between the FCC and the FCU.
+* If the returned value is true - the session should be finished in the communication layer after current message processing,
+* if the return value is false - the session should be kept alive for next message.
+*
+*    @returns
+*       bool
+*/
+bool fcc_is_session_finished(void);
+
+/* === Verification === */
+
+/** Verifies that all mandatory fields needed to connect to mbed Cloud are in place on the device.
+ *  Should be called in the end of the factory process
+ *
+ *    @returns
+ *       FCC_STATUS_SUCCESS in case of success or one of the `::fcc_status_e` errors otherwise.
+ */
+fcc_status_e fcc_verify_device_configured_4mbed_cloud(void);
+
+
+/* === Secure Time === */
+
+/** Sets device time. This function will set the device time to what the user provides.
+*   Device time must be set in order to enable certificate expiration validations.
+*
+*     @param time The device time to set. As epoch time (number of seconds that have elapsed since January 1, 1970)
+*
+*     @returns
+*        Operation status.
+*/
+fcc_status_e fcc_time_set(uint64_t time);
+
+
+/* === Entropy and RoT injection === */
+
+/** Sets Entropy.
+*   If  device does not have its own entropy - this function must be called after fcc_init() and prior to any other FCC or KCM functions.
+*   This API should be used if device has its own entropy and user wishes to add his own entropy.
+*
+*     @param buf The buffer containing the entropy.
+*     @param buf_size The size of buf in bytes. Must be exactly FCC_ENTROPY_SIZE.
+*
+*     @returns
+*        Operation status.
+*/
+fcc_status_e fcc_entropy_set(const uint8_t *buf, size_t buf_size);
+
+/** Sets root of trust
+*   If user wishes to set his own root of trust, this function must be called after fcc_init() and fcc_entropy_set() (if user sets his own entropy),
+*   and prior to any other FCC or KCM functions.
+*
+*     @param buf The buffer containing the root of trust.
+*     @param buf_size The size of buf in bytes. Must be exactly FCC_ROT_SIZE.
+*
+*     @returns
+*        Operation status.
+*/
+fcc_status_e fcc_rot_set(const uint8_t *buf, size_t buf_size);
+
+/* === Bootstrap CA certificate identification storage === */
+
+/** The function sets bootstrap ca identification and stores it.
+*   Should be called only after storing bootstrap ca certificate on the device.
+*
+*     @returns
+*        Operation status.
+*/
+fcc_status_e fcc_trust_ca_cert_id_set(void);
+
+
+/* === Factory flow disable === */
+/** Sets Factory disabled flag to disable further use of the factory flow.
+*
+*     @returns
+*        Operation status.
+*/
+fcc_status_e fcc_factory_disable(void);
+
+/** Returns true if the factory flow was disabled by calling fcc_factory_disable() API, outherwise
+*   returns false.
+*
+*   - If the factory flow is already disabled any FCC API(s) will fail.
+*
+*     @param fcc_factory_disable An output parameter, will be set to "true" in case factory
+*                                     flow is already disabled, "false" otherwise.
+*
+*   @returns
+*       FCC_STATUS_SUCCESS in case of success or one of the `::fcc_status_e` errors otherwise.
+*/
+fcc_status_e fcc_is_factory_disabled(bool *fcc_factory_disable);
+
+/* === Developer flow === */
+
+/** This API is for developers only.
+*   You can download the `mbed_cloud_dev_credentials.c` file from the portal and thus, skip running FCU on PC side.
+*   The API reads all credentials from the `mbed_cloud_dev_credentials.c` file and stores them in the KCM.
+*   RoT, Entropy and Time configurations are not a part of fcc_developer_flow() API. Devices that need to set RoT or Entropy
+*   should call `fcc_rot_set()`/`fcc_entropy_set()` APIs before fcc_developer_flow().
+*   If device does not have it's own time configuration and `fcc_time_set()` was not called before  fcc_developer_flow(),
+*   during fcc_verify_device_configured_4mbed_cloud() certificate time validity will not be checked.
+*
+*
+*   @returns
+*       FCC_STATUS_SUCCESS in case of success or one of the `::fcc_status_e` errors otherwise.
+*/
+fcc_status_e fcc_developer_flow(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__FACTORY_CONFIGURATOR_CLIENT_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/factory-configurator-client/fcc_defs.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,186 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FCC_DEFS_H__
+#define __FCC_DEFS_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+* @file fcc_defs.h
+*  \brief factory configurator client defines.
+* Contains the names of all parameters needed to configure the device to work with mbed Cloud.
+*/
+/*
+* Warnings linked list structure
+*/
+struct fcc_warning_info_ {
+    //Example for warning_info_string - "Certificate is self signed:mbed.BootstrapServerCACert"
+    char *warning_info_string;// pattern of the warning string - warning_string:item_name
+    struct fcc_warning_info_ *next;
+};
+typedef struct fcc_warning_info_ fcc_warning_info_s;
+/**
+* Output info structure
+*/
+typedef struct fcc_output_info_ {
+    //Example for error_string_info - "Invalid certificate:mbed.BootstrapServerCACert"
+    char *error_string_info; // pattern of the error string - error_string:failed_item_name. Only one error string is possible.
+    size_t size_of_warning_info_list; // size of warning_info_list
+    struct fcc_warning_info_ *head_of_warning_list; //The head of warning list
+    struct fcc_warning_info_ *tail_of_warning_list; //The tail of warning list
+} fcc_output_info_s;
+/*=== Device general information ===*/
+
+/**
+* Bootstrap mode parameter name.
+*/
+extern const char g_fcc_use_bootstrap_parameter_name[];
+
+/**
+* Endpoint parameter name.
+*/
+extern const char g_fcc_endpoint_parameter_name[];
+
+/**
+* First to claim parameter name.
+*/
+extern const char g_fcc_first_to_claim_parameter_name[];
+
+/*=== Device meta data ===*/
+
+/**
+* Manufacturer parameter name.
+*/
+extern const char g_fcc_manufacturer_parameter_name[];
+
+/**
+* Model number parameter name.
+*/
+extern const char g_fcc_model_number_parameter_name[];
+
+/**
+* Device type parameter name.
+*/
+extern const char g_fcc_device_type_parameter_name[];
+
+/**
+* Hardware version parameter name.
+*/
+extern const char g_fcc_hardware_version_parameter_name[];
+
+/**
+* Memory size parameter name.
+*/
+extern const char g_fcc_memory_size_parameter_name[];
+
+/**
+* Device serial number parameter name.
+*/
+extern const char g_fcc_device_serial_number_parameter_name[];
+
+/**
+* Device current time parameter name.
+*/
+extern const char g_fcc_current_time_parameter_name[];
+/**
+* Device time zone name.
+*/
+extern const  char g_fcc_device_time_zone_parameter_name[];
+/**
+* Offset of the device timezone from UTC name.
+*/
+extern const char g_fcc_offset_from_utc_parameter_name[];
+
+/*=== Bootstrap configuration ===*/
+
+/**
+* Bootstrap server CA certificate parameter name.
+*/
+extern const char g_fcc_bootstrap_server_ca_certificate_name[];
+
+/**
+* Bootstrap server CRL parameter name.
+*/
+extern const char g_fcc_bootstrap_server_crl_name[];
+
+/**
+* Bootstrap server URI parameter name.
+*/
+extern const char g_fcc_bootstrap_server_uri_name[];
+
+/**
+* Bootstrap device certificate parameter name.
+*/
+extern const char g_fcc_bootstrap_device_certificate_name[];
+
+/**
+* Bootstrap device private key parameter name.
+*/
+extern const char g_fcc_bootstrap_device_private_key_name[];
+
+/*=== LWM2M configuration ===*/
+
+/**
+* LWM2M server CA certificate parameter name.
+*/
+extern const char g_fcc_lwm2m_server_ca_certificate_name[];
+
+/**
+* LWM2M server CRL parameter name.
+*/
+extern const char g_fcc_lwm2m_server_crl_name[];
+
+/**
+* LWM2M server URI parameter name.
+*/
+extern const char g_fcc_lwm2m_server_uri_name[];
+
+/**
+* LWM2M device certificate parameter name.
+*/
+extern const char g_fcc_lwm2m_device_certificate_name[];
+
+/**
+* LWM2M device private key parameter name.
+*/
+extern const char g_fcc_lwm2m_device_private_key_name[];
+
+/**
+* Firmware update authentication certificate parameter name.
+*/
+extern const char g_fcc_update_authentication_certificate_name[];
+
+
+/**
+* Firmware update class id name.
+*/
+extern const char g_fcc_class_id_name[];
+
+/**
+* Firmware update vendor id name.
+*/
+
+extern const char g_fcc_vendor_id_name[];
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__FCC_DEFS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/factory-configurator-client/fcc_status.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,73 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FCC_STATUS_H__
+#define __FCC_STATUS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+* @file fcc_status.h
+*  \brief factory configurator client status/error codes.
+* This list may grow as needed.
+*/
+    typedef enum {
+        FCC_STATUS_SUCCESS  = 0,                    //!< Operation completed successfully.
+        FCC_STATUS_ERROR,                      //!< Operation ended with an unspecified error.
+        FCC_STATUS_MEMORY_OUT,                 //!< An out-of-memory condition occurred.
+        FCC_STATUS_INVALID_PARAMETER,          //!< A parameter provided to the function was invalid.
+        FCC_STATUS_STORE_ERROR,                //!< Storage internal error.
+        FCC_STATUS_INTERNAL_ITEM_ALREADY_EXIST,//!< Current item already exists in storage.
+        FCC_STATUS_CA_ERROR,                   //!< CA Certificate already exist in storage (currently only bootstrap CA)
+        FCC_STATUS_ROT_ERROR,                  //!< ROT already exist in storage
+        FCC_STATUS_ENTROPY_ERROR,              //!< Entropy already exist in storage
+        FCC_STATUS_FACTORY_DISABLED_ERROR,     //!< FCC flow was disabled - denial of service error.
+        FCC_STATUS_INVALID_CERTIFICATE,        //!< Invalid certificate found.
+        FCC_STATUS_INVALID_CERT_ATTRIBUTE,     //!< Operation failed to get an attribute.
+        FCC_STATUS_INVALID_CA_CERT_SIGNATURE,  //!< Invalid ca signature.
+        FCC_STATUS_EXPIRED_CERTIFICATE,        //!< Certificate is expired.
+        FCC_STATUS_INVALID_LWM2M_CN_ATTR,      //!< Invalid CN field of certificate.
+        FCC_STATUS_KCM_ERROR,                  //!< KCM basic functionality failed.
+        FCC_STATUS_KCM_STORAGE_ERROR,          //!< KCM failed to read, write or get size of item from/to storage.
+        FCC_STATUS_KCM_FILE_EXIST_ERROR,       //!< KCM tried to create existing storage item.
+        FCC_STATUS_KCM_CRYPTO_ERROR,           //!< KCM returned error upon cryptographic check of an certificate or key.
+        FCC_STATUS_NOT_INITIALIZED,            //!< FCC failed or did not initialized.
+        FCC_STATUS_BUNDLE_ERROR,               //!< Protocol layer general error.
+        FCC_STATUS_BUNDLE_RESPONSE_ERROR,      //!< Protocol layer failed to create response buffer.
+        FCC_STATUS_BUNDLE_UNSUPPORTED_GROUP,   //!< Protocol layer detected unsupported group was found in a message.
+        FCC_STATUS_BUNDLE_INVALID_GROUP,       //!< Protocol layer detected invalid group in a message.
+        FCC_STATUS_BUNDLE_INVALID_SCHEME,      //!< The scheme version of a message in the protocol layer is wrong.
+        FCC_STATUS_ITEM_NOT_EXIST,             //!< Current item wasn't found in the storage
+        FCC_STATUS_EMPTY_ITEM,                 //!< Current item's size is 0
+        FCC_STATUS_WRONG_ITEM_DATA_SIZE,       //!< Current item's size is different then expected
+        FCC_STATUS_URI_WRONG_FORMAT,           //!< Current URI is different than expected.
+        FCC_STATUS_FIRST_TO_CLAIM_NOT_ALLOWED, //!< Can't use first to claim without bootstrap or with account ID
+        FCC_STATUS_BOOTSTRAP_MODE_ERROR,       //!< Wrong value of bootstrapUse mode.
+        FCC_STATUS_OUTPUT_INFO_ERROR,          //!< The process failed in output info creation.
+        FCC_STATUS_WARNING_CREATE_ERROR,       //!< The process failed in output info creation.
+        FCC_STATUS_UTC_OFFSET_WRONG_FORMAT,    //!< Current UTC is wrong.
+        FCC_STATUS_CERTIFICATE_PUBLIC_KEY_CORRELATION_ERROR, //!< Certificate's public key failed do not matches to corresponding private key        
+        FCC_STATUS_BUNDLE_INVALID_KEEP_ALIVE_SESSION_STATUS,//!< The message status is invalid.
+        FCC_STATUS_TOO_MANY_CSR_REQUESTS,     //!< The message contained more than CSR_MAX_NUMBER_OF_CSRS CSR requests
+        FCC_MAX_STATUS = 0x7fffffff
+} fcc_status_e;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__FCC_STATUS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/factory_configurator_client.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,341 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "factory_configurator_client.h"
+#include "fcc_sotp.h"
+#include "key_config_manager.h"
+#include "pv_error_handling.h"
+#include "fcc_verification.h"
+#include "storage.h"
+#include "fcc_defs.h"
+#include "fcc_malloc.h"
+#include "common_utils.h"
+#include "pal.h"
+
+/**
+* Device general info
+*/
+const char g_fcc_use_bootstrap_parameter_name[] = "mbed.UseBootstrap";
+const char g_fcc_endpoint_parameter_name[] = "mbed.EndpointName";
+const char g_fcc_account_id_parameter_name[] = "mbed.AccountID";
+const char g_fcc_first_to_claim_parameter_name[] = "mbed.FirstToClaim";
+
+/**
+* Device meta data
+*/
+const char g_fcc_manufacturer_parameter_name[] = "mbed.Manufacturer";
+const char g_fcc_model_number_parameter_name[] = "mbed.ModelNumber";
+const char g_fcc_device_type_parameter_name[] = "mbed.DeviceType";
+const char g_fcc_hardware_version_parameter_name[] = "mbed.HardwareVersion";
+const char g_fcc_memory_size_parameter_name[] = "mbed.MemoryTotalKB";
+const char g_fcc_device_serial_number_parameter_name[] = "mbed.SerialNumber";
+/**
+* Time Synchronization
+*/
+const char g_fcc_current_time_parameter_name[] = "mbed.CurrentTime";
+const char g_fcc_device_time_zone_parameter_name[] = "mbed.Timezone";
+const char g_fcc_offset_from_utc_parameter_name[] = "mbed.UTCOffset";
+/**
+* Bootstrap configuration
+*/
+const char g_fcc_bootstrap_server_ca_certificate_name[] = "mbed.BootstrapServerCACert";
+const char g_fcc_bootstrap_server_crl_name[] = "mbed.BootstrapServerCRL";
+const char g_fcc_bootstrap_server_uri_name[] = "mbed.BootstrapServerURI";
+const char g_fcc_bootstrap_device_certificate_name[] = "mbed.BootstrapDeviceCert";
+const char g_fcc_bootstrap_device_private_key_name[] = "mbed.BootstrapDevicePrivateKey";
+/**
+* LWm2m configuration
+*/
+const char g_fcc_lwm2m_server_ca_certificate_name[] = "mbed.LwM2MServerCACert";
+const char g_fcc_lwm2m_server_crl_name[] = "mbed.LwM2MServerCRL";
+const char g_fcc_lwm2m_server_uri_name[] = "mbed.LwM2MServerURI";
+const char g_fcc_lwm2m_device_certificate_name[] = "mbed.LwM2MDeviceCert";
+const char g_fcc_lwm2m_device_private_key_name[] = "mbed.LwM2MDevicePrivateKey";
+/**
+* Firmware update
+*/
+const char g_fcc_update_authentication_certificate_name[] = "mbed.UpdateAuthCert";
+const char g_fcc_class_id_name[] = "mbed.ClassId";
+const char g_fcc_vendor_id_name[] = "mbed.VendorId";
+
+static bool g_is_fcc_initialized = false;
+bool g_is_session_finished = true;
+
+fcc_status_e fcc_init(void)
+{
+    palStatus_t pal_status;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    if (g_is_fcc_initialized) {
+        // No need for second initialization
+        return FCC_STATUS_SUCCESS;
+    }
+    
+    pal_status = pal_init();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), FCC_STATUS_ERROR, "Failed initializing PAL (%" PRIu32 ")", pal_status);
+    
+    //Initialize output info handler
+    fcc_init_output_info_handler();
+
+    g_is_fcc_initialized = true;
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return FCC_STATUS_SUCCESS;
+}
+
+fcc_status_e fcc_finalize(void)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
+
+    //FIXME: add relevant error handling - general task for all APIs.
+    //It is okay to finalize KCM here since it's already initialized beforehand.
+    kcm_status = kcm_finalize();
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        fcc_status = FCC_STATUS_ERROR;
+        SA_PV_LOG_ERR("Failed finalizing KCM");
+    }
+
+    //Finalize output info handler
+    fcc_clean_output_info_handler();
+
+    //Finalize PAL
+    pal_destroy();
+
+    g_is_fcc_initialized = false;
+    g_is_session_finished = true;
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return fcc_status;
+}
+
+fcc_status_e fcc_storage_delete()
+{
+    kcm_status_e status = KCM_STATUS_SUCCESS;
+    sotp_result_e sotp_status = SOTP_SUCCESS;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
+
+    status = storage_reset();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((status == KCM_STATUS_ESFS_ERROR), FCC_STATUS_KCM_STORAGE_ERROR, "Failed in storage_reset. got ESFS error");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), FCC_STATUS_ERROR, "Failed storage reset");
+
+    sotp_status = sotp_reset();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_status != SOTP_SUCCESS), FCC_STATUS_STORE_ERROR, "Failed to reset sotp storage ");
+    
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return FCC_STATUS_SUCCESS;
+}
+
+fcc_output_info_s* fcc_get_error_and_warning_data(void)
+{
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), NULL, "FCC not initialized");
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return get_output_info();
+}
+
+bool fcc_is_session_finished(void)
+{
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    return g_is_session_finished;
+}
+
+fcc_status_e fcc_verify_device_configured_4mbed_cloud(void)
+{
+    fcc_status_e  fcc_status =  FCC_STATUS_SUCCESS;
+    bool use_bootstrap = false;
+    bool success = false;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
+
+    /*Initialize fcc_output_info_s structure.
+    In case output indo struct is not empty in the beginning of the verify process we will clean it.*/
+    fcc_clean_output_info_handler();
+
+    //Check entropy initialization
+    success = fcc_is_entropy_initialized();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((success != true), fcc_status = FCC_STATUS_ENTROPY_ERROR, "Entropy is not initialized");
+
+    //Check time synchronization
+    fcc_status = fcc_check_time_synchronization();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to check time synhronization");
+
+    //Get bootstrap mode
+    fcc_status = fcc_get_bootstrap_mode(&use_bootstrap);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to get bootstrap mode");
+
+    // Check general info
+    fcc_status = fcc_check_device_general_info();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to check general info");
+
+    //Check device meta-data
+    fcc_status = fcc_check_device_meta_data();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to check configuration parameters");
+
+    //Check device security objects
+    fcc_status = fcc_check_device_security_objects(use_bootstrap);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to check device security objects");
+
+    //Check firmware integrity
+    fcc_status = fcc_check_firmware_update_integrity();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to check device security objects");
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return fcc_status;
+}
+
+fcc_status_e fcc_entropy_set(const uint8_t *buf, size_t buf_size)
+{
+    fcc_status_e fcc_status;
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
+
+    fcc_status = fcc_sotp_data_store(buf, buf_size, SOTP_TYPE_RANDOM_SEED);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status == FCC_STATUS_INTERNAL_ITEM_ALREADY_EXIST), FCC_STATUS_ENTROPY_ERROR, "Entropy already exist in storage");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to set entropy");
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return FCC_STATUS_SUCCESS;
+}
+
+fcc_status_e fcc_rot_set(const uint8_t *buf, size_t buf_size)
+{
+    fcc_status_e fcc_status;
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
+
+    fcc_status = fcc_sotp_data_store(buf, buf_size, SOTP_TYPE_ROT);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status == FCC_STATUS_INTERNAL_ITEM_ALREADY_EXIST), FCC_STATUS_ROT_ERROR, "RoT already exist in storage");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to set RoT");
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return FCC_STATUS_SUCCESS;
+}
+
+fcc_status_e fcc_time_set(uint64_t time)
+{
+    palStatus_t pal_status;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
+
+    pal_status = pal_osSetStrongTime(time);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), FCC_STATUS_ERROR, "Failed to set new EPOCH time (pal_status = %" PRIu32 ")", pal_status);
+
+    return FCC_STATUS_SUCCESS;
+}
+
+fcc_status_e fcc_is_factory_disabled(bool *is_factory_disabled)
+{
+    fcc_status_e fcc_status;
+    int64_t factory_disable_flag = 0;
+    size_t data_actual_size_out = 0;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((is_factory_disabled == NULL), FCC_STATUS_INVALID_PARAMETER, "Invalid param is_factory_disabled");
+
+    fcc_status = fcc_sotp_data_retrieve((uint8_t *)(&factory_disable_flag), sizeof(factory_disable_flag), &data_actual_size_out, SOTP_TYPE_FACTORY_DONE);
+    SA_PV_LOG_INFO("fcc_status: %d, factory_disable_flag:%" PRIuMAX "\n", fcc_status, factory_disable_flag);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS && fcc_status != FCC_STATUS_ITEM_NOT_EXIST), fcc_status, "Failed for fcc_sotp_buffer_retrieve");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(((factory_disable_flag != 0) && (factory_disable_flag != 1)), FCC_STATUS_FACTORY_DISABLED_ERROR, "Failed for fcc_sotp_buffer_retrieve");
+
+    // If we get here - it must be either "0" or "1"
+    *is_factory_disabled = (factory_disable_flag == 1) ? true : false;
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return FCC_STATUS_SUCCESS;
+}
+
+
+fcc_status_e fcc_factory_disable(void)
+{
+    fcc_status_e fcc_status;
+    int64_t factory_disable_flag = 1;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
+
+    fcc_status = fcc_sotp_data_store((uint8_t *)(&factory_disable_flag), sizeof(factory_disable_flag), SOTP_TYPE_FACTORY_DONE);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status == FCC_STATUS_INTERNAL_ITEM_ALREADY_EXIST), FCC_STATUS_FACTORY_DISABLED_ERROR, "FCC already disabled in storage");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed for fcc_sotp_buffer_store");
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return FCC_STATUS_SUCCESS;
+}
+
+
+fcc_status_e fcc_trust_ca_cert_id_set(void)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    uint8_t attribute_data[PAL_CERT_ID_SIZE] = {0};
+    size_t size_of_attribute_data = 0;
+    bool use_bootstrap = false;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!g_is_fcc_initialized), FCC_STATUS_NOT_INITIALIZED, "FCC not initialized");
+
+    fcc_status = fcc_get_bootstrap_mode(&use_bootstrap);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to get bootstrap mode");
+
+
+    //For now this API relevant only for bootstrap certificate.
+    if (use_bootstrap == true) {
+        fcc_status = fcc_get_certificate_attribute_by_name((const uint8_t*)g_fcc_bootstrap_server_ca_certificate_name,
+            (size_t)(strlen(g_fcc_bootstrap_server_ca_certificate_name)),
+            CS_CERT_ID_ATTR,
+            attribute_data,
+            sizeof(attribute_data),
+            &size_of_attribute_data);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to get ca id");
+ 
+        fcc_status = fcc_sotp_data_store(attribute_data, size_of_attribute_data, SOTP_TYPE_TRUSTED_TIME_SRV_ID);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status == FCC_STATUS_INTERNAL_ITEM_ALREADY_EXIST), (fcc_status = FCC_STATUS_CA_ERROR), exit, "CA already exist in storage");
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to set ca id");
+    }
+
+exit:
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_store_error_info((const uint8_t*)g_fcc_bootstrap_server_ca_certificate_name, strlen(g_fcc_bootstrap_server_ca_certificate_name), fcc_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+            fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+            "Failed to set ca identifier error  %d",
+            fcc_status);
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/fcc_dev_flow.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,105 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "factory_configurator_client.h"
+#include "key_config_manager.h"
+#include "fcc_defs.h"
+#include "pv_error_handling.h"
+#include "fcc_utils.h"
+
+typedef struct fcc_deloveper_mode_item_params {
+    const char *item_name;
+    kcm_item_type_e item_kcm_type;
+    const uint8_t *item_data;
+    const uint32_t item_data_size;
+} fcc_deloveper_mode_item_params_s;
+
+//bootstrap endpoint name
+extern const char MBED_CLOUD_DEV_BOOTSTRAP_ENDPOINT_NAME[];
+//bootstrap server uri
+extern const char MBED_CLOUD_DEV_BOOTSTRAP_SERVER_URI[];
+//bootstrap device certificate
+extern const uint8_t MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_CERTIFICATE[];
+extern const uint32_t MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_CERTIFICATE_SIZE;
+//bootstrap server root ca certificate
+extern const uint8_t MBED_CLOUD_DEV_BOOTSTRAP_SERVER_ROOT_CA_CERTIFICATE[];
+extern const uint32_t MBED_CLOUD_DEV_BOOTSTRAP_SERVER_ROOT_CA_CERTIFICATE_SIZE;
+//bootstrap device private key
+extern const uint8_t MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_PRIVATE_KEY[];
+extern const uint32_t MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_PRIVATE_KEY_SIZE;
+//device manufacturer
+extern const char MBED_CLOUD_DEV_MANUFACTURER[];
+//device  model number
+extern const char MBED_CLOUD_DEV_MODEL_NUMBER[];
+//device serial number
+extern const char MBED_CLOUD_DEV_SERIAL_NUMBER[];
+//device type
+extern const char MBED_CLOUD_DEV_DEVICE_TYPE[];
+//device hw version
+extern const char MBED_CLOUD_DEV_HARDWARE_VERSION[];
+//device total memory
+extern const uint32_t MBED_CLOUD_DEV_MEMORY_TOTAL_KB;
+
+
+fcc_status_e fcc_developer_flow(void)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    fcc_status_e  fcc_status =  FCC_STATUS_SUCCESS;
+    const bool is_factory_item = true;
+    static const uint32_t is_bootstrap_mode = 1;
+    const fcc_deloveper_mode_item_params_s fcc_deloveper_mode_item_params_table[] = {
+
+        //param name                                //param kcm type        //param data                                              //param data_size
+        //Device general info
+        { g_fcc_use_bootstrap_parameter_name,          KCM_CONFIG_ITEM,      (const uint8_t*)&is_bootstrap_mode,                       sizeof(uint32_t) },
+        { g_fcc_endpoint_parameter_name,               KCM_CONFIG_ITEM,      (const uint8_t*)MBED_CLOUD_DEV_BOOTSTRAP_ENDPOINT_NAME,   (uint32_t)strlen((char*)MBED_CLOUD_DEV_BOOTSTRAP_ENDPOINT_NAME) },
+        //Bootstrap configuration
+        { g_fcc_bootstrap_device_certificate_name,     KCM_CERTIFICATE_ITEM,  MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_CERTIFICATE,             MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_CERTIFICATE_SIZE },
+        { g_fcc_bootstrap_server_ca_certificate_name,  KCM_CERTIFICATE_ITEM,  MBED_CLOUD_DEV_BOOTSTRAP_SERVER_ROOT_CA_CERTIFICATE,     MBED_CLOUD_DEV_BOOTSTRAP_SERVER_ROOT_CA_CERTIFICATE_SIZE },
+        { g_fcc_bootstrap_device_private_key_name,     KCM_PRIVATE_KEY_ITEM,  MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_PRIVATE_KEY,             MBED_CLOUD_DEV_BOOTSTRAP_DEVICE_PRIVATE_KEY_SIZE },
+        { g_fcc_bootstrap_server_uri_name,             KCM_CONFIG_ITEM,       (const uint8_t*)MBED_CLOUD_DEV_BOOTSTRAP_SERVER_URI,     (uint32_t)strlen((char*)MBED_CLOUD_DEV_BOOTSTRAP_SERVER_URI) },
+        //device meta data
+        { g_fcc_manufacturer_parameter_name,           KCM_CONFIG_ITEM,      (const uint8_t*)MBED_CLOUD_DEV_MANUFACTURER,              (uint32_t)strlen((char*)MBED_CLOUD_DEV_MANUFACTURER) },
+        { g_fcc_model_number_parameter_name,           KCM_CONFIG_ITEM,      (const uint8_t*)MBED_CLOUD_DEV_MODEL_NUMBER,              (uint32_t)strlen((char*)MBED_CLOUD_DEV_MODEL_NUMBER) },
+        { g_fcc_device_serial_number_parameter_name,   KCM_CONFIG_ITEM,      (const uint8_t*)MBED_CLOUD_DEV_SERIAL_NUMBER,             (uint32_t)strlen((char*)MBED_CLOUD_DEV_SERIAL_NUMBER) },
+        { g_fcc_device_type_parameter_name,            KCM_CONFIG_ITEM,      (const uint8_t*)MBED_CLOUD_DEV_DEVICE_TYPE,               (uint32_t)strlen((char*)MBED_CLOUD_DEV_DEVICE_TYPE) },
+        { g_fcc_hardware_version_parameter_name,       KCM_CONFIG_ITEM,      (const uint8_t*)MBED_CLOUD_DEV_HARDWARE_VERSION,          (uint32_t)strlen((char*)MBED_CLOUD_DEV_HARDWARE_VERSION) },
+        { g_fcc_memory_size_parameter_name,            KCM_CONFIG_ITEM,      (const uint8_t*)&MBED_CLOUD_DEV_MEMORY_TOTAL_KB,          sizeof(uint32_t) },
+
+        //last item
+        { NULL,                                       KCM_LAST_ITEM,         NULL,                                                    0},
+    };
+
+    const fcc_deloveper_mode_item_params_s* mandatory_items_iter = &fcc_deloveper_mode_item_params_table[0];
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    for (; mandatory_items_iter->item_name!= NULL; mandatory_items_iter++) {
+
+        kcm_status = kcm_item_store((const uint8_t*)(mandatory_items_iter->item_name), strlen(mandatory_items_iter->item_name), mandatory_items_iter->item_kcm_type, is_factory_item,
+                                    (const uint8_t*)(mandatory_items_iter->item_data), mandatory_items_iter->item_data_size, NULL);
+
+        //FIXME : add relevant error translation.
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_convert_kcm_to_fcc_status(kcm_status), "Store status: %d, Failed to store %s", kcm_status, mandatory_items_iter->item_name);
+    }
+
+    fcc_status = fcc_trust_ca_cert_id_set();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to set ca certificate identifier");
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return fcc_status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/fcc_sotp.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,155 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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,get
+// 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.
+// ----------------------------------------------------------------------------
+
+#include <string.h>
+#include "fcc_sotp.h"
+#include "pv_error_handling.h"
+#include "kcm_internal.h"
+
+static bool get_sotp_type_size(sotp_type_e sotp_type, uint16_t *required_size_out)
+{
+    size_t required_size;
+
+    switch (sotp_type) {
+        case SOTP_TYPE_ROT:
+            required_size = FCC_ROT_SIZE;
+            break;
+        case SOTP_TYPE_FACTORY_DONE:
+            required_size = FCC_FACTORY_DISABLE_FLAG_SIZE;
+            break;
+        case SOTP_TYPE_RANDOM_SEED:
+            required_size = FCC_ENTROPY_SIZE;
+            break;
+        case SOTP_TYPE_SAVED_TIME:
+            required_size = sizeof(uint64_t);
+            break;
+        case SOTP_TYPE_TRUSTED_TIME_SRV_ID:
+            required_size = FCC_CA_IDENTIFICATION_SIZE;
+            break;
+        default:
+            SA_PV_LOG_ERR("Wrong sotp_type");
+            return false;
+    }
+
+    // Success
+    *required_size_out = (uint16_t)required_size;
+
+    return true;
+}
+
+static fcc_status_e sotp_to_fcc_error_translation(sotp_result_e err)
+{
+    fcc_status_e fcc_result;
+    switch(err)
+    {
+        case SOTP_SUCCESS:
+            fcc_result = FCC_STATUS_SUCCESS;
+            break;
+        case SOTP_NOT_FOUND:
+            fcc_result = FCC_STATUS_ITEM_NOT_EXIST;
+            break;
+        case SOTP_ALREADY_EXISTS:
+            fcc_result = FCC_STATUS_INTERNAL_ITEM_ALREADY_EXIST;
+            break;
+        case SOTP_READ_ERROR:
+        case SOTP_WRITE_ERROR:
+        case SOTP_DATA_CORRUPT:
+        case SOTP_BAD_VALUE:
+        case SOTP_BUFF_TOO_SMALL:
+        case SOTP_FLASH_AREA_TOO_SMALL:
+        case SOTP_OS_ERROR:
+        case SOTP_BUFF_NOT_ALIGNED:
+        default:
+            fcc_result = FCC_STATUS_STORE_ERROR;
+            break;
+    }
+    return fcc_result;
+}
+
+
+fcc_status_e fcc_sotp_data_store(const uint8_t *data, size_t data_size, sotp_type_e sotp_type)
+{
+    bool success;
+    sotp_result_e sotp_result;
+    uint16_t required_size = 0;
+    int64_t aligned_8_bytes_buffer[MAX_SOTP_BUFFER_SIZE / 8];
+    uint16_t sotp_buffer_size = 0;
+
+    SA_PV_LOG_INFO_FUNC_ENTER("data_size = %" PRIu32 " sotp_type = %d", (uint32_t)data_size, (int)sotp_type);
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((data == NULL), FCC_STATUS_INVALID_PARAMETER, "Invalid param data");
+
+    success = get_sotp_type_size(sotp_type, &required_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!success), FCC_STATUS_INVALID_PARAMETER, "Failed for get_sotp_type_size()");
+
+    if (sotp_type != SOTP_TYPE_SAVED_TIME) {
+        //Check if current type was already written to sotp by triyng to get the data
+        sotp_result = sotp_get_item_size(sotp_type, &sotp_buffer_size);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_result == SOTP_SUCCESS), FCC_STATUS_INTERNAL_ITEM_ALREADY_EXIST, "The item was already written to sotp");
+    }
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size != required_size), FCC_STATUS_INVALID_PARAMETER, "Wrong buf_size provided. Must be size of exactly %" PRIu32 " bytes", (uint32_t)required_size);
+
+    // Write buf to SOTP. Cast is OK since size must be divisible by 8
+    
+    /*
+    * Copy from data (uint8_t*) to aligned_8_bytes_buffer (uint64_t*) to make sure that data is 8 byte aligned.
+    * Since sotp_set() gets a pointer to int64_t, if it is not aligned, and we just cast it to uint8_t*,
+    * ARMCC functions like memcpy will assume 8 byte alignment resulting in possible access of unallocated memory. 
+    */
+    memcpy(aligned_8_bytes_buffer, data, data_size);
+
+    sotp_result = sotp_set(sotp_type, (uint16_t)(data_size), (const uint32_t*)aligned_8_bytes_buffer);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_result != SOTP_SUCCESS) , sotp_to_fcc_error_translation(sotp_result), "SOTP set failed");
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return FCC_STATUS_SUCCESS;
+}
+
+
+fcc_status_e fcc_sotp_data_retrieve(uint8_t *data_out, size_t data_size_max, size_t *data_actual_size_out, sotp_type_e sotp_type)
+{
+    bool success;
+    sotp_result_e sotp_result;
+    uint16_t required_size = 0;
+    int64_t aligned_8_bytes_buffer[MAX_SOTP_BUFFER_SIZE / 8] = {0};
+    uint16_t actual_data_size = 0;
+
+    SA_PV_LOG_INFO_FUNC_ENTER("data_out = %" PRIu32 " sotp_type = %d", (uint32_t)data_size_max, (int)sotp_type);
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((data_out == NULL), FCC_STATUS_INVALID_PARAMETER, "invalid param data_out");
+
+    success = get_sotp_type_size(sotp_type, &required_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!success), FCC_STATUS_INVALID_PARAMETER, "Failed for get_sotp_type_size()");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((data_size_max < required_size), FCC_STATUS_ERROR, "Wrong buf_size provided. Must be size of exactly %" PRIu32 " bytes", (uint32_t)required_size);
+
+    // Retrieve buf from SOTP. Cast is OK since size must be multiple of 8
+    sotp_result = sotp_get(sotp_type, (uint16_t)data_size_max, (uint32_t*)aligned_8_bytes_buffer, &actual_data_size);
+    if (sotp_result == SOTP_NOT_FOUND) { //To prevent error log for positive flows
+        return sotp_to_fcc_error_translation(sotp_result);
+    }
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_result != SOTP_SUCCESS), sotp_to_fcc_error_translation(sotp_result), "SOTP_Get failed");
+
+    // Copy from aligned buffer to callers uint8_t* buffer
+    memcpy(data_out, aligned_8_bytes_buffer, actual_data_size);
+
+    *data_actual_size_out = (size_t)(actual_data_size);
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return FCC_STATUS_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/fcc_utils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,147 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "factory_configurator_client.h"
+#include "fcc_status.h"
+#include "fcc_utils.h"
+#include "key_config_manager.h"
+#include "pv_error_handling.h"
+#include "fcc_sotp.h"
+
+
+const char g_sotp_entropy_data_type_name[] = "EntropyData";
+const char g_sotp_rot_data_type_name[] = "ROTData";
+const char g_sotp_factory_disable_type_name[] = "FactoryDisableFlag";
+const char g_sotp_ca_server_id_type_name[] = "CAServerId";
+const char g_sotp_time_type_name[] = "Time";
+const char g_sotp_wrong_type_name[] = "Wrong_sotp_type";
+
+
+fcc_status_e fcc_get_sotp_type_name(sotp_type_e sotp_type,char **sotp_type_name, size_t *sotp_type_name_size)
+{
+
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((sotp_type_name_size == NULL), fcc_status, "Wrong sotp_type_name_size pointer");
+
+    switch (sotp_type) {
+    case SOTP_TYPE_ROT:
+        *sotp_type_name = (char*)g_sotp_rot_data_type_name;
+        *sotp_type_name_size = (size_t)strlen(g_sotp_rot_data_type_name);
+        break;
+    case SOTP_TYPE_FACTORY_DONE:
+        *sotp_type_name = (char*)g_sotp_factory_disable_type_name;
+        *sotp_type_name_size = (size_t)strlen(g_sotp_factory_disable_type_name);
+        break;
+    case SOTP_TYPE_RANDOM_SEED:
+        *sotp_type_name = (char*)g_sotp_entropy_data_type_name;
+        *sotp_type_name_size = (size_t)strlen(g_sotp_entropy_data_type_name);
+        break;
+    case SOTP_TYPE_SAVED_TIME:
+        *sotp_type_name = (char*)g_sotp_time_type_name;
+        *sotp_type_name_size = (size_t)strlen(g_sotp_time_type_name);
+        break;
+    case SOTP_TYPE_TRUSTED_TIME_SRV_ID:
+        *sotp_type_name = (char*)g_sotp_ca_server_id_type_name;
+        *sotp_type_name_size = (size_t)strlen(g_sotp_ca_server_id_type_name);
+        break;
+    default:
+        SA_PV_LOG_ERR("Non existent sotp_type provided");
+        *sotp_type_name = (char*)g_sotp_wrong_type_name;
+        *sotp_type_name_size = (size_t)strlen(g_sotp_wrong_type_name);
+        return FCC_STATUS_INVALID_PARAMETER;
+    }
+
+    return fcc_status;
+}
+
+fcc_status_e fcc_convert_kcm_to_fcc_status(kcm_status_e kcm_result)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+
+    switch (kcm_result) {
+        case KCM_STATUS_SUCCESS:
+            fcc_status = FCC_STATUS_SUCCESS;
+            break;
+        case KCM_STATUS_ERROR:
+        case KCM_STATUS_INVALID_PARAMETER:
+        case KCM_STATUS_OUT_OF_MEMORY:
+        case KCM_STATUS_INSUFFICIENT_BUFFER:
+            fcc_status = FCC_STATUS_KCM_ERROR;
+            break;
+        case KCM_STATUS_ITEM_NOT_FOUND:
+            fcc_status = FCC_STATUS_ITEM_NOT_EXIST;
+            break;
+        case KCM_STATUS_STORAGE_ERROR:
+        case KCM_STATUS_META_DATA_NOT_FOUND:
+        case KCM_STATUS_META_DATA_SIZE_ERROR:
+        case KCM_STATUS_NOT_PERMITTED:
+        case KCM_STATUS_ITEM_IS_EMPTY:
+        case KCM_STATUS_INVALID_FILE_VERSION:
+        case KCM_STATUS_UNKNOWN_STORAGE_ERROR:
+        case KCM_STATUS_NOT_INITIALIZED:
+        case KCM_STATUS_CLOSE_INCOMPLETE_CHAIN:
+        case KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN:
+        case KCM_STATUS_FILE_CORRUPTED:
+        case KCM_STATUS_FILE_NAME_CORRUPTED:
+        case KCM_STATUS_INVALID_FILE_ACCESS_MODE:
+        case KCM_STATUS_CORRUPTED_CHAIN_FILE:
+        case KCM_STATUS_FILE_NAME_TOO_LONG:
+            fcc_status = FCC_STATUS_KCM_STORAGE_ERROR;
+            break;
+        case KCM_STATUS_SELF_GENERATED_CERTIFICATE_VERIFICATION_ERROR:
+            fcc_status = FCC_STATUS_CERTIFICATE_PUBLIC_KEY_CORRELATION_ERROR;
+            break;
+        case KCM_STATUS_FILE_EXIST:
+        case KCM_STATUS_KEY_EXIST:
+            fcc_status = FCC_STATUS_KCM_FILE_EXIST_ERROR;
+            break;
+        case KCM_CRYPTO_STATUS_UNSUPPORTED_HASH_MODE:
+        case KCM_CRYPTO_STATUS_PARSING_DER_PRIVATE_KEY:
+        case KCM_CRYPTO_STATUS_PARSING_DER_PUBLIC_KEY:
+        case KCM_CRYPTO_STATUS_PK_KEY_INVALID_FORMAT:
+        case KCM_CRYPTO_STATUS_INVALID_PK_PUBKEY:
+        case KCM_CRYPTO_STATUS_ECP_INVALID_KEY:
+        case KCM_CRYPTO_STATUS_PK_KEY_INVALID_VERSION:
+        case KCM_CRYPTO_STATUS_PK_PASSWORD_REQUIRED:
+        case KCM_CRYPTO_STATUS_PRIVATE_KEY_VERIFICATION_FAILED:
+        case KCM_CRYPTO_STATUS_PUBLIC_KEY_VERIFICATION_FAILED:
+        case KCM_CRYPTO_STATUS_PK_UNKNOWN_PK_ALG:
+        case KCM_CRYPTO_STATUS_UNSUPPORTED_CURVE:
+        case KCM_CRYPTO_STATUS_PARSING_DER_CERT:
+        case KCM_CRYPTO_STATUS_CERT_EXPIRED:
+        case KCM_CRYPTO_STATUS_CERT_FUTURE:
+        case KCM_CRYPTO_STATUS_CERT_MD_ALG:
+        case KCM_CRYPTO_STATUS_CERT_PUB_KEY_TYPE:
+        case KCM_CRYPTO_STATUS_CERT_PUB_KEY:
+        case KCM_CRYPTO_STATUS_CERT_NOT_TRUSTED:
+        case KCM_CRYPTO_STATUS_INVALID_X509_ATTR:
+        case KCM_CRYPTO_STATUS_VERIFY_SIGNATURE_FAILED:
+        case KCM_CRYPTO_STATUS_INVALID_MD_TYPE:
+        case KCM_CRYPTO_STATUS_FAILED_TO_WRITE_SIGNATURE:
+        case KCM_STATUS_CERTIFICATE_CHAIN_VERIFICATION_FAILED:
+        case KCM_CRYPTO_STATUS_FAILED_TO_WRITE_PRIVATE_KEY:
+        case KCM_CRYPTO_STATUS_FAILED_TO_WRITE_PUBLIC_KEY:
+        case KCM_CRYPTO_STATUS_INVALID_OID:
+        case KCM_CRYPTO_STATUS_INVALID_NAME_FORMAT:
+        case KCM_CRYPTO_STATUS_FAILED_TO_WRITE_CSR:
+        case KCM_MAX_STATUS:
+            fcc_status = FCC_STATUS_KCM_CRYPTO_ERROR;
+            break;
+
+    }
+    return fcc_status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/fcc_verification.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1063 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "factory_configurator_client.h"
+#include "fcc_status.h"
+#include "fcc_verification.h"
+#include "key_config_manager.h"
+#include "pv_error_handling.h"
+#include "cs_der_certs.h"
+#include "cs_utils.h"
+#include "fcc_output_info_handler.h"
+#include "fcc_malloc.h"
+#include "time.h"
+#include "cs_der_keys_and_csrs.h"
+#include "cs_utils.h"
+#include "fcc_sotp.h"
+#include "common_utils.h"
+#include "kcm_internal.h"
+#include "fcc_utils.h"
+
+#define FCC_10_YEARS_IN_SECONDS 315360000//10*365*24*60*60
+
+/*
+* The function checks that UTC offset value is inside defined range of valid offsets :-12:00 - +14:00
+*/
+static bool check_utc_offset_data(char *utc_offset_data, size_t utc_data_size)
+{
+    uint8_t symbol_index = 0;
+    uint8_t first_digit_of_hour = 1;
+    uint8_t second_digit_of_hour = 2;
+    uint8_t first_digit_of_minutes = 4;
+    uint8_t second_digit_of_minutes = 5;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    /*
+    The range of UTC offsets taken from https://en.wikipedia.org/wiki/List_of_UTC_time_offsets
+    We check only that the offset is -xx:yy or +xx:yy and that the offset is in range of offsets : -12:00 - +14:00
+    but we check only that UTC contain restricted symbols(-,+,:_) and numbers at xx or yy.
+    */
+    //The first char must be '+' or '-'
+    if ((utc_offset_data[symbol_index] != '+') && (utc_offset_data[symbol_index] != '-')) {
+        return false;
+    }
+
+    //The format of utc offset should be -xx:xx or +xx:xx
+    if (utc_offset_data[3] != ':') {
+        return false;
+    }
+
+    //Check that all numbers of hours and minutes are valid
+    if (utc_offset_data[first_digit_of_hour] < '0' || utc_offset_data[first_digit_of_hour] > '9') {
+        return false;
+    }
+    if (utc_offset_data[second_digit_of_hour] < '0' || utc_offset_data[second_digit_of_hour] > '9') {
+        return false;
+    }
+    if (utc_offset_data[first_digit_of_minutes] < '0' || utc_offset_data[first_digit_of_minutes] > '9') {
+        return false;
+    }
+    if (utc_offset_data[second_digit_of_minutes] < '0' || utc_offset_data[second_digit_of_minutes] > '9') {
+        return false;
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return true;
+}
+
+/** The function checks bootstrap server uri data contents.
+*
+* @param uri_data_buffer[in]             The bootstrap uri data.
+* @param size_of_uri_data_buffer[in]      The bootstrap uri data size.
+* @return
+*     fcc_status_e.
+*/
+static fcc_status_e fcc_check_uri_contents(bool use_bootstrap, uint8_t* uri_data_buffer, size_t size_of_uri_data_buffer)
+{
+    const char uri_coap_prefix[] = "coap://";
+    const char uri_coaps_prefix[] = "coaps://";
+    const char uri_aid_1[] = "?aid=";
+    const char uri_aid_2[] = "&aid=";
+    bool has_uri_aid = false;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    char *uri_string = NULL;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    bool is_first_to_claim_mode = false;
+    uint32_t first_to_claim = 0;
+    size_t act_config_param_size = 0;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    // get first to claim
+    kcm_status = kcm_item_get_data((const uint8_t*)g_fcc_first_to_claim_parameter_name,
+                                   strlen(g_fcc_first_to_claim_parameter_name),
+                                   KCM_CONFIG_ITEM,
+                                   (uint8_t*)&first_to_claim,
+                                   sizeof(uint32_t),
+                                   &act_config_param_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS && kcm_status != KCM_STATUS_ITEM_NOT_FOUND), FCC_STATUS_KCM_ERROR, "Failed to get first to claim config parameter");
+    if (kcm_status == KCM_STATUS_SUCCESS) {
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((act_config_param_size != sizeof(uint32_t)), FCC_STATUS_WRONG_ITEM_DATA_SIZE, "Size of first to claim mode parameter is wrong ");
+        is_first_to_claim_mode = (first_to_claim == 1);
+    }
+
+    //Allocate buffer for uri string creation
+    uri_string = fcc_malloc(size_of_uri_data_buffer + 1);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((uri_string == NULL), FCC_STATUS_MEMORY_OUT, "Failed to allocate memory for URI string");
+
+    //Copy data and create null terminated string
+    memcpy(uri_string, uri_data_buffer, size_of_uri_data_buffer);
+    (*(uri_string + size_of_uri_data_buffer)) = '\0';
+
+    // Check that uri_string has correct prefix
+    if (memcmp(uri_string, uri_coap_prefix, strlen(uri_coap_prefix)) != 0 && memcmp(uri_string, uri_coaps_prefix, strlen(uri_coaps_prefix)) != 0) {
+        SA_PV_ERR_RECOVERABLE_GOTO_IF(true, fcc_status = FCC_STATUS_URI_WRONG_FORMAT, exit, "Wrong uri prefix");
+    }
+
+    // Check if uri_string contains uri_aid (indicate the uri contains AccountId)
+    if ((strstr(uri_string, uri_aid_1) != NULL) || (strstr(uri_string, uri_aid_2) != NULL)) {
+        has_uri_aid = true;
+    }
+
+    if (is_first_to_claim_mode == true) {
+        SA_PV_ERR_RECOVERABLE_GOTO_IF(use_bootstrap == false, fcc_status = FCC_STATUS_FIRST_TO_CLAIM_NOT_ALLOWED, exit, "First to claim not allowed in lwm2m mode");
+        SA_PV_ERR_RECOVERABLE_GOTO_IF(has_uri_aid == true, fcc_status = FCC_STATUS_FIRST_TO_CLAIM_NOT_ALLOWED, exit, "First to claim not allowed if account ID exist");
+    } else {
+        SA_PV_ERR_RECOVERABLE_GOTO_IF(has_uri_aid == false, fcc_status = FCC_STATUS_URI_WRONG_FORMAT, exit, "Wrong uri data");
+    }
+
+exit:
+    fcc_free(uri_string);
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+/* The function verifies if current item exists and checks the result with is_should_be_present flag.
+*  In case of unsuitability of the flag and existence of the item, the function sets warning with relevant message.
+*/
+static fcc_status_e verify_existence_and_set_warning(const uint8_t *parameter_name, size_t size_of_parameter_name, kcm_item_type_e parameter_type, bool is_should_be_present)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    size_t item_size = 0;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    //Check that second mode server uri is not present
+    kcm_status = kcm_item_get_data_size(parameter_name,
+                                        size_of_parameter_name,
+                                        parameter_type,
+                                        &item_size);
+
+    if (kcm_status == KCM_STATUS_SUCCESS && is_should_be_present == false) {
+        output_info_fcc_status = fcc_store_warning_info((const uint8_t*)parameter_name, size_of_parameter_name, g_fcc_redundant_item_warning_str);
+    }
+    if (kcm_status != KCM_STATUS_SUCCESS &&  is_should_be_present == true) {
+        output_info_fcc_status = fcc_store_warning_info((const uint8_t*)parameter_name, size_of_parameter_name, g_fcc_item_not_set_warning_str);
+    }
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                    fcc_status = FCC_STATUS_WARNING_CREATE_ERROR,
+                                    "Failed to create warning");
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+/**This function verifies certificate expiration according to
+*
+* @param certificate_data[in]                  buffer of certificate.
+* @param size_of_certificate_data[in]          size of certificate data.
+* @param certificate_name[in]                  buffer of certificate name.
+* @param size_of_certificate_name[in]          size of certificate name buffer.
+*    @returns
+*        fcc_status_e status.
+*/
+static fcc_status_e verify_certificate_expiration(palX509Handle_t x509_cert, const uint8_t *certificate_name, size_t size_of_certificate_name)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    size_t size_of_valid_from_attr = 0;
+    size_t size_of_valid_until_attr = 0;
+    uint64_t valid_from_attr = 0;
+    uint64_t time = 0;
+    uint64_t diff_time = 60; //seconds. This value used to reduce time adjustment 
+    uint64_t valid_until_attr = 0;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    //Get "valid_from" certificate attribute
+    kcm_status = cs_attr_get_data_x509_cert(x509_cert,
+                                            CS_VALID_FROM_ATTRIBUTE_TYPE,
+                                            (uint8_t*)&valid_from_attr,
+                                            sizeof(uint64_t),
+                                            &size_of_valid_from_attr);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF(kcm_status != KCM_STATUS_SUCCESS, fcc_status = FCC_STATUS_INVALID_CERT_ATTRIBUTE, exit, "Failed to get valid_from attribute");
+
+    //Get "valid_until" certificate attribute
+    kcm_status = cs_attr_get_data_x509_cert(x509_cert,
+                                            CS_VALID_TO_ATTRIBUTE_TYPE,
+                                            (uint8_t*)&valid_until_attr,
+                                            sizeof(uint64_t),
+                                            &size_of_valid_until_attr);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF(kcm_status != KCM_STATUS_SUCCESS, fcc_status = FCC_STATUS_INVALID_CERT_ATTRIBUTE, exit, "Failed to get valid_until attribute");
+
+
+    //Check device time
+    time = pal_osGetTime();
+    if (time == 0) {
+        output_info_fcc_status = fcc_store_warning_info((const uint8_t*)certificate_name, size_of_certificate_name, g_fcc_cert_time_validity_warning_str);
+        SA_PV_LOG_ERR("time is (%" PRIuMAX ") ", (uint64_t)time);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_WARNING_CREATE_ERROR, exit, "Failed to create warning");
+    } else {
+        //Check that the certificate is not expired
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((time > (valid_until_attr)), fcc_status = FCC_STATUS_EXPIRED_CERTIFICATE, exit, "The certificate is expired");
+
+        //Check that start of validity is less than current time
+        if (time + diff_time < (valid_from_attr)) {
+            SA_PV_LOG_ERR("valid_from_attr is (%" PRIuMAX ") ", (uint64_t)(valid_from_attr));
+            SA_PV_LOG_ERR("time is (%" PRIuMAX ") ", (uint64_t)time);
+            output_info_fcc_status = fcc_store_warning_info((const uint8_t*)certificate_name, size_of_certificate_name, g_fcc_cert_time_validity_warning_str);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_WARNING_CREATE_ERROR, exit, "Failed to create warning");
+        }
+
+        //Check that the certificate is valid at least for 10 years
+        if ((valid_until_attr)-time < FCC_10_YEARS_IN_SECONDS) {
+            output_info_fcc_status = fcc_store_warning_info((const uint8_t*)certificate_name, size_of_certificate_name, g_fcc_cert_validity_less_10_years_warning_str);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_WARNING_CREATE_ERROR, exit, "Failed to create warning");
+        }
+
+    }
+exit:
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_store_error_info((const uint8_t*)certificate_name, size_of_certificate_name, fcc_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR, "Failed to create output fcc_status error %d", fcc_status);
+    }
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+/**This function verifies lwm2m certificate ou attribute is equal to aid from server link.
+*
+* @param certificate_data[in]                  buffer of certificate.
+* @param size_of_certificate_data[in]          size of certificate data.
+*        fcc_status_e status.
+*/
+static fcc_status_e compare_ou_with_aid_server(palX509Handle_t x509_cert)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    uint8_t *ou_attribute_data = NULL;
+    size_t ou_attribute_size = 0;
+    uint8_t *parameter_name = (uint8_t*)g_fcc_lwm2m_server_uri_name;
+    size_t size_of_parameter_name = strlen(g_fcc_lwm2m_server_uri_name);
+    uint8_t *server_uri_buffer = NULL;
+    size_t item_size = 0;
+    char *uri_string = NULL;
+    char *aid_substring = NULL;
+    int aid_substring_size = 0;
+    int result = 0;
+    int len_of_aid_sub_string = (int)strlen("&aid=");
+
+    //Get OU certificate attribute
+    fcc_status = fcc_get_certificate_attribute(x509_cert, CS_OU_ATTRIBUTE_TYPE, &ou_attribute_data, &ou_attribute_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(fcc_status != FCC_STATUS_SUCCESS, fcc_status = fcc_status, "Failed to get size OU attribute");
+
+    //Get aid data
+    fcc_status = fcc_get_kcm_data(parameter_name, size_of_parameter_name, KCM_CONFIG_ITEM, &server_uri_buffer, &item_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to get kcm data server url");
+
+    uri_string = fcc_malloc(item_size + 1);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((uri_string == NULL), fcc_status = FCC_STATUS_MEMORY_OUT, exit, "Failed to get kcm data server url");
+
+    memcpy(uri_string, server_uri_buffer, item_size);
+    (*(uri_string + item_size)) = '\0';
+
+    aid_substring = strstr(uri_string, "&aid=");
+    if (aid_substring == NULL) {
+        aid_substring = strstr(uri_string, "?aid=");
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((aid_substring == NULL), fcc_status = FCC_STATUS_URI_WRONG_FORMAT, exit, "URI format is wrong");
+    }
+
+    aid_substring_size = (int)strlen(aid_substring);
+    aid_substring_size = aid_substring_size - len_of_aid_sub_string;
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((aid_substring_size < (int)ou_attribute_size - 1), fcc_status = FCC_STATUS_URI_WRONG_FORMAT, exit, "URI format is wrong");
+
+    result = memcmp(&(aid_substring[len_of_aid_sub_string]), ou_attribute_data, ou_attribute_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((result != 0), fcc_status = FCC_STATUS_INVALID_LWM2M_CN_ATTR, exit, "CN of LWM2M different from endpoint name");
+
+exit:
+    fcc_free(ou_attribute_data);
+    fcc_free(server_uri_buffer);
+    fcc_free(uri_string);
+    return fcc_status;
+}
+/**This function verifies  certificate's cn attribute is equal to endpoint name.
+*
+* @param certificate_data[in]                  buffer of certificate.
+* @param size_of_certificate_data[in]          size of certificate data.
+*        fcc_status_e status.
+*/
+static fcc_status_e compare_cn_with_endpoint(palX509Handle_t x509_cert)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    //fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    size_t size_of_cn_attr = 0;
+    uint8_t *cn_attribute_data = NULL;
+    size_t endpoint_name_size;
+    uint8_t *endpoint_name_data = NULL;
+    int result = 0;
+
+    //Get  CN certificate attribute
+    fcc_status = fcc_get_certificate_attribute(x509_cert, CS_CN_ATTRIBUTE_TYPE, &cn_attribute_data, &size_of_cn_attr);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(fcc_status != FCC_STATUS_SUCCESS, fcc_status = fcc_status, "Failed to get size CN attribute");
+
+    //Get attribute returns size of string including  "\0"
+    size_of_cn_attr = size_of_cn_attr - 1;
+
+    //Get endpoint name size
+    fcc_status = fcc_get_kcm_data((const uint8_t*)g_fcc_endpoint_parameter_name, strlen(g_fcc_endpoint_parameter_name), KCM_CONFIG_ITEM, &endpoint_name_data, &endpoint_name_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to get endpoint name");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((size_of_cn_attr != endpoint_name_size), fcc_status = FCC_STATUS_INVALID_LWM2M_CN_ATTR, exit, "Wrong size of CN");
+
+    result = memcmp(endpoint_name_data, cn_attribute_data, size_of_cn_attr);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((result != 0), fcc_status = FCC_STATUS_INVALID_LWM2M_CN_ATTR, exit, "CN of the certificate is different from endpoint name");
+
+exit:
+    fcc_free(cn_attribute_data);
+    fcc_free(endpoint_name_data);
+    return fcc_status;
+}
+/** The function checks validity of bootstrap server uri parameter
+*
+* The function checks the item's size, gets its data and checks it.
+*
+* @param bootrstrap_server_uri_name[in]             The bootstrap uri name.
+* @param size_of_bootrstrap_server_uri_name[in]     The size of bootstrap uri name.
+* @return
+*     fcc_status_e.
+*/
+static fcc_status_e verify_server_uri(bool use_bootstrap)
+{
+
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    size_t item_size = 0;
+    uint8_t *server_uri_buffer = NULL;
+    uint8_t *parameter_name = NULL;
+    size_t size_of_parameter_name = 0;
+    uint8_t *second_mode_parameter_name = NULL;
+    size_t size_of_second_mode_parameter_name = 0;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    //Set server uri parameter names of current and second mode according to bootstrap mode
+    if (use_bootstrap == true) {
+        parameter_name = (uint8_t*)g_fcc_bootstrap_server_uri_name;
+        size_of_parameter_name = strlen(g_fcc_bootstrap_server_uri_name);
+        second_mode_parameter_name = (uint8_t*)g_fcc_lwm2m_server_uri_name;
+        size_of_second_mode_parameter_name = strlen(g_fcc_lwm2m_server_uri_name);
+    } else {
+        parameter_name = (uint8_t*)g_fcc_lwm2m_server_uri_name;
+        size_of_parameter_name = strlen(g_fcc_lwm2m_server_uri_name);
+        second_mode_parameter_name = (uint8_t*)g_fcc_bootstrap_server_uri_name;
+        size_of_second_mode_parameter_name = strlen(g_fcc_bootstrap_server_uri_name);
+    }
+    fcc_status = fcc_get_kcm_data(parameter_name, size_of_parameter_name, KCM_CONFIG_ITEM, &server_uri_buffer, &item_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to get kcm data server url");
+
+    //Check that server uri of second mode is not present, if yes - set warning
+    fcc_status = verify_existence_and_set_warning(second_mode_parameter_name, size_of_second_mode_parameter_name, KCM_CONFIG_ITEM, false);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to verify_existence_and_set_warning");
+
+    //Check server uri data
+    fcc_status = fcc_check_uri_contents(use_bootstrap, server_uri_buffer, item_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to check bootstrap uri data");
+
+exit:
+    fcc_free(server_uri_buffer);
+    //In case kcm or fcc error, record the error with parameter name
+    if (kcm_status != KCM_STATUS_SUCCESS || fcc_status != FCC_STATUS_SUCCESS) {
+        if (fcc_status == FCC_STATUS_FIRST_TO_CLAIM_NOT_ALLOWED && parameter_name == (uint8_t*)g_fcc_lwm2m_server_uri_name)
+        {
+            // In case that using lwm2m and first to claim on, change the parameter_name
+            parameter_name = (uint8_t*)g_fcc_first_to_claim_parameter_name;
+            size_of_parameter_name = strlen(g_fcc_first_to_claim_parameter_name);
+        }
+        output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output fcc_status error %d",
+                                        fcc_status);
+    }
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+/* The function checks UTC offset.
+*/
+static fcc_status_e check_utc_offset(void)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e fcc_output_status = FCC_STATUS_SUCCESS;
+    uint8_t *parameter_name = (uint8_t*)g_fcc_offset_from_utc_parameter_name;
+    size_t size_of_parameter_name = strlen(g_fcc_offset_from_utc_parameter_name);
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    size_t item_size = 0;
+
+    uint8_t *utc_offset_data = NULL;
+    bool status = false;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    fcc_status = fcc_get_kcm_data(parameter_name, size_of_parameter_name, KCM_CONFIG_ITEM, &utc_offset_data, &item_size);
+
+    //If the item is missing or empty, write warning
+    if (fcc_status == FCC_STATUS_ITEM_NOT_EXIST || fcc_status == FCC_STATUS_EMPTY_ITEM) {
+        fcc_output_status = fcc_store_warning_info(parameter_name, size_of_parameter_name, g_fcc_item_not_set_warning_str);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_output_status != FCC_STATUS_SUCCESS),
+                                      fcc_status = FCC_STATUS_WARNING_CREATE_ERROR,
+                                      exit,
+                                      "Failed to create output warning %s",
+                                      g_fcc_item_not_set_warning_str);
+        fcc_status = FCC_STATUS_SUCCESS;
+    } else {
+        //If get kcm data returned error, exit with error
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to get utc data");
+
+        status = check_utc_offset_data((char*)utc_offset_data, item_size);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), fcc_status = FCC_STATUS_UTC_OFFSET_WRONG_FORMAT, exit, "Failed to check utc offset");
+    }
+
+exit:
+    fcc_free(utc_offset_data);
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output fcc_status error  %d",
+                                        fcc_status);
+    }
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+/**This function checks Root CA certificate.
+*
+* @param device_objects[in]         Structure with set of device security object data.
+* @param use_bootstrap[in]          Bootstrap mode.
+*    @returns
+*        fcc_status_e status.
+*/
+static fcc_status_e verify_root_ca_certificate(bool use_bootstrap)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    size_t item_size = 0;
+    uint8_t *parameter_name = NULL;
+    size_t size_of_parameter_name = 0;
+    uint8_t *second_mode_parameter_name = NULL;
+    size_t size_of_second_mode_parameter_name = 0;
+    uint8_t attribute_data[PAL_CERT_ID_SIZE] = { 0 };
+    size_t size_of_attribute_data = 0;
+    uint8_t data_out[FCC_CA_IDENTIFICATION_SIZE] = { 0 };
+    size_t data_size_out = 0;
+    int result = 0;
+
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    //Set CA certificate names of current and second mode
+    if (use_bootstrap == true) {
+        //Set bootstrap root ca certificate name
+        parameter_name = (uint8_t*)g_fcc_bootstrap_server_ca_certificate_name;
+        size_of_parameter_name = strlen(g_fcc_bootstrap_server_ca_certificate_name);
+        second_mode_parameter_name = (uint8_t*)g_fcc_lwm2m_server_ca_certificate_name;
+        size_of_second_mode_parameter_name = strlen(g_fcc_lwm2m_server_ca_certificate_name);
+    } else {
+        //Set lwm2m root ca certificate name
+        parameter_name = (uint8_t*)g_fcc_lwm2m_server_ca_certificate_name;
+        size_of_parameter_name = strlen(g_fcc_lwm2m_server_ca_certificate_name);
+        second_mode_parameter_name = (uint8_t*)g_fcc_bootstrap_server_ca_certificate_name;
+        size_of_second_mode_parameter_name = strlen(g_fcc_bootstrap_server_ca_certificate_name);
+    }
+
+    //Check that ca certificate of current mode is present 
+    kcm_status = kcm_item_get_data_size((const uint8_t*)parameter_name,
+                                        size_of_parameter_name,
+                                        KCM_CERTIFICATE_ITEM,
+                                        &item_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_ITEM_NOT_EXIST, store_error_and_exit, "Failed to get size bootstrap root ca certificate size");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((item_size == 0), fcc_status = FCC_STATUS_EMPTY_ITEM, store_error_and_exit, "Empty root CA certificate");
+
+    //Check  that ca certificate of second mode is not present, if yes - set warning
+    fcc_status = verify_existence_and_set_warning(second_mode_parameter_name, size_of_second_mode_parameter_name, KCM_CERTIFICATE_ITEM, false);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, store_error_and_exit, "Failed in verify_existence_and_set_warning");
+
+    if (use_bootstrap == true) {
+        fcc_status = fcc_get_certificate_attribute_by_name((const uint8_t*)parameter_name,
+                                                           size_of_parameter_name,
+                                                           CS_CERT_ID_ATTR,
+                                                           attribute_data,
+                                                           sizeof(attribute_data),
+                                                           &size_of_attribute_data);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, store_error_and_exit, "Failed to get ca id attribute");
+
+        fcc_status = fcc_sotp_data_retrieve(data_out, size_of_attribute_data, &data_size_out, SOTP_TYPE_TRUSTED_TIME_SRV_ID);
+
+        if (fcc_status != FCC_STATUS_SUCCESS || data_size_out != size_of_attribute_data) {
+            output_info_fcc_status = fcc_store_warning_info((const uint8_t*)parameter_name, size_of_parameter_name, g_fcc_ca_identifier_warning_str);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_WARNING_CREATE_ERROR, store_error_and_exit, "Failed to create warning");
+        }
+
+        if (fcc_status == FCC_STATUS_SUCCESS) {
+            result = memcmp(data_out, attribute_data, data_size_out);
+            if (result != 0) {
+                output_info_fcc_status = fcc_store_warning_info((const uint8_t*)parameter_name, size_of_parameter_name, g_fcc_ca_identifier_warning_str);
+                SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_WARNING_CREATE_ERROR, store_error_and_exit, "Failed to create warning");
+            }
+        }
+        fcc_status = FCC_STATUS_SUCCESS;
+    }
+
+    //TBD : check of mbed crypto scheme IOTPREQ-1417
+store_error_and_exit:
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output fcc_status error  %d",
+                                        fcc_status);
+    }
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+/** Get a handle to the next X509 in the chain
+*   This is done by getting the size of the next X509, then reading the file into a dynamically allocated buffer, creating the X509 handle and freeing the buffer.
+*   Calling this function after ::kcm_cert_chain_open will output the X509 handle of the first certificate in the chain
+*
+*    @param[in]  kcm_chain_handle                  pointer to an open chain handle (use the ::kcm_cert_chain_open API).
+*    @param[out] x509_cert_handle_out              pointer to an X509 handle where the created handle will be placed.
+*
+*    @returns
+*        FCC_STATUS_SUCCESS in case of success or one of the `::fcc_status_e` errors otherwise.
+*/
+static fcc_status_e get_next_x509_in_chain(kcm_cert_chain_handle chain_handle, palX509Handle_t *x509_cert_handle_out)
+{
+    uint8_t *cert_buff = NULL;
+    size_t cert_buff_size = 0;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+
+    kcm_status = kcm_cert_chain_get_next_size(chain_handle, &cert_buff_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_convert_kcm_to_fcc_status(kcm_status), "Failed to get next size");
+
+    cert_buff = fcc_malloc(cert_buff_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cert_buff == NULL), FCC_STATUS_MEMORY_OUT, "Allocation failed");
+
+    kcm_status = kcm_cert_chain_get_next_data(chain_handle, cert_buff, cert_buff_size, &cert_buff_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_status), Exit, "Failed to get next cert");
+
+    kcm_status = cs_create_handle_from_der_x509_cert(cert_buff, cert_buff_size, x509_cert_handle_out);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_status), Exit, "Failed to get X509 handle");
+
+Exit:
+    fcc_free(cert_buff);
+    return fcc_status;
+}
+
+/**This function checks device private key.
+*
+* @param use_bootstrap[in]          Bootstrap mode.
+*    @returns
+*        fcc_status_e status.
+*/
+static fcc_status_e verify_device_certificate_and_private_key(bool use_bootstrap)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    bool is_self_signed = false;
+    uint8_t *parameter_name = NULL;
+    size_t size_of_parameter_name = 0;
+    uint8_t *second_mode_parameter_name = NULL;
+    size_t size_of_second_mode_parameter_name = 0;
+    uint8_t *private_key_data = NULL;
+    size_t size_of_private_key_data = 0;
+    kcm_cert_chain_context_int_s *cert_chain;
+    kcm_cert_chain_handle chain_handle;
+    size_t chain_len = 0;
+    palX509Handle_t x509_cert_handle = NULLPTR;
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    //Set device private key names of current and second modes
+    if (use_bootstrap == true) {
+        parameter_name = (uint8_t*)g_fcc_bootstrap_device_private_key_name;
+        size_of_parameter_name = strlen(g_fcc_bootstrap_device_private_key_name);
+        second_mode_parameter_name = (uint8_t*)g_fcc_lwm2m_device_private_key_name;
+        size_of_second_mode_parameter_name = strlen(g_fcc_lwm2m_device_private_key_name);
+    } else {
+        parameter_name = (uint8_t*)g_fcc_lwm2m_device_private_key_name;
+        size_of_parameter_name = strlen(g_fcc_lwm2m_device_private_key_name);
+        second_mode_parameter_name = (uint8_t*)g_fcc_bootstrap_device_private_key_name;
+        size_of_second_mode_parameter_name = strlen(g_fcc_bootstrap_device_private_key_name);
+    }
+
+    fcc_status = fcc_get_kcm_data(parameter_name, size_of_parameter_name, KCM_PRIVATE_KEY_ITEM, &private_key_data, &size_of_private_key_data);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, store_error_and_exit, "Failed to get device certificate");
+
+    //Check that device private key of second mode is not present, if yes - set warning
+    fcc_status = verify_existence_and_set_warning(second_mode_parameter_name, size_of_second_mode_parameter_name, KCM_PRIVATE_KEY_ITEM, false);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, store_error_and_exit, "Failed in verify_existence_and_set_warning");
+
+
+    //Set parameter names of device certificate according to mode
+    if (use_bootstrap == true) {
+        //Set bootstrap root ca certificate name
+        parameter_name = (uint8_t*)g_fcc_bootstrap_device_certificate_name;
+        size_of_parameter_name = strlen(g_fcc_bootstrap_device_certificate_name);
+        second_mode_parameter_name = (uint8_t*)g_fcc_lwm2m_device_certificate_name;
+        size_of_second_mode_parameter_name = strlen(g_fcc_lwm2m_device_certificate_name);
+    } else {
+        //Set lwm2m device certificate name
+        parameter_name = (uint8_t*)g_fcc_lwm2m_device_certificate_name;
+        size_of_parameter_name = strlen(g_fcc_lwm2m_device_certificate_name);
+        second_mode_parameter_name = (uint8_t*)g_fcc_bootstrap_device_certificate_name;
+        size_of_second_mode_parameter_name = strlen(g_fcc_bootstrap_device_certificate_name);
+    }
+
+    // Open device certificate as chain. 
+    kcm_status = kcm_cert_chain_open(&chain_handle, parameter_name, size_of_parameter_name, &chain_len);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_status), store_error_and_exit, "Failed to get device certificate descriptor");
+    
+    cert_chain = (kcm_cert_chain_context_int_s *)chain_handle;
+
+    //Create device certificate handle
+    fcc_status = get_next_x509_in_chain(chain_handle, &x509_cert_handle);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to get device certificate descriptor");
+
+    //Check device certificate public key
+    kcm_status = cs_check_certifcate_public_key(x509_cert_handle, private_key_data, size_of_private_key_data);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_CERTIFICATE_PUBLIC_KEY_CORRELATION_ERROR, close_chain, "Failed to check device certificate public key");
+
+    //Check if the certificate of second mode exists, if yes - set warning
+    fcc_status = verify_existence_and_set_warning(second_mode_parameter_name, size_of_second_mode_parameter_name, KCM_CERTIFICATE_ITEM, false);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to verify_existence_and_set_warning");
+
+    //Compare device certificate's CN attribute with endpoint name
+    fcc_status = compare_cn_with_endpoint(x509_cert_handle);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to compare_cn_with_endpoint");
+
+    //In case LWM2M certificate check it's OU attribute with aid of server link
+    if (strcmp((const char*)parameter_name, g_fcc_lwm2m_device_certificate_name) == 0) {
+        fcc_status = compare_ou_with_aid_server(x509_cert_handle);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to compare_ou_with_aid_server");
+    }
+
+    //Check that device certificate not self-signed
+    kcm_status = cs_is_self_signed_x509_cert(x509_cert_handle, &is_self_signed);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_INVALID_CERTIFICATE, close_chain, "Failed to check if device certificate is self-signed");
+    if (is_self_signed == true) {
+        output_info_fcc_status = fcc_store_warning_info(parameter_name, size_of_parameter_name, g_fcc_self_signed_warning_str);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                      fcc_status = FCC_STATUS_WARNING_CREATE_ERROR,
+                                      close_chain,
+                                      "Failed to create warning %s",
+                                      g_fcc_self_signed_warning_str);
+    }
+
+    //Verify expiration of first certificate in chain
+    fcc_status = verify_certificate_expiration(x509_cert_handle, parameter_name, size_of_parameter_name);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to verify_certificate_validity");
+
+    // Verify expiration of rest of chain
+    while (cert_chain->current_cert_index < cert_chain->num_of_certificates_in_chain) {
+
+        // Close handle of first X509 in chain
+        cs_close_handle_x509_cert(&x509_cert_handle);
+        
+        // Acquire a handle to the next X509 in the chain
+        fcc_status = get_next_x509_in_chain(chain_handle, &x509_cert_handle);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to get device certificate descriptor");
+
+        // Only verify the expiration date of the X509, not the signature (was checked before the store)
+        fcc_status = verify_certificate_expiration(x509_cert_handle, KCM_FILE_BASENAME(cert_chain->chain_name, KCM_FILE_PREFIX_CERTIFICATE), KCM_FILE_BASENAME_LEN(cert_chain->chain_name_len, KCM_FILE_PREFIX_CERTIFICATE));
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, close_chain, "Failed to verify_certificate_validity");
+    }
+
+
+close_chain:
+    kcm_cert_chain_close(chain_handle);
+
+store_error_and_exit:
+    fcc_free(private_key_data);
+    cs_close_handle_x509_cert(&x509_cert_handle);
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output fcc_status error  %d",
+                                        fcc_status);
+    }
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+/* The function checks firmware integrity ca and firmware integrity certificates
+*/
+static fcc_status_e verify_firmware_update_certificate(void)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e fcc_output_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    uint8_t *parameter_name = (uint8_t*)g_fcc_update_authentication_certificate_name;
+    size_t size_of_parameter_name = strlen(g_fcc_update_authentication_certificate_name);
+    palX509Handle_t x509_cert_handle = NULLPTR;
+    kcm_cert_chain_context_int_s *cert_chain = NULL;
+    kcm_cert_chain_handle chain_handle;
+    size_t chain_len = 0;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    // Open device certificate as chain. 
+    kcm_status = kcm_cert_chain_open(&chain_handle, parameter_name, size_of_parameter_name, &chain_len);
+
+    // If item does not exist or is empty -set warning
+    if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND ) {
+        fcc_output_status = fcc_store_warning_info((const uint8_t*)parameter_name, size_of_parameter_name, g_fcc_item_not_set_warning_str);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_output_status != FCC_STATUS_SUCCESS),
+                                      fcc_status = FCC_STATUS_WARNING_CREATE_ERROR,
+                                      exit,
+                                      "Failed to create output warning %s",
+                                      g_fcc_item_not_set_warning_str);
+        fcc_status = FCC_STATUS_SUCCESS;
+    } else {
+
+        //If get kcm data returned error, exit with error
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_status), exit, "Failed to get update certificate data");
+
+        cert_chain = (kcm_cert_chain_context_int_s *)chain_handle;
+
+        // Verify expiration of all certificates in firmware chain
+        // ADAM: Maybe change to function that gets verify_certificate_expiration as callback function (seems unnecessary for now...)
+        while (cert_chain->current_cert_index < cert_chain->num_of_certificates_in_chain) {
+
+            // Acquire a handle to the next X509 in the chain
+            fcc_status = get_next_x509_in_chain(chain_handle, &x509_cert_handle);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to get device certificate descriptor");
+
+            // Only verify the expiration date of the X509, not the signature (was checked before the store)
+            fcc_status = verify_certificate_expiration(x509_cert_handle, KCM_FILE_BASENAME(cert_chain->chain_name, KCM_FILE_PREFIX_CERTIFICATE), KCM_FILE_BASENAME_LEN(cert_chain->chain_name_len, KCM_FILE_PREFIX_CERTIFICATE));
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to verify_certificate_validity");
+
+            cs_close_handle_x509_cert(&x509_cert_handle);
+
+            // Set handle to 0 so that cs_close_handle_x509_cert is not called upon exit
+            x509_cert_handle = NULLPTR;
+        }
+        
+    }
+
+exit:
+    //Close the chain in case it was created
+    if ( cert_chain != NULL) {
+        kcm_cert_chain_close(chain_handle);
+    }
+    if (x509_cert_handle != NULLPTR) {
+        cs_close_handle_x509_cert(&x509_cert_handle);
+    }
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output fcc_status error  %d",
+                                        fcc_status);
+    }
+    return fcc_status;
+}
+
+// Check that fcc_firmware_id_name exists and is of correct uuid5 size
+/** Check that fcc_firmware_id_name exists and is of correct uuid5 size
+*
+* @param fcc_firmware_id_name[in]           Name of the file of the uuid (must be either g_fcc_class_id_name or g_fcc_vendor_id_name).
+*    @returns
+*        FCC_STATUS_SUCCESS If validated successfully, or if the item does not exist (warning is set).
+*        Otherwise will return an fcc_status_e error
+*/
+
+static fcc_status_e verify_firmware_uuid(const char *fcc_firmware_id_name)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    size_t item_size = 0;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER("fcc_firmware_id_name = %s", fcc_firmware_id_name);
+
+    // Check if class id exists - if not write warning
+    kcm_status = kcm_item_get_data_size((const uint8_t*)fcc_firmware_id_name,
+                                        strlen(fcc_firmware_id_name),
+                                        KCM_CONFIG_ITEM,
+                                        &item_size);
+
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        // If item not found, store warning
+        if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
+            fcc_status = fcc_store_warning_info((const uint8_t*)fcc_firmware_id_name, strlen(fcc_firmware_id_name), g_fcc_item_not_set_warning_str);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS),
+                (fcc_status = FCC_STATUS_WARNING_CREATE_ERROR),
+                                          Exit,
+                                          "Failed to create output warning %s",
+                                          g_fcc_item_not_set_warning_str);
+
+        } else { // If any other KCM error - exit with generic KCM error
+            fcc_status = FCC_STATUS_KCM_ERROR;
+
+            // Go to Exit returning FCC_STATUS_KCM_ERROR and setting error buffer
+            goto Exit;
+        }
+
+    } else {
+        // If item exists assert item is correct size of UUID5 
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((item_size != FCC_UUID5_SIZE_IN_BYTES), (fcc_status = FCC_STATUS_WRONG_ITEM_DATA_SIZE), Exit, "Class ID of incorrect size - %" PRIu32, (uint32_t)item_size);
+    }
+
+Exit:
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_store_error_info((uint8_t*)fcc_firmware_id_name, strlen(fcc_firmware_id_name), fcc_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output fcc_status error  %d",
+                                        fcc_status);
+    }
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+//FIXME : once init entropy API will be ready,add fcc_is_entropy_initialized implementation
+bool fcc_is_entropy_initialized(void)
+{
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return true;
+}
+fcc_status_e fcc_check_time_synchronization()
+{
+
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    uint64_t time = 0;
+    uint8_t *parameter_name = (uint8_t*)g_fcc_device_time_zone_parameter_name;
+    size_t size_of_parameter_name = strlen(g_fcc_device_time_zone_parameter_name);
+    size_t item_size = 0;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    /*
+    Time zone defines -  https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
+    */
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    //Check device time
+    time = pal_osGetTime();
+    if (time == 0) {
+        output_info_fcc_status = fcc_store_warning_info((const uint8_t*)g_fcc_current_time_parameter_name, strlen(g_fcc_current_time_parameter_name), g_fcc_item_not_set_warning_str);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_WARNING_CREATE_ERROR, "Failed to create warning");
+    }
+
+    //Check device time zone
+    kcm_status = kcm_item_get_data_size((const uint8_t*)parameter_name,
+                                        size_of_parameter_name,
+                                        KCM_CONFIG_ITEM,
+                                        &item_size);
+    //Store warning in case time zone is missing or empty
+    if (kcm_status != KCM_STATUS_SUCCESS || item_size == 0) {
+        output_info_fcc_status = fcc_store_warning_info(parameter_name, size_of_parameter_name, g_fcc_item_not_set_warning_str);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_WARNING_CREATE_ERROR,
+                                        "Failed to create output warning %s",
+                                        g_fcc_item_not_set_warning_str);
+    }
+
+    //Check UTC offset
+    fcc_status = check_utc_offset();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed in check_utc_offset");
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+fcc_status_e fcc_check_device_general_info()
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    size_t config_param_size = 0;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+    //Check FCC_ENDPOINT_NAME_CONFIG_PARAM_NAME
+    kcm_status = kcm_item_get_data_size((const uint8_t*)&g_fcc_endpoint_parameter_name,
+                                        strlen(g_fcc_endpoint_parameter_name),
+                                        KCM_CONFIG_ITEM,
+                                        &config_param_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_ITEM_NOT_EXIST, exit, "Failed to get size of %s ", g_fcc_endpoint_parameter_name);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((config_param_size == 0), fcc_status = FCC_STATUS_EMPTY_ITEM, exit, "Size of %s is 0 ", g_fcc_endpoint_parameter_name);
+
+exit:
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_store_error_info((const uint8_t*)g_fcc_endpoint_parameter_name, strlen(g_fcc_endpoint_parameter_name), fcc_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output fcc_status error %d",
+                                        fcc_status);
+    }
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+fcc_status_e fcc_check_device_meta_data(void)
+{
+    int config_param_index = 0;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    size_t config_param_size = 0;
+    uint8_t *parameter_name = NULL;
+    size_t size_of_parameter_name = 0;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    for (config_param_index = 0; config_param_index < FCC_MAX_CONFIG_PARAM_TYPE; config_param_index++) {
+
+        //Set current configuration parameter to local variable
+        parameter_name = (uint8_t*)fcc_config_param_lookup_table[config_param_index].config_param_name;
+        size_of_parameter_name = strlen(fcc_config_param_lookup_table[config_param_index].config_param_name);
+
+        //Check that current configuration parameter is present
+        kcm_status = kcm_item_get_data_size((const uint8_t*)parameter_name,
+                                            size_of_parameter_name,
+                                            KCM_CONFIG_ITEM,
+                                            &config_param_size);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_ITEM_NOT_EXIST, exit, "Failed to get size of %s ", fcc_config_param_lookup_table[config_param_index].config_param_name);
+    }
+
+exit:
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output fcc_status error %d",
+                                        fcc_status);
+    }
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+fcc_status_e fcc_get_bootstrap_mode(bool *use_bootstrap)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    size_t config_param_size = sizeof(uint32_t);
+    size_t act_config_param_size = 0;
+    uint32_t bootstrap;
+    uint8_t *parameter_name = (uint8_t*)g_fcc_use_bootstrap_parameter_name;
+    size_t size_of_parameter_name = strlen(g_fcc_use_bootstrap_parameter_name);
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    //Get configuration parameter
+    kcm_status = kcm_item_get_data((const uint8_t*)parameter_name,
+                                   size_of_parameter_name,
+                                   KCM_CONFIG_ITEM,
+                                   (uint8_t*)&bootstrap,
+                                   config_param_size,
+                                   &act_config_param_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_ITEM_NOT_EXIST, exit, "Failed to get data bootstrap mode parameter");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((act_config_param_size != sizeof(uint32_t)), fcc_status = FCC_STATUS_WRONG_ITEM_DATA_SIZE, exit, "Size of bootstrap mode parameter is wrong ");
+
+    if (bootstrap != 0 && bootstrap != 1) {
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((true), fcc_status = FCC_STATUS_BOOTSTRAP_MODE_ERROR, exit, "Invalid bootstrap mode");
+    }
+    if (bootstrap == 0) {
+        *use_bootstrap = false;
+        output_info_fcc_status = fcc_store_warning_info(parameter_name, size_of_parameter_name, g_fcc_bootstrap_mode_false_warning_str);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                      fcc_status = FCC_STATUS_WARNING_CREATE_ERROR,
+                                      exit,
+                                      "Failed to create output warning %s",
+                                      g_fcc_bootstrap_mode_false_warning_str);
+    } else {
+        *use_bootstrap = true;
+    }
+
+exit:
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_store_error_info(parameter_name, size_of_parameter_name, fcc_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output fcc_status error  %d",
+                                        fcc_status);
+    }
+    SA_PV_LOG_TRACE_FUNC_EXIT("use_bootstrap is %d", *use_bootstrap);
+    return fcc_status;
+}
+
+fcc_status_e fcc_check_device_security_objects(bool use_bootstrap)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    fcc_status = verify_root_ca_certificate(use_bootstrap);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to verify root CA certificate");
+
+    //Check bootstrap server URI
+    fcc_status = verify_server_uri(use_bootstrap);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to verify server URI");
+
+    //Check device certificate and private key
+    fcc_status = verify_device_certificate_and_private_key(use_bootstrap);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to verify device certificate and private key");
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+
+fcc_status_e fcc_check_firmware_update_integrity(void)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    fcc_status = verify_firmware_update_certificate();
+    //fcc_status = verify_certificate(g_fcc_update_authentication_certificate_name);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed to verify integrity CA certificate");
+
+    fcc_status = verify_firmware_uuid(g_fcc_class_id_name);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Error verifying class ID");
+
+    fcc_status = verify_firmware_uuid(g_fcc_vendor_id_name);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Error verifying vendor ID");
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/include/fcc_bundle_fields.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,197 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FCC_BUNDLE_FIELDS_H__
+#define __FCC_BUNDLE_FIELDS_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* @file fcc_bundle_handler.h
+*  \brief Defines for the bundles sent between the FCU and FCC 
+* This layer handles a device configuration bundle created by factory configurator utility (FCU).
+*/
+
+
+/**
+* Names of key parameters
+*/
+#define FCC_BUNDLE_DATA_PARAMETER_NAME                  "Name"
+#define FCC_BUNDLE_DATA_PARAMETER_SCHEME                "Type"
+#define FCC_BUNDLE_DATA_PARAMETER_FORMAT                "Format"
+#define FCC_BUNDLE_DATA_PARAMETER_DATA                  "Data"
+#define FCC_BUNDLE_DATA_PARAMETER_ACL                   "ACL"
+#define FCC_BUNDLE_DATA_PARAMETER_ARRAY                 "DataArray"
+#define FCC_BUNDLE_DATA_PARAMETER_PRIVATE_KEY_NAME      "PrKN"
+/**
+* Names of data formats
+*/
+#define FCC_BUNDLE_DER_DATA_FORMAT_NAME  "der"
+#define FCC_BUNDLE_PEM_DATA_FORMAT_NAME   "pem"
+
+
+/****************************************/
+/* Inbound Message Main CBOR Map Groups */
+/****************************************/
+
+/**
+* Name of keys group.
+*/
+#define FCC_KEY_GROUP_NAME                   "Keys"
+/**
+* Name of certificates group
+*/
+#define FCC_CERTIFICATE_GROUP_NAME           "Certificates"
+/**
+* Name of configuration parameters group.
+*/
+#define FCC_CONFIG_PARAM_GROUP_NAME           "ConfigParams"
+/**
+* Name of certificate chain group.
+*/
+#define FCC_CERTIFICATE_CHAIN_GROUP_NAME       "CertificateChains"
+/**
+* Name of scheme version group.
+*/
+#define FCC_BUNDLE_SCHEME_GROUP_NAME          "SchemeVersion"
+/**
+* Name of keep alive session group.
+*/
+#define FCC_KEEP_ALIVE_SESSION_GROUP_NAME          "KpAlvSess"
+/**
+* Name of Entropy group.
+*/
+#define FCC_ENTROPY_NAME       "Entropy"
+/**
+* Name of RoT group.
+*/
+#define FCC_ROT_NAME          "ROT"
+/**
+* Name of device verify readiness group.
+*/
+#define FCC_VERIFY_DEVICE_IS_READY_GROUP_NAME          "Verify"
+/**
+* Name of device verify readiness group.
+*/
+#define FCC_FACTORY_DISABLE_GROUP_NAME          "Disable"
+
+/**
+* Name of FCU session ID group (optional).
+*/
+#define FCC_FCU_SESSION_ID_GROUP_TYPE_NAME          "SID"
+
+/** Name of CSR requests group.
+*/
+#define FCC_CSR_REQUESTS_GROUP_NAME            "CsrReqs"
+
+/************************************************/
+/* Inbound Message: fields within CsrReqs Group */
+/************************************************/
+
+/**
+* Name of private key name field, within CSR Requests group
+*/
+#define FCC_CSRREQ_INBOUND_PRIVATE_KEY_NAME "PrKN"
+
+/**
+* Name of public key name field, within CSR Requests group
+*/
+#define FCC_CSRREQ_INBOUND_PUBLIC_KEY_NAME "PbKN"
+
+/**
+* Name of Extensions field, within CSR Requests group
+*/
+#define FCC_CSRREQ_INBOUND_EXTENSIONS_NAME "Ext"
+
+/**
+* Name of Subject field, within CSR Requests group
+*/
+#define FCC_CSRREQ_INBOUND_SUBJECT_NAME "Subj"
+
+/**
+* Name of Message digest field, within CSR Requests group
+*/
+#define FCC_CSRREQ_INBOUND_MESSAGEDIGEST_NAME "MD"
+
+
+/**********************************************************************/
+/* Inbound Message: fields within Extensions map within CsrReqs Group */
+/**********************************************************************/
+
+/**
+* Name of Trust field within Extensions
+*/
+#define FCC_CSRREQ_INBOUND_EXTENSION_TRUSTLEVEL_NAME "Trust"
+
+/**
+* Name of Key Usage field within Extensions
+*/
+#define FCC_CSRREQ_INBOUND_EXTENSION_KEYUSAGE_NAME "KU"
+
+/**
+* Name of Extended Key Usage field within Extensions
+*/
+#define FCC_CSRREQ_INBOUND_EXTENSION_EXTENDEDKEYUSAGE_NAME "EKU"
+
+/****************************************/
+/* Outbound Message Main CBOR Map Groups */
+/****************************************/
+
+/**
+* Name of error info group.
+*/
+//Fixme : rename "infoMessage" to ErrorInfo" when Factory tool will be ready for the change
+#define FCC_ERROR_INFO_GROUP_NAME              "InfoMessage"
+
+/**
+* Name of return status group.
+*/
+#define FCC_RETURN_STATUS_GROUP_NAME          "ReturnStatus"
+
+/**
+* Name of warning info group.
+*/
+#define FCC_WARNING_INFO_GROUP_NAME            "WarningInfo"
+
+/**
+* Name of CSRs group.
+*/
+#define FCC_CSR_OUTBOUND_GROUP_NAME                "Csrs"
+
+
+/***********************************************************/
+/* Outbound Message: fields the CSR maps within Csrs array */
+/***********************************************************/
+
+/**
+* Name of the private key corresponding to the CSR within the CSR map.
+*/
+#define FCC_CSR_OUTBOUND_MAP_PRIVATE_KEY_NAME FCC_CSRREQ_INBOUND_PRIVATE_KEY_NAME
+
+/**
+* Name of the data of the CSR within the CSR map.
+*/
+#define FCC_CSR_OUTBOUND_MAP_DATA FCC_BUNDLE_DATA_PARAMETER_DATA
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__FCC_BUNDLE_FIELDS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/include/fcc_sotp.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,60 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FCC_SOTP_H__
+#define __FCC_SOTP_H__
+
+#include "factory_configurator_client.h"
+#include "sotp.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+// Size of factory disabled flag in SOTP - internal use only.
+#define FCC_FACTORY_DISABLE_FLAG_SIZE    sizeof(int64_t)
+/** Writes data to SOTP
+*
+* @param data[in]         The data to store in SOTP.
+* @param data_size[in]     The size of buf in bytes. Must be divisible by 8, and less than or equal to 1024. Must be according to sotp_type.
+* @param sotp_type[in]    Enum representing the type of the item to be stored in SOTP.
+*
+* @return
+*     FCC_STATUS_SUCCESS for success or one of the `::fcc_status_e` errors otherwise.
+*/
+fcc_status_e fcc_sotp_data_store(const uint8_t *data, size_t data_size, sotp_type_e sotp_type);
+
+/** Reads data from SOTP
+*
+* @param data_out[out]             A buffer to retrieve data from SOTP.
+* @param data_size_max[in]         The size of data_out max. bytes.
+* @param data_actual_size_out[out] The actual size of bytes returned by this function, should be less or equal to data_size_max.
+* @param sotp_type[in]             Enum representing the type of the item to be stored in SOTP.
+*
+* @return
+*     FCC_STATUS_SUCCESS for success or one of the `::fcc_status_e` errors otherwise.
+*/
+fcc_status_e fcc_sotp_data_retrieve(uint8_t *data_out, size_t data_size_max, size_t *data_actual_size_out, sotp_type_e sotp_type);
+
+
+#define MAX_SOTP_BUFFER_SIZE    FCC_ENTROPY_SIZE
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__FCC_SOTP_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/include/fcc_utils.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,61 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FCC_UTILS_H__
+#define __FCC_UTILS_H__
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include "key_config_manager.h"
+#include "factory_configurator_client.h"
+#include "fcc_defs.h"
+#include "fcc_sotp.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern const char g_sotp_entropy_data_type_name[];
+extern const char g_sotp_rot_data_type_name[];
+extern const char g_sotp_factory_disable_type_name[];
+extern const char g_sotp_ca_server_id_type_name[];
+extern const char g_sotp_time_type_name[];
+
+/** Returns sotp type name and name size
+*
+* @param sotp_type[in]             The sotp type
+* @param sotp_type_name[out]       The pointer to sotp type name
+* @param sotp_type[out]            The size of sotp type name
+*    @returns
+*        fcc_status_e status.
+*/
+fcc_status_e fcc_get_sotp_type_name(sotp_type_e sotp_type, char* *sotp_type_name, size_t *sotp_type_name_size);
+
+/** Converts kcm error status to appropriate fcc error.
+*
+* @param kcm_result[in/out]    The kcm error status
+*    @returns
+*        fcc_status_e status.
+*/
+fcc_status_e fcc_convert_kcm_to_fcc_status(kcm_status_e kcm_result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__FCC_UTILS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/factory-configurator-client/source/include/fcc_verification.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,130 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FCC_VERIFICATION_H__
+#define __FCC_VERIFICATION_H__
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include "key_config_manager.h"
+#include "factory_configurator_client.h"
+#include "fcc_defs.h"
+#include "cs_utils.h"
+#include "cs_der_certs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* The size of the binary representation of UUID5. Used in verifying firmware vendor and class IDs.
+*/
+#define FCC_UUID5_SIZE_IN_BYTES 16
+
+/**
+* Types of configuration parameter
+*/
+typedef enum {
+    FCC_MANUFACTURER_NAME_CONFIG_PARAM_TYPE,
+    FCC_MODEL_NUMBER_CONFIG_PARAM_TYPE,
+    FCC_DEVICE_TYPE_CONFIG_PARAM_TYPE,
+    FCC_HARDWARE_VERSION_CONFIG_PARAM_TYPE,
+    FCC_MEMORY_TOTAL_SIZE_CONFIG_PARAM_TYPE,
+    FCC_DEVICE_SERIAL_NUMBER_CONFIG_PARAM_TYPE,
+    FCC_MAX_CONFIG_PARAM_TYPE
+} fcc_config_param_type_e;
+
+/**
+* Configuration parameters lookup record, correlating parameter's type and name
+*/
+typedef struct fcc_config_param_lookup_record_ {
+    fcc_config_param_type_e config_param_type;
+    const char *config_param_name;
+} fcc_config_param_lookup_record_s;
+
+/**
+* Group lookup table, correlating for each group its type and name
+*/
+static const fcc_config_param_lookup_record_s fcc_config_param_lookup_table[FCC_MAX_CONFIG_PARAM_TYPE] = {
+    { FCC_MANUFACTURER_NAME_CONFIG_PARAM_TYPE,     g_fcc_manufacturer_parameter_name },
+    { FCC_MODEL_NUMBER_CONFIG_PARAM_TYPE,          g_fcc_model_number_parameter_name },
+    { FCC_DEVICE_TYPE_CONFIG_PARAM_TYPE,           g_fcc_device_type_parameter_name },
+    { FCC_HARDWARE_VERSION_CONFIG_PARAM_TYPE,      g_fcc_hardware_version_parameter_name },
+    { FCC_MEMORY_TOTAL_SIZE_CONFIG_PARAM_TYPE,     g_fcc_memory_size_parameter_name },
+    { FCC_DEVICE_SERIAL_NUMBER_CONFIG_PARAM_TYPE,  g_fcc_device_serial_number_parameter_name },
+};
+
+
+/** Checks entropy initialization
+*
+*    @returns
+*        entropy status  true/false.
+*/
+bool fcc_is_entropy_initialized(void);
+
+/** Checks that all mandatory device meta data is present
+*
+*    @returns
+*        fcc_status_e status.
+*/
+fcc_status_e fcc_check_device_meta_data(void);
+
+/** Gets current bootstrap mode
+*
+* @param use_bootstrap[in/out]    The bootstrap mode
+*    @returns
+*        fcc_status_e status.
+*/
+fcc_status_e fcc_get_bootstrap_mode(bool *use_bootstrap);
+
+/**Function that checks all time synchronization parameters.
+*
+*    @returns
+*        fcc_status_e status.
+*/
+fcc_status_e fcc_check_time_synchronization(void);
+
+/** Checks mandatory device general info  - endpoint name. Does not check bootstrap_mode (checked with fcc_get_bootstrap_mode()).
+*
+*    @returns
+*        fcc_status_e status.
+*/
+fcc_status_e fcc_check_device_general_info( void );
+
+/** Checks device security objects : root ca certificate, device certificate, device private key and server URL.
+*
+* @param device_objects[in]           Structure with set of device security object names.
+* @param use_bootstrap[in]         Bootstrap mode.
+*    @returns
+*        fcc_status_e status.
+*/
+fcc_status_e fcc_check_device_security_objects(bool use_bootstrap);
+
+
+/** Checks firmware update integrity objects
+*
+*    @returns
+*        fcc_status_e status.
+*/
+fcc_status_e  fcc_check_firmware_update_integrity( void );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__FCC_VERIFICATION_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/fcc-bundle-handler/fcc_bundle_handler.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,48 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FCC_BUNDLE_HANDLER_H__
+#define __FCC_BUNDLE_HANDLER_H__
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include "fcc_status.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Decodes and processes an inbound device configuration bundle created by FCU.
+* Also creates an outbound bundle that should be sent to FCU.
+* The function assumes that the bundle includes four groups represented as cbor maps.
+* The names of the groups are `SchemeVersion`, `Keys`, `Certificates` and `ConfigParams`.
+* Each group contains a list of items, and for each item, there are a number of relevant parameters.
+*
+* @param encoded_bundle The encoded FCU bundle that is written into a secure storage.
+* @param encoded_blob_size The encoded FCU bundle size in bytes.
+* @param bundle_response_out The encoded outbound bundle. It may contain data such as CSR and different types of key schemes.
+*        The response associates a descriptive error in case of a fault. Will be NULL if response not created successfully.
+* @param bundle_response_size_out The encoded outbound bundle size in bytes.
+*
+* @return
+*       FCC_STATUS_SUCCESS in case of success or one of the `::fcc_status_e` errors otherwise.
+*/
+fcc_status_e fcc_bundle_handler(const uint8_t *encoded_bundle, size_t encoded_bundle_size, uint8_t **bundle_response_out, size_t *bundle_response_size_out);
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__FCC_BUNDLE_HANDLER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_certificate_chain_utils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,127 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+#ifndef USE_TINY_CBOR
+#include "fcc_bundle_handler.h"
+#include "cn-cbor.h"
+#include "pv_error_handling.h"
+#include "fcc_bundle_utils.h"
+#include "key_config_manager.h"
+#include "fcc_output_info_handler.h"
+#include "fcc_malloc.h"
+#include "fcc_time_profiling.h"
+#include "fcc_utils.h"
+
+
+/** Processes  certificate chain list.
+* The function extracts data parameters for each certificate chain and stores it.
+*
+* @param cert_chains_list_cb[in]   The cbor structure with certificate chain list.
+*
+* @return
+*     true for success, false otherwise.
+*/
+fcc_status_e fcc_bundle_process_certificate_chains(const cn_cbor *cert_chains_list_cb)
+{
+    bool status = false;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_result = KCM_STATUS_SUCCESS;
+    uint32_t cert_chain_index = 0;
+    uint32_t cert_index = 0;
+    cn_cbor *cert_chain_cb = NULL;
+    cn_cbor *cert_cb = NULL;
+    fcc_bundle_data_param_s certificate_chain;
+    uint8_t *certificate_data;
+    size_t certificate_data_size = 0;
+    kcm_cert_chain_handle cert_chain_handle = NULL;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cert_chains_list_cb == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Invalid cert_chains_list_cb pointer");
+
+    //Initialize data struct
+    memset(&certificate_chain, 0, sizeof(fcc_bundle_data_param_s));
+
+    for (cert_chain_index = 0; cert_chain_index < (uint32_t)cert_chains_list_cb->length; cert_chain_index++) {
+
+        FCC_SET_START_TIMER(fcc_certificate_chain_timer);
+
+        certificate_data = NULL;
+
+
+        //Get certificate chain CBOR struct at index cert_chain_index
+        cert_chain_cb = cn_cbor_index(cert_chains_list_cb, cert_chain_index);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((cert_chain_cb == NULL), fcc_status = FCC_STATUS_BUNDLE_ERROR, "Failed to get certificate chain at index (%" PRIu32 ") ", cert_chain_index);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((cert_chain_cb->type != CN_CBOR_MAP), fcc_status = FCC_STATUS_BUNDLE_ERROR, "Wrong type of certificate chain CBOR struct at index (%" PRIu32 ") ", cert_chain_index);
+
+        status = fcc_bundle_get_data_param(cert_chain_cb, &certificate_chain);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "Failed to get certificate chain data at index (%" PRIu32 ") ", cert_chain_index);
+
+        // create chain
+        kcm_result = kcm_cert_chain_create(&cert_chain_handle, certificate_chain.name, certificate_chain.name_len, (size_t)certificate_chain.array_cn->length, true);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_result != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_KCM_ERROR, exit, "Failed to create certificate chain");
+        
+        //Get all certificates in certificate chain and store it
+        for (cert_index = 0; cert_index < (uint32_t)certificate_chain.array_cn->length; cert_index++) {
+
+            cert_cb = cn_cbor_index(certificate_chain.array_cn, (unsigned int)cert_index);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((cert_cb == NULL), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "Failed to get cert cbor at index (%" PRIu32 ") ", cert_index);
+
+            status = get_data_buffer_from_cbor(cert_cb, &certificate_data, &certificate_data_size);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((status == false || certificate_data == NULL || certificate_data_size == 0), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "Failed to get cert data at index (%" PRIu32 ") ", cert_index);
+
+            //If private key name was passed - current leaf certificate is self generated and we need to perform verification against given private key
+            if (cert_index == 0 && certificate_chain.private_key_name != NULL) {
+                //Try to retrieve the private key from the device and verify the leaf certificate against private key data
+                kcm_result = kcm_certificate_verify_with_private_key(
+                    certificate_data,
+                    certificate_data_size,
+                    certificate_chain.private_key_name,
+                    certificate_chain.private_key_name_len);
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_result != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_CERTIFICATE_PUBLIC_KEY_CORRELATION_ERROR, exit, "Failed to verify leaf certificate against given private key (%" PRIu32 ") ", cert_chain_index);
+            }
+            kcm_result = kcm_cert_chain_add_next(cert_chain_handle, certificate_data, certificate_data_size);            
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_result != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_result), exit, "Failed to add certificate chain at index (%" PRIu32 ") ", cert_chain_index);
+        }
+        // close chain
+        kcm_result = kcm_cert_chain_close(cert_chain_handle);
+        cert_chain_handle = NULL;
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_result != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_KCM_ERROR, exit, "Failed to close certificate chain");
+        FCC_END_TIMER((char*)certificate_chain.name, certificate_chain.name_len, fcc_certificate_chain_timer);
+    }
+
+exit:
+    if (kcm_result != KCM_STATUS_SUCCESS) {
+        if (cert_chain_handle != NULL) {
+            kcm_cert_chain_close(cert_chain_handle);
+        }
+        //KCM_STATUS_ITEM_NOT_FOUND returned only if private key of self-generate certificate is missing.In this case we need to return name of themissing item -the private key.
+        if (kcm_result == KCM_STATUS_ITEM_NOT_FOUND) {
+            output_info_fcc_status = fcc_bundle_store_error_info(certificate_chain.private_key_name, certificate_chain.private_key_name_len, kcm_result);
+        } else {
+            output_info_fcc_status = fcc_bundle_store_error_info(certificate_chain.name, certificate_chain.name_len, kcm_result);
+        }
+
+    }
+    fcc_bundle_clean_and_free_data_param(&certificate_chain);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                    fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                    "Failed to create output kcm_status error %d", kcm_result);
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return fcc_status;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_certificate_utils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,101 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+#ifndef USE_TINY_CBOR
+#include "fcc_bundle_handler.h"
+#include "cn-cbor.h"
+#include "pv_error_handling.h"
+#include "fcc_bundle_utils.h"
+#include "key_config_manager.h"
+#include "fcc_output_info_handler.h"
+#include "fcc_time_profiling.h"
+#include "fcc_utils.h"
+
+
+/** Processes  certificate list.
+* The function extracts data parameters for each certificate and stores it.
+*
+* @param certs_list_cb[in]   The cbor structure with certificate list.
+*
+* @return
+*     true for success, false otherwise.
+*/
+fcc_status_e fcc_bundle_process_certificates(const cn_cbor *certs_list_cb)
+{
+    bool status = false;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_result =  KCM_STATUS_SUCCESS;
+    uint32_t cert_index = 0;
+    cn_cbor *cert_cb;
+    fcc_bundle_data_param_s certificate;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((certs_list_cb == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Invalid certs_list_cb pointer");
+
+    //Initialize data struct
+    memset(&certificate, 0, sizeof(fcc_bundle_data_param_s));
+
+    for (cert_index = 0; cert_index < (uint32_t)certs_list_cb->length; cert_index++) {
+
+        FCC_SET_START_TIMER(fcc_certificate_timer);
+
+        //fcc_bundle_clean_and_free_data_param(&certificate);
+
+        //Get key CBOR struct at index key_index
+        cert_cb = cn_cbor_index(certs_list_cb, cert_index);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((cert_cb == NULL), fcc_status = FCC_STATUS_BUNDLE_ERROR, "Failed to get certificate at index (%" PRIu32 ") ", cert_index);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((cert_cb->type != CN_CBOR_MAP), fcc_status = FCC_STATUS_BUNDLE_ERROR, "Wrong type of certificate CBOR struct at index (%" PRIu32 ") ", cert_index);
+
+        status = fcc_bundle_get_data_param(cert_cb, &certificate);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((status != true), fcc_status = FCC_STATUS_BUNDLE_ERROR, "Failed to get certificate data at index (%" PRIu32 ") ", cert_index);
+
+        //If private key name was passed with the certificate - the certificate is self-generated and we need to verify it agains given private key
+        if (certificate.private_key_name != NULL) {
+            //Try to retrieve the private key from the device and verify the certificate against key data
+            kcm_result = kcm_certificate_verify_with_private_key(
+                certificate.data,
+                certificate.data_size,
+                certificate.private_key_name,
+                certificate.private_key_name_len);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_result != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_CERTIFICATE_PUBLIC_KEY_CORRELATION_ERROR, exit, "Failed to verify certificate against given private key (%" PRIu32 ") ", cert_index);
+        }
+
+        kcm_result = kcm_item_store(certificate.name, certificate.name_len, KCM_CERTIFICATE_ITEM, true, certificate.data, certificate.data_size, certificate.acl);
+        FCC_END_TIMER((char*)certificate.name, certificate.name_len,fcc_certificate_timer);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_result != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_result), exit,"Failed to store certificate at index (%" PRIu32 ") ", cert_index);
+
+    }
+
+exit:
+    if (kcm_result != KCM_STATUS_SUCCESS) {
+        //FCC_STATUS_ITEM_NOT_EXIST returned only if private key of self-generate certificate is missing. In this case we need to return name of missing item
+        if (kcm_result == KCM_STATUS_ITEM_NOT_FOUND) {
+            output_info_fcc_status = fcc_bundle_store_error_info(certificate.private_key_name, certificate.private_key_name_len, kcm_result);
+        }
+        else {
+            output_info_fcc_status = fcc_bundle_store_error_info(certificate.name, certificate.name_len, kcm_result);
+        }
+
+
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR, 
+                                        "Failed to create output kcm_status error %d", kcm_result);
+    }
+    fcc_bundle_clean_and_free_data_param(&certificate);
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_common_utils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,315 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+#ifndef USE_TINY_CBOR
+#include "fcc_bundle_handler.h"
+#include "cn-cbor.h"
+#include "pv_error_handling.h"
+#include "fcc_bundle_utils.h"
+#include "fcc_malloc.h"
+#include "general_utils.h"
+#include "fcc_utils.h"
+#include "factory_configurator_client.h"
+
+#define  FCC_MAX_SIZE_OF_STRING 512
+
+/** Gets name from cbor struct.
+*
+* @param text_cb[in]          The cbor text structure
+* @param name_out[out]        The out buffer for string data
+* @param name_len_out[out]    The actual size of output buffer
+*
+* @return
+*     true for success, false otherwise.
+*/
+static bool get_data_name(const cn_cbor *text_cb, uint8_t **name_out, size_t *name_len_out)
+{
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((text_cb == NULL), false, "Cbor pointer is NULL");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((name_out == NULL), false, "Invalid pointer for name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((name_len_out == NULL), false, "Invalid pointer for name_len");
+
+    *name_out = (uint8_t*)fcc_malloc((size_t)(text_cb->length));
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((*name_out == NULL), false, "Failed to allocate buffer for name");
+
+    memcpy(*name_out, text_cb->v.bytes, (size_t)text_cb->length);
+    *name_len_out = (size_t)text_cb->length;
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return true;
+}
+
+/** Gets data format from cbor struct
+*
+* The function goes over all formats and compares it with format from cbor structure.
+*
+* @param data_cb[in]         The cbor text structure
+* @param data_format[out]    The format of data
+*
+* @return
+*     true for success, false otherwise.
+*/
+static bool get_data_format(const cn_cbor *data_cb, fcc_bundle_data_format_e *data_format)
+{
+
+    int data_format_index;
+    bool res;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((data_cb == NULL), false, "data_cb is null");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((data_format == NULL), false, "data_format is null");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((*data_format != FCC_INVALID_DATA_FORMAT), false, "wrong data format value");
+
+    for (data_format_index = 0; data_format_index < FCC_MAX_DATA_FORMAT - 1; data_format_index++) {
+        res = is_memory_equal(fcc_bundle_data_format_lookup_table[data_format_index].data_format_name,
+                              strlen(fcc_bundle_data_format_lookup_table[data_format_index].data_format_name),
+                              data_cb->v.bytes,
+                              (size_t)(data_cb->length));
+        if (res) {
+            *data_format = fcc_bundle_data_format_lookup_table[data_format_index].data_format_type;
+            return true;
+        }
+    }
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return false;
+}
+
+bool get_data_buffer_from_cbor(const cn_cbor *data_cb, uint8_t **out_data_buffer, size_t *out_size)
+{
+
+    cn_cbor_type cb_type;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((data_cb == NULL), false, "key_data_cb is null");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((out_size == NULL), false, "Size buffer is null ");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((out_data_buffer == NULL), false, "Data buffer is null");
+    cb_type = data_cb->type;
+
+    switch (cb_type) {
+        case CN_CBOR_TAG:
+            *out_data_buffer = (uint8_t*)data_cb->first_child->v.bytes;
+            *out_size = (size_t)data_cb->first_child->length;
+            break;
+        case CN_CBOR_TEXT:
+        case CN_CBOR_BYTES:
+            *out_data_buffer = (uint8_t*)data_cb->v.bytes;
+            *out_size = (size_t)(data_cb->length);
+            break;
+        case CN_CBOR_UINT:
+            *out_data_buffer = (uint8_t*)(&(data_cb->v.uint));
+            *out_size = (size_t)(data_cb->length);
+            break;
+        case CN_CBOR_INT:
+            *out_data_buffer = (uint8_t*)(&(data_cb->v.sint));
+            *out_size = (size_t)(data_cb->length);
+            break;
+        default:
+            SA_PV_LOG_ERR("Invalid cbor data type (%u)!", data_cb->type);
+            return false;
+    }
+    SA_PV_LOG_TRACE_FUNC_EXIT("out_size=%" PRIu32 "", (uint32_t)*out_size);
+    return true;
+}
+/** Frees all allocated memory of data parameter struct and sets initial values.
+*
+* @param data_param[in/out]    The data parameter structure
+*/
+void fcc_bundle_clean_and_free_data_param(fcc_bundle_data_param_s *data_param)
+{
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    if (data_param->name != NULL) {
+        fcc_free(data_param->name);
+        data_param->name = NULL;
+    }
+
+    if (data_param->private_key_name != NULL) {
+        fcc_free(data_param->private_key_name);
+        data_param->private_key_name = NULL;
+    }
+
+    data_param->array_cn = NULL;
+
+    //FIXME - in case we will support pem, add additional pointer data_der, that will point to allocated
+    // memory and will always released in case not NULL nad data pointer will relate to user buffer allways.
+    /*if (data_param->data_der != NULL) {
+    fcc_stats_free(data_param->data_der);
+    data_param->data_der = NULL;
+    }*/
+
+    memset(data_param, 0, sizeof(fcc_bundle_data_param_s));
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+}
+bool fcc_bundle_get_data_param(const cn_cbor *data_param_cb, fcc_bundle_data_param_s *data_param)
+{
+    bool status = false;
+    int data_param_index = 0;
+    cn_cbor *data_param_value_cb;
+    fcc_bundle_data_param_type_e data_param_type;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    //Prepare key struct
+    fcc_bundle_clean_and_free_data_param(data_param);
+
+    //Go over all key's parameters and extract it to appropriate key struct member
+    for (data_param_index = FCC_BUNDLE_DATA_PARAM_NAME_TYPE; data_param_index < FCC_BUNDLE_DATA_PARAM_MAX_TYPE; data_param_index++) {
+
+        //Get value of parameter
+        data_param_value_cb = cn_cbor_mapget_string(data_param_cb, fcc_bundle_data_param_lookup_table[data_param_index].data_param_name);
+
+        if (data_param_value_cb != NULL) {
+            //Get type of parameter
+            data_param_type = fcc_bundle_data_param_lookup_table[data_param_index].data_param_type;
+
+            switch (data_param_type) {
+                case FCC_BUNDLE_DATA_PARAMETER_PRIVATE_KEY_NAME_TYPE:
+                    status = get_data_name(data_param_value_cb, &(data_param->private_key_name), &(data_param->private_key_name_len));
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to get private key  name");
+                    break;
+
+                case FCC_BUNDLE_DATA_PARAM_NAME_TYPE:
+                    status = get_data_name(data_param_value_cb, &(data_param->name), &(data_param->name_len));
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to get data parameter name");
+                    break;
+
+                case FCC_BUNDLE_DATA_PARAM_SCHEME_TYPE:
+                    status = fcc_bundle_get_key_type(data_param_value_cb, (fcc_bundle_key_type_e*)&(data_param->type));
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to get parameter type");
+                    break;
+
+                case FCC_BUNDLE_DATA_PARAM_FORMAT_TYPE:
+                    status = get_data_format(data_param_value_cb, (fcc_bundle_data_format_e*)&(data_param->format));
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to get key format");
+                    break;
+
+                case FCC_BUNDLE_DATA_PARAM_DATA_TYPE:
+                    status = get_data_buffer_from_cbor(data_param_value_cb, &(data_param->data), &(data_param->data_size));
+                    data_param->data_type = FCC_EXTERNAL_BUFFER_TYPE;
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to get parameter data");
+                    break;
+                case FCC_BUNDLE_DATA_PARAM_ARRAY_TYPE:
+                    data_param->array_cn = data_param_value_cb;
+                    break;
+                case FCC_BUNDLE_DATA_PARAM_ACL_TYPE:
+                    status = get_data_buffer_from_cbor(data_param_value_cb, &(data_param->acl), &data_param->acl_size);
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to get acl data");
+                    break;
+                default:
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((true), status = false, error_exit, "Parameter's field name is illegal");
+            }//switch
+        }//if
+    }//for
+
+    //FIXME: should be uncommented if PEM format is supported.
+    /*
+      if (data_param->format == FCC_PEM_DATA_FORMAT) {
+          //status = convert_certificate_from_pem_to_der((uint8_t**)&(data_param->data), &(data_param->data_size));
+          SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, error_exit, "Failed to convert the key from pem to der");
+          //key->data_type = FCC_INTERNAL_BUFFER_TYPE;
+      }
+    */
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return status;
+
+error_exit:
+    fcc_bundle_clean_and_free_data_param(data_param);
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return false;
+}
+
+fcc_status_e fcc_bundle_process_sotp_buffer(cn_cbor *cbor_bytes, sotp_type_e sotp_type)
+{
+    uint8_t *buf;
+    size_t buf_size;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    bool status;
+    char *sotp_type_name;
+    size_t sotp_type_name_size = 0;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+	
+    fcc_status = fcc_get_sotp_type_name(sotp_type, &sotp_type_name, &sotp_type_name_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_INVALID_PARAMETER,exit, "Failed to get sotp type name");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_bytes->type != CN_CBOR_BYTES), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "cn_cbor object of incorrect type");
+
+    status = get_data_buffer_from_cbor(cbor_bytes, &buf, &buf_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((status == false), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "Unable to retrieve data from cn_cbor");
+
+    fcc_status = fcc_sotp_data_store(buf, buf_size, sotp_type);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_STORE_ERROR, exit, "Unable to store data to sotp");
+
+exit:
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        // In case of fcc_store_error_info failure we would still rather return the previous caught error.
+        (void)fcc_store_error_info((const uint8_t*)sotp_type_name, sotp_type_name_size, fcc_status);
+    }
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+fcc_status_e bundle_process_status_field(const cn_cbor *cbor_blob, char *cbor_group_name, size_t cbor_group_name_size, bool *fcc_field_status)
+{
+    uint8_t *buff = NULL;
+    size_t buff_size;
+    uint32_t fcc_field_value;
+    bool status;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_blob == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Invalid param cbor_blob");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_blob->type != CN_CBOR_UINT), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "Unexpected CBOR type");
+
+    status = get_data_buffer_from_cbor(cbor_blob, &buff, &buff_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((!status), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "Unable to retrieve data from cn_cbor");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((buff_size != sizeof(fcc_field_value)), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "Incorrect buffer size for field value");
+
+    memcpy(&fcc_field_value, buff, buff_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF(((fcc_field_value != 0) && (fcc_field_value != 1)), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit,"Unexpected value, should be either 0 or 1");
+
+    if (fcc_field_value == 1) {
+        *fcc_field_status = true;
+    }
+    else {
+        *fcc_field_status = false;
+    }
+
+exit:
+    if (fcc_status != FCC_STATUS_SUCCESS)
+    {
+        // In case of fcc_store_error_info failure we would still rather return the previous caught error.
+        (void)fcc_store_error_info((const uint8_t*)cbor_group_name, cbor_group_name_size, fcc_status);
+    }
+    return fcc_status;
+}
+
+
+fcc_status_e fcc_bundle_factory_disable( void )
+{
+
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+
+    fcc_status = fcc_factory_disable();
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to set factory disable flag");
+
+exit:
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        // In case of fcc_store_error_info failure we would still rather return the previous caught error.
+        (void)fcc_store_error_info((const uint8_t*)g_sotp_factory_disable_type_name, strlen(g_sotp_factory_disable_type_name), fcc_status);
+    }
+    return fcc_status;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_config_params_utils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,104 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+#ifndef USE_TINY_CBOR
+#include "fcc_bundle_handler.h"
+#include "cn-cbor.h"
+#include "pv_error_handling.h"
+#include "fcc_bundle_utils.h"
+#include "key_config_manager.h"
+#include "fcc_defs.h"
+#include "fcc_output_info_handler.h"
+#include "factory_configurator_client.h"
+#include "general_utils.h"
+#include "fcc_time_profiling.h"
+#include "fcc_utils.h"
+
+static fcc_status_e set_time_from_config_param(const fcc_bundle_data_param_s *current_time)
+{
+
+    fcc_status_e status;
+    uint64_t time = 0;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((current_time == NULL), FCC_STATUS_INVALID_PARAMETER, "Got invalid or corrupted 'current_time' pointer");
+
+    // Check given time length before copying
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((current_time->data_size > sizeof(uint64_t)), FCC_STATUS_MEMORY_OUT, "Time length (%" PRIu32 "B) too long (corrupted format?)", (uint32_t)current_time->data_size);
+    memcpy(&time, current_time->data, current_time->data_size);
+
+    status = fcc_time_set(time);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((status != FCC_STATUS_SUCCESS), FCC_STATUS_ERROR, "fcc_time_set failed");
+
+
+    return FCC_STATUS_SUCCESS;
+}
+
+fcc_status_e fcc_bundle_process_config_params(const cn_cbor *config_params_list_cb)
+{
+
+    bool success = false;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_result = KCM_STATUS_SUCCESS;
+    uint32_t config_param_index = 0;
+    cn_cbor *config_param_cb;
+    fcc_bundle_data_param_s config_param;
+    size_t currentTimeLength = strlen(g_fcc_current_time_parameter_name);
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((config_params_list_cb == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Invalid config_params_list_cb pointer");
+
+    //Initialize data struct
+    memset(&config_param, 0, sizeof(config_param));
+
+    for (config_param_index = 0; config_param_index < (uint32_t)config_params_list_cb->length; config_param_index++) {
+
+        FCC_SET_START_TIMER(fcc_config_param_timer);
+
+        //fcc_bundle_clean_and_free_data_param(&config_param);
+
+        //Get key CBOR struct at index key_index
+        config_param_cb = cn_cbor_index(config_params_list_cb, config_param_index);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((config_param_cb == NULL), fcc_status = FCC_STATUS_BUNDLE_ERROR, "Failed to get certificate at index (%" PRIu32 ") ", config_param_index);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((config_param_cb->type != CN_CBOR_MAP), fcc_status = FCC_STATUS_BUNDLE_ERROR, "Wrong type of config param CBOR struct at index (%" PRIu32 ")", config_param_index);
+
+        success = fcc_bundle_get_data_param(config_param_cb, &config_param);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((success != true), fcc_status = FCC_STATUS_BUNDLE_ERROR, "Failed to get config param data at index (%" PRIu32 ") ", config_param_index);
+
+        // Sets the time
+        if (is_memory_equal(config_param.name, config_param.name_len, g_fcc_current_time_parameter_name, currentTimeLength)) {
+            fcc_status = set_time_from_config_param(&config_param);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "set_time_from_config_param failed");
+        } else {
+            kcm_result = kcm_item_store(config_param.name, config_param.name_len, KCM_CONFIG_ITEM, true, config_param.data, config_param.data_size, config_param.acl);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_result != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_result), exit, "Failed to store configuration parameter at index (%" PRIu32 ") ", (uint32_t)config_param_index);
+        }
+        FCC_END_TIMER((char*)config_param.name, config_param.name_len, fcc_config_param_timer);
+    }
+
+exit:
+    if (kcm_result != KCM_STATUS_SUCCESS) {
+
+        output_info_fcc_status =  fcc_bundle_store_error_info(config_param.name, config_param.name_len, kcm_result);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output kcm_status error %d", kcm_result);
+    }
+    fcc_bundle_clean_and_free_data_param(&config_param);
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return fcc_status;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_csr_utils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,339 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+#ifndef USE_TINY_CBOR
+#include "fcc_bundle_utils.h"
+#include "fcc_bundle_handler.h"
+#include "fcc_malloc.h"
+#include "pv_error_handling.h"
+#include "fcc_utils.h"
+#include "kcm_internal.h"
+#include "fcc_bundle_fields.h"
+
+// For convenience when migrating to tinycbor
+#define CN_CBOR_NEXT_GET(cn) cn->next 
+
+// Initial attempt to allocate buffer for generated CSR will be <size (in bytes) of the encoded CSR request map (part of the CBOR)> + CSR_INITIAL_EXTRA_ALLOCATION_BYTES.
+// If the allocation is not enough we keep allocating an extra CSR_ALLOCATION_STEP until the buffer is sufficiently large, or, the allocation fails.
+#define CSR_INITIAL_EXTRA_ALLOCATION_BYTES 100
+#define CSR_ALLOCATION_STEP 100
+
+
+// FIXME: Temporary. This is a workaround so that the memory is still allocated when calling cn_cbor_encoder_write().
+// When we migrate to tinycbor we could either write the CSR directly into the preallocated encoder buffer, or write to a separate buffer, then write to the encoder, then immediately free the separate buffer.
+uint8_t *g_csr_buf[CSR_MAX_NUMBER_OF_CSRS] = { 0 };
+
+void g_csr_buf_free()
+{
+    int i;
+
+    for (i = 0; i < CSR_MAX_NUMBER_OF_CSRS; i++) {
+        fcc_free(g_csr_buf[i]);
+        g_csr_buf[i] = NULL;
+    }
+}
+
+static uint8_t **g_csr_next_available()
+{
+    int i;
+
+    for (i = 0; i < CSR_MAX_NUMBER_OF_CSRS; i++) {
+        if (!g_csr_buf[i]) {
+            return &g_csr_buf[i];
+        }
+    }
+
+    return NULL;
+}
+
+
+static fcc_status_e csr_extensions_parse(const cn_cbor *parser, kcm_csr_params_s *csr_params_out)
+{
+    cn_cbor *cbor_iterator, *cbor_extension_map;
+
+    // Get the extensions from the map - a map (optional, return success if does not exist)
+    cbor_extension_map = cn_cbor_mapget_string(parser, FCC_CSRREQ_INBOUND_EXTENSIONS_NAME);
+    if (!cbor_extension_map) {
+        return FCC_STATUS_SUCCESS;
+    }
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor_extension_map->type != CN_CBOR_MAP), FCC_STATUS_BUNDLE_ERROR, "Extensions wrong format");
+
+    // FIXME: Should parse the trust level from the extensions. Currently not in use
+
+    // Parse key usage (optional)
+    cbor_iterator = cn_cbor_mapget_string(cbor_extension_map, FCC_CSRREQ_INBOUND_EXTENSION_KEYUSAGE_NAME);
+    if (cbor_iterator) {
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor_iterator->type != CN_CBOR_UINT), FCC_STATUS_BUNDLE_ERROR, "Key usage wrong format");
+        csr_params_out->key_usage = (uint32_t)cbor_iterator->v.uint;
+    }
+
+    // Parse extended key usage (optional)
+    cbor_iterator = cn_cbor_mapget_string(cbor_extension_map, FCC_CSRREQ_INBOUND_EXTENSION_EXTENDEDKEYUSAGE_NAME);
+    if (cbor_iterator) {
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor_iterator->type != CN_CBOR_UINT), FCC_STATUS_BUNDLE_ERROR, "Extended Key usage wrong format");
+        csr_params_out->ext_key_usage = (uint32_t)cbor_iterator->v.uint;
+    }
+
+    return FCC_STATUS_SUCCESS;
+}
+/*
+* parser - points to a CSR request map
+*/
+static fcc_status_e csr_params_parse(const cn_cbor *parser, kcm_csr_params_s *csr_params_out)
+{
+    cn_cbor *cbor_iterator;
+    fcc_status_e fcc_status;
+
+    // Parse the extension (optional - will return success if extensions do not exist)
+    fcc_status = csr_extensions_parse(parser, csr_params_out);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Error parsing CSR extensions");
+
+    // Retrieve the MD type
+    cbor_iterator = cn_cbor_mapget_string(parser, FCC_CSRREQ_INBOUND_MESSAGEDIGEST_NAME);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor_iterator == NULL), FCC_STATUS_BUNDLE_ERROR, "No MD type");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor_iterator->type != CN_CBOR_UINT), FCC_STATUS_BUNDLE_ERROR, "MD type wrong format");
+
+    csr_params_out->md_type = (kcm_md_type_e)cbor_iterator->v.uint;
+
+    // Retrieve the subject
+    cbor_iterator = cn_cbor_mapget_string(parser, FCC_CSRREQ_INBOUND_SUBJECT_NAME);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor_iterator == NULL), FCC_STATUS_BUNDLE_ERROR, "No subject");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor_iterator->type != CN_CBOR_BYTES && cbor_iterator->type != CN_CBOR_TEXT), FCC_STATUS_BUNDLE_ERROR, "Subject wrong format");
+
+    // Allocate memory for the subject, it may be large and must be terminated with a '\0' terminator
+    csr_params_out->subject = fcc_malloc((size_t)cbor_iterator->length + 1);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params_out->subject == NULL), FCC_STATUS_MEMORY_OUT, "Error allocating subject");
+
+    memcpy(csr_params_out->subject, cbor_iterator->v.bytes, (size_t)cbor_iterator->length);
+
+    // Append the NULL terminator
+    csr_params_out->subject[cbor_iterator->length] = '\0';
+
+    return FCC_STATUS_SUCCESS;
+}
+
+/** Parse, create, and encode the next CSR map into the CSR cbor array in the response CBOR
+* The outcome of this function is that the following map will be appended to the encoder: {"PrKN: "<name>", "Data": <CSR byte array>}
+* @param parser CSRrequest map:
+*    INBOUND MESSAGE:
+*    {
+*     ...
+*
+*     "CsrReqs" : [ { ... }, { ... }, ... , <YOU ARE HERE> ]
+*
+*     ...
+*    }
+*
+* @param encoder - points to the next place in the CSR CBOR array:
+*    OUTBOUND MESSAGE:
+*    {
+*     ...
+*
+*     "Csrs" : [ { ... }, { ... }, ... , <YOU ARE HERE> ]
+*
+*     ...
+*    }
+*
+*
+*/
+static fcc_status_e encode_next_csr(const cn_cbor *parser, cn_cbor *encoder)
+{
+    kcm_csr_params_s csr_params;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    bool status;
+    size_t csr_extra_bytes = CSR_INITIAL_EXTRA_ALLOCATION_BYTES;
+    size_t csr_buf_len;
+    const uint8_t *private_key_name, *public_key_name;
+    size_t private_key_name_len, public_key_name_len;
+    int approximated_csr_size = 0;
+    uint8_t **csr_buf;
+    size_t csr_len = 0;
+
+    char *key;
+    cn_cbor *val, *cbor, *encoder_iterator;
+
+    memset(&csr_params, 0, sizeof(kcm_csr_params_s));
+
+    // First, Create and open a new map for the encoder, that will eventually look like that {"PrKN: "<name>", "Data": <CSR byte array>}
+    encoder_iterator = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA NULL);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((encoder_iterator == NULL), FCC_STATUS_MEMORY_OUT, "Error creating CBOR");
+
+    // Push the empty map into the encoder (open the container part 2)
+    status = cn_cbor_array_append(encoder, encoder_iterator, NULL);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((status == false), FCC_STATUS_BUNDLE_ERROR, "CBOR error");
+
+    // Get private key name
+    cbor = cn_cbor_mapget_string(parser, FCC_CSRREQ_INBOUND_PRIVATE_KEY_NAME);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor == NULL), FCC_STATUS_BUNDLE_ERROR, "No private key in message");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor->type != CN_CBOR_TEXT), FCC_STATUS_BUNDLE_ERROR, "No private key in message");
+
+    private_key_name = cbor->v.bytes;
+    private_key_name_len = (size_t)cbor->length;
+
+    // Append Name key-value into the encoder
+    val = cn_cbor_text_create(private_key_name, (int)private_key_name_len, CBOR_CONTEXT_PARAM_COMMA NULL);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((val == NULL), FCC_STATUS_MEMORY_OUT, "Error creating CBOR");
+    status = cn_cbor_mapput_string(encoder_iterator, FCC_CSR_OUTBOUND_MAP_PRIVATE_KEY_NAME, val, CBOR_CONTEXT_PARAM_COMMA NULL);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((status == false), FCC_STATUS_BUNDLE_ERROR, "CBOR error");
+
+    // Get public key name. Field is optional, if does not exist - set to NULL
+    cbor = cn_cbor_mapget_string(parser, FCC_CSRREQ_INBOUND_PUBLIC_KEY_NAME);
+    if (cbor == NULL) {
+        public_key_name = NULL;
+        public_key_name_len = 0;
+    } else {
+        public_key_name = cbor->v.bytes;
+        public_key_name_len = (size_t)cbor->length;
+    }
+
+    // Extract CSR params
+    fcc_status = csr_params_parse(parser, &csr_params);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, Exit, "Error parsing CSR params");
+
+    // Gets the size in bytes of the encoded CSR request map
+    approximated_csr_size = cn_cbor_get_encoded_container_size(parser);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((approximated_csr_size < 0), fcc_status = FCC_STATUS_BUNDLE_ERROR, Exit, "Error getting encoded CBOR size");
+
+    approximated_csr_size += KCM_EC_SECP256R1_MAX_PUB_KEY_DER_SIZE + KCM_ECDSA_SECP256R1_MAX_SIGNATURE_SIZE_IN_BYTES;
+
+    csr_buf = g_csr_next_available();
+
+    // Start with an approximate allocation and keep trying to increase the allocation until it is sufficiently large, or some error occurres.
+    while (true) {
+        csr_buf_len = (size_t)approximated_csr_size + csr_extra_bytes;
+        *csr_buf = fcc_malloc(csr_buf_len);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((*csr_buf == NULL), fcc_status = FCC_STATUS_MEMORY_OUT, Exit, "Error generating CSR");
+
+        // Generate the CSR into the encoder 
+        // FIXME: when migrating to tinycbor we might want to try to encode it directly into the encoder buffer. This may require manually creating the cbor byte-array prefix (major type 3)
+        // Requires understanding the CBOR mechanism but could save significant space since this way the CSR will not be duplicated.
+        kcm_status = kcm_generate_keys_and_csr(KCM_SCHEME_EC_SECP256R1, private_key_name, private_key_name_len,
+                                               public_key_name, public_key_name_len, true, &csr_params,
+                                               *csr_buf, csr_buf_len, &csr_len,
+                                               NULL);
+        if (kcm_status == KCM_STATUS_SUCCESS) {
+            break;
+        } else if (kcm_status == KCM_STATUS_INSUFFICIENT_BUFFER) { // If buffer insufficient - attempt with larger buffer
+            csr_extra_bytes += CSR_ALLOCATION_STEP;
+        } else {
+            fcc_status = fcc_convert_kcm_to_fcc_status(kcm_status);
+            goto Exit;
+        }
+    }
+
+    // Append the encoded CSR data key-value to the CSR response map
+    key = FCC_CSR_OUTBOUND_MAP_DATA;
+    val = cn_cbor_data_create(*csr_buf, (int)csr_len, CBOR_CONTEXT_PARAM_COMMA NULL);    
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((val == NULL), fcc_status = FCC_STATUS_MEMORY_OUT, Exit, "Error creating CBOR");
+
+    status = cn_cbor_mapput_string(encoder_iterator, key, val, CBOR_CONTEXT_PARAM_COMMA NULL);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((status == false), fcc_status = FCC_STATUS_BUNDLE_ERROR, Exit, "CBOR error");
+
+    // FIXME: For tinycbor - this would be the time to close the map opened in the beginning - {"Name: "<name>", "Format": "der", "Data": <CSR byte array>}
+
+Exit:
+    fcc_free(csr_params.subject);
+    // If KCM error - store the KCM error, If FCC error, store the FCC error
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_bundle_store_error_info(private_key_name, private_key_name_len, kcm_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output kcm_status error %d", kcm_status);
+    } 
+    
+
+    return fcc_status;
+}
+
+/** Parse a CBOR array of CSR requests, for each CSR request - generate the keys and the CSR, save the keys in the persistent storage, and encode the CSR in the response encoder.
+* @param csrs_list_cb CSR Requests array:
+*    INBOUND MESSAGE:
+*    {
+*     ...
+*
+*     "CsrReqs" : <YOU ARE HERE>
+*
+*     ...
+*    }
+*
+* @param response_encoder - points to the next place in the CSR CBOR array:
+*    OUTBOUND MESSAGE:
+*    {
+*     "SchemeVersion": "0.0.1", 
+*     ...
+*
+*     <YOU ARE HERE>
+*
+*     ...
+*    }
+*
+*
+*/
+fcc_status_e fcc_bundle_process_csrs(const cn_cbor *csrs_list_cb, cn_cbor *response_encoder)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    cn_cbor *cbor, *encoder_iterator;
+    const cn_cbor *parser_iterator;
+    bool status;
+    int i = 0;
+
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((csrs_list_cb == NULL || response_encoder == NULL), fcc_status = FCC_STATUS_BUNDLE_ERROR, SetError, "Invalid cbor_blob");
+    
+    // Make sure we get a array of CSR requests
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((csrs_list_cb->type != CN_CBOR_ARRAY), fcc_status = FCC_STATUS_BUNDLE_ERROR, SetError, "CSR requests must be array");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((csrs_list_cb->length > CSR_MAX_NUMBER_OF_CSRS), fcc_status = FCC_STATUS_TOO_MANY_CSR_REQUESTS, SetError, "More CSR requests than the maximum allowed");
+
+    parser_iterator = csrs_list_cb;
+
+    // Open a new map for the encoder (open the container part 1)
+    cbor = cn_cbor_array_create(CBOR_CONTEXT_PARAM_COMMA NULL);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor == NULL), fcc_status = FCC_STATUS_MEMORY_OUT, SetError, "Error creating CBOR");
+
+    // Push the empty array into the encoder (open the container part 2)
+    status = cn_cbor_mapput_string(response_encoder, FCC_CSR_OUTBOUND_GROUP_NAME, cbor, CBOR_CONTEXT_PARAM_COMMA NULL);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((status == false), fcc_status = FCC_STATUS_BUNDLE_ERROR, SetError, "Error appending");
+
+    // Step into the encoder array (the last child is the value of the last appended KV pair which is the empty array)
+    encoder_iterator = response_encoder->last_child;
+
+    // Go to the first value of the array
+    parser_iterator = parser_iterator->first_child;
+
+    for (i = 0; i < csrs_list_cb->length; i++) {
+
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((parser_iterator == NULL), fcc_status = FCC_STATUS_BUNDLE_ERROR, SetError, "Error getting CBOR");
+
+        fcc_status = encode_next_csr(parser_iterator, encoder_iterator);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, SetError, "Error encoding CSR");
+        
+        // step into next value in the CBOR array
+        parser_iterator = CN_CBOR_NEXT_GET(parser_iterator);
+    }
+
+SetError:
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_store_error_info(NULL, 0, fcc_status);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output fcc_status error %d", fcc_status);
+    }
+
+    return fcc_status;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_handler.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,568 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+#ifndef USE_TINY_CBOR
+#include "fcc_bundle_handler.h"
+#include "cn-cbor.h"
+#include "pv_error_handling.h"
+#include "factory_configurator_client.h"
+#include "fcc_bundle_utils.h"
+#include "fcc_output_info_handler.h"
+#include "fcc_malloc.h"
+#include "fcc_sotp.h"
+#include "general_utils.h"
+#include "fcc_time_profiling.h"
+#include "fcc_utils.h"
+#include "fcc_bundle_fields.h"
+
+/**
+* Defines for cbor layer
+*/
+#ifdef USE_CBOR_CONTEXT
+#define CONTEXT_NULL , NULL
+#define CONTEXT_NULL_COMMA NULL,
+#else
+#define CONTEXT_NULL
+#define CONTEXT_NULL_COMMA
+#endif
+
+/**
+* Definition of size and value of current protocol scheme version
+*/
+#define FCC_SIZE_OF_VERSION_FIELD 5
+const char fcc_bundle_scheme_version[] = "0.0.1";
+extern bool g_is_session_finished;
+
+// FIXME: temporary. Will be removed when migration to tinycbor is complete
+void g_csr_buf_free();
+
+/**
+* Types of configuration parameter groups
+*/
+typedef enum {
+    FCC_KEY_GROUP_TYPE,                //!< Key group type
+    FCC_CERTIFICATE_GROUP_TYPE,        //!< Certificate group type
+    FCC_CONFIG_PARAM_GROUP_TYPE,       //!< Configuration parameter group type
+    FCC_CERTIFICATE_CHAIN_GROUP_TYPE,  //!< Certificate chain group type
+    FCC_SCHEME_VERSION_TYPE,           //!< Scheme version group type
+    FCC_ENTROPY_TYPE,                  //!< Entropy group type
+    FCC_ROT_TYPE,                      //!< Root of trust group type
+    FCC_VERIFY_DEVICE_IS_READY_TYPE,   //!< Verify device readiness type
+    FCC_FACTORY_DISABLE_TYPE,          //!< Disable FCC flow type
+    FCC_IS_ALIVE_SESSION_GROUP_TYPE,   //!< Indicates current message status - last message or not
+    FCC_FCU_SESSION_ID_GROUP_TYPE,     //!< Session ID sent by the FCU
+    FCC_CSR_REQUESTS_GROUP_TYPE,       //!< CSR requests type
+    FCC_MAX_CONFIG_PARAM_GROUP_TYPE    //!< Max group type
+} fcc_bundle_param_group_type_e;
+
+/**
+* Group lookup record, correlating group's type and name
+*/
+typedef struct fcc_bundle_group_lookup_record_ {
+    fcc_bundle_param_group_type_e group_type;
+    const char *group_name;
+} fcc_bundle_group_lookup_record_s;
+/**
+* Group lookup table, correlating for each group its type and name.
+* Order is important - it is the order that fcc_bundle_handler() reads the cbor fields.
+* FCC_ENTROPY_TYPE and FCC_ROT_TYPE Must be processed first and second respectively.
+*/
+static const fcc_bundle_group_lookup_record_s fcc_groups_lookup_table[FCC_MAX_CONFIG_PARAM_GROUP_TYPE] = {
+    { FCC_SCHEME_VERSION_TYPE,           FCC_BUNDLE_SCHEME_GROUP_NAME },
+    { FCC_ENTROPY_TYPE,                  FCC_ENTROPY_NAME },
+    { FCC_ROT_TYPE,                      FCC_ROT_NAME },
+    { FCC_IS_ALIVE_SESSION_GROUP_TYPE,   FCC_KEEP_ALIVE_SESSION_GROUP_NAME },
+    { FCC_KEY_GROUP_TYPE,                FCC_KEY_GROUP_NAME },
+    { FCC_CERTIFICATE_GROUP_TYPE,        FCC_CERTIFICATE_GROUP_NAME },
+    { FCC_CONFIG_PARAM_GROUP_TYPE,       FCC_CONFIG_PARAM_GROUP_NAME },
+    { FCC_CERTIFICATE_CHAIN_GROUP_TYPE,  FCC_CERTIFICATE_CHAIN_GROUP_NAME },
+    { FCC_VERIFY_DEVICE_IS_READY_TYPE,   FCC_VERIFY_DEVICE_IS_READY_GROUP_NAME },
+    { FCC_FACTORY_DISABLE_TYPE,          FCC_FACTORY_DISABLE_GROUP_NAME },
+    { FCC_FCU_SESSION_ID_GROUP_TYPE,     FCC_FCU_SESSION_ID_GROUP_TYPE_NAME },
+    { FCC_CSR_REQUESTS_GROUP_TYPE,       FCC_CSR_REQUESTS_GROUP_NAME }
+};
+
+
+
+
+/* Response cbor blob structure
+
+{  "SchemeVersion": "0.0.1",
+   "FCUSessionID": uint32_t,
+   "Csrs": [ {"Name": "__", "Format":"_","Data":"__"},
+             {"Name": "__", "Format":"_","Data":"__"}],
+   "WarningInfo": "string of warnings",
+   "ReturnStatus": uint32_t,
+   "InfoMessage": "detailed error string"}
+*/
+/** Prepare a response message
+*
+* The function prepare response buffer according to result of bundle buffer processing.
+* In case of failure, the function prepare buffer with status,scheme version and error logs,
+* in case of success - only the status and scheme version.
+*
+* @param bundle_response_out[in/out]   The pointer to response buffer.
+* @param bundle_response_size_out[out/out]     The size of response buffer.
+* @param fcc_status[in]     The result of bundle buffer processing.
+* 
+* @return
+*     true for success, false otherwise.
+*/
+static bool prepare_reponse_message(uint8_t **bundle_response_out, size_t *bundle_response_size_out, fcc_status_e fcc_status, cn_cbor *encoder, const uint8_t *session_id, size_t session_id_len)
+{
+    bool status = false;
+    cn_cbor_errback err;
+    cn_cbor *cbor_struct_cb = NULL;
+    int size_of_cbor_buffer = 0;
+    int size_of_out_buffer = 0;
+    uint8_t *out_buffer = NULL;
+    char *error_string_info = NULL;
+    char *warning_string_info = NULL;
+    const char success_message[] = { "The Factory process succeeded\n" };
+    *bundle_response_out = NULL;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    // If error has occurred during bundle processing - create a new encoder (all that was encoded is not needed)
+    // If no error occurred - the encoder will already have the scheme version and the FCU session ID inside an open map - therefore, in case of an error, we add them to a new map
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        // Free the old encoder and create a new one
+        if (encoder) {
+            cn_cbor_free(encoder CBOR_CONTEXT_PARAM);
+        }
+        encoder = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &err);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((encoder == NULL), false, "Failed to create cbor map");
+
+        /**
+        * Create cbor with scheme version
+        */
+        cbor_struct_cb = NULL;
+        cbor_struct_cb = cn_cbor_text_create((const uint8_t *)fcc_bundle_scheme_version, sizeof(fcc_bundle_scheme_version) CBOR_CONTEXT_PARAM, &err);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "Failed to create scheme_version_cb ");
+
+        //Put the cbor scheme version in cbor map with string key "SchemeVersion"
+        status = cn_cbor_mapput_string(encoder, FCC_BUNDLE_SCHEME_GROUP_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed to put return status to cbor map");
+
+        //Put the cbor session ID in cbor map with string key "SID"
+        if(session_id != NULL) { 
+            cbor_struct_cb = cn_cbor_text_create(session_id, (int)session_id_len CBOR_CONTEXT_PARAM, &err);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "CBOR error");
+
+            status = cn_cbor_mapput_string(encoder, FCC_FCU_SESSION_ID_GROUP_TYPE_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed to put return session ID");
+        }
+    }
+
+
+    /**
+    * Create cbor with return status
+    */
+    cbor_struct_cb = cn_cbor_int_create(fcc_status CBOR_CONTEXT_PARAM, &err);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "Failed to create return_status_cb ");
+
+    //Put the cbor return status in cbor map with string key "ReturnStatus"
+    status = cn_cbor_mapput_string(encoder, FCC_RETURN_STATUS_GROUP_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed top put return status to cbor map");
+
+
+    /**
+    * Create cbor with error info
+    */
+    cbor_struct_cb = NULL;
+    if (fcc_status == FCC_STATUS_SUCCESS) {
+        cbor_struct_cb = cn_cbor_text_create((const uint8_t*)success_message, (int)strlen(success_message) CBOR_CONTEXT_PARAM, &err);
+    } else {
+        error_string_info = fcc_get_output_error_info();
+        if (error_string_info == NULL) {
+            cbor_struct_cb = cn_cbor_text_create((const uint8_t*)g_fcc_general_status_error_str, (int)strlen(g_fcc_general_status_error_str) CBOR_CONTEXT_PARAM, &err);
+        } else {
+            cbor_struct_cb = cn_cbor_text_create((const uint8_t*)error_string_info, (int)strlen(error_string_info) CBOR_CONTEXT_PARAM, &err);
+       }
+    }
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "Failed to create cbor_struct_cb ");
+
+    //Put the cbor info message in cbor map with string key "infoMessage"
+    status = cn_cbor_mapput_string(encoder, FCC_ERROR_INFO_GROUP_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed top put cbor_struct_cb to cbor map");
+
+    /**
+    * Create cbor with warning info
+    */
+    cbor_struct_cb = NULL;
+    status = fcc_get_warning_status();
+    warning_string_info = fcc_get_output_warning_info();
+    SA_PV_ERR_RECOVERABLE_GOTO_IF(status == true && warning_string_info == NULL, status = false, exit, "Failed to get created warnings");
+    if (warning_string_info != NULL) {
+        cbor_struct_cb = cn_cbor_text_create((const uint8_t *)warning_string_info, (int)strlen(warning_string_info) CBOR_CONTEXT_PARAM, &err);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((cbor_struct_cb == NULL), status = false, exit, "Failed to create warning_message_cb ");
+
+        //Put the cbor info message in cbor map with string key "WarningInfo"
+        status = cn_cbor_mapput_string(encoder, FCC_WARNING_INFO_GROUP_NAME, cbor_struct_cb CBOR_CONTEXT_PARAM, &err);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), status = false, exit, "Failed top put warning_message_cb to cbor map");
+    } 
+
+    status = true;
+    //Get size of encoded cbor buffer
+    size_of_cbor_buffer = cn_cbor_get_encoded_size(encoder, &err);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((size_of_cbor_buffer == -1), status = false, exit, "Failed to get cbor buffer size");
+
+    //Allocate out buffer
+    out_buffer = fcc_malloc((size_t)size_of_cbor_buffer);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((out_buffer == NULL), status = false, exit, "Failed to allocate memory for out buffer");
+
+    //Write cbor blob to output buffer
+    size_of_out_buffer = cn_cbor_encoder_write(encoder, out_buffer, size_of_cbor_buffer, &err);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((size_of_out_buffer == -1), status = false, exit_without_out_buffer, "Failed to  write cbor buffer to output buffer");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((size_of_out_buffer != size_of_cbor_buffer), status = false, exit_without_out_buffer, "Wrong written size for outbut buffer");
+
+    //Update pointer and size of output buffer
+    *bundle_response_out = out_buffer;
+    *bundle_response_size_out = (size_t)size_of_out_buffer;
+    goto exit;
+
+exit_without_out_buffer:
+    fcc_free(out_buffer);
+
+    // Nullify pointer so that the user cannot accidentally double free it.
+    *bundle_response_out = NULL;
+exit:
+    // FIXME: Free the CSRs buffer after the writing to the encoder buffer. Not needed after migration to tinycbor
+    g_csr_buf_free();
+    fcc_free(warning_string_info);
+    if (encoder != NULL) {
+        cn_cbor_free(encoder CBOR_CONTEXT_PARAM);
+    }
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return status;
+}
+
+
+/** Checks bundle scheme version
+*
+* @param cbor_blob[in]   The pointer to main cbor blob.
+* @param encoder[in]     Pointer to an encoder that points to the beginning of the CBOR response encoder
+*
+* FIXME: When we migrate to tinycbor encoder should be pointer to the encoder so that after encoding, the encoder will point to the next available spot in the response CBOR
+* @return
+*     true for success, false otherwise.
+*/
+static bool check_scheme_version(cn_cbor *cbor_blob, cn_cbor *encoder)
+{
+    cn_cbor *cbor = NULL;
+    bool status;
+    int result;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor_blob == NULL), false, "Invalid cbor_blob");
+
+    cbor = cn_cbor_mapget_string(cbor_blob, FCC_BUNDLE_SCHEME_GROUP_NAME);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor == NULL), false, "Failed to find scheme version group");
+
+    result = is_memory_equal(cbor->v.bytes, (size_t)(cbor->length), fcc_bundle_scheme_version, (size_t)strlen(fcc_bundle_scheme_version));
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((!result), false, "Wrong scheme version");
+
+    // append the scheme version key-value into the encoder
+    cbor = cn_cbor_text_create((const uint8_t *)fcc_bundle_scheme_version, sizeof(fcc_bundle_scheme_version) CBOR_CONTEXT_PARAM, NULL);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor == NULL), false, "Failed to create scheme_version_cb ");
+
+    status = cn_cbor_mapput_string(encoder, FCC_BUNDLE_SCHEME_GROUP_NAME, cbor, CBOR_CONTEXT_PARAM_COMMA NULL);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((status == false), status, "CBOR error");
+
+    return true;
+}
+
+/** Checks the FCU session ID and encodes it into the encoder
+*
+* @param parser[in]             Pointer to cbor containing the FCU session ID (the value of the KV pair where the key is FCC_FCU_SESSION_ID_GROUP_TYPE_NAME).
+* @param encoder[in]            Pointer to an encoder that points to the beginning of the CBOR response encoder.
+* @param session_id[out]        Pointer to a pointer that will point to the session ID in the incoming message.
+* @param session_id_len[out]    The length of the session ID in the incoming message.
+*
+* FIXME: When we migrate to tinycbor encoder should be pointer to the encoder so that after encoding, the encoder will point to the next available spot in the response CBOR
+* @return
+*     true for success, false otherwise.
+*/
+static bool fcc_bundle_process_session_id(cn_cbor *parser, cn_cbor *encoder, const uint8_t **session_id, size_t *session_id_len)
+{
+    cn_cbor *cbor = NULL;
+    bool status;
+
+    // Get the session ID from the message and make sure that it is either a text or bytes string
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((parser->type != CN_CBOR_TEXT), false, "Session ID of wrong type");
+
+    // Output the values for use of the prepare_reponse_message() function in case of an error during the bundle handling process
+    *session_id = (uint8_t *)parser->v.bytes;
+    *session_id_len = (size_t)parser->length;
+
+    cbor = cn_cbor_text_create(*session_id, (int)*session_id_len CBOR_CONTEXT_PARAM, NULL);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((cbor == NULL), false, "CBOR error");
+	
+    // append the session id key-value into the encoder
+    status = cn_cbor_mapput_string(encoder, FCC_FCU_SESSION_ID_GROUP_TYPE_NAME, cbor, CBOR_CONTEXT_PARAM_COMMA NULL);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((status == false), false, "CBOR error");
+
+    return true;
+}
+
+
+
+/** The function parses group that indicates if current session will be closed after the processing of the message.
+*  The function checks existence and value of the group and sets the result to global variable g_is_alive_sesssion.
+*
+* @param cbor_blob[in]   The pointer to main cbor blob.
+* @return
+*     true for success, false otherwise.
+*/
+static bool parse_keep_alive_session_group(cn_cbor *cbor_blob)
+{
+    cn_cbor *is_alive_message = NULL;
+
+    is_alive_message = cn_cbor_mapget_string(cbor_blob, FCC_KEEP_ALIVE_SESSION_GROUP_NAME);
+    //In case current group wasn't found -  set g_is_not_last_message to false (for backward compatibility)
+    if (is_alive_message == NULL) {
+        g_is_session_finished = true;
+        return true;
+    }
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((is_alive_message->type != CN_CBOR_UINT || is_alive_message->v.uint > 1), false, "Wrong is alive session structure");
+
+    // Session is finished if value is 0, and alive if value is 1
+    g_is_session_finished = !(is_alive_message->v.uint);
+
+    return true;
+}
+
+/* CBOR blob structure
+{   "SchemeVersion": "0.0.1",
+    "FCUSessionID": uint32_t,
+    "IsNotLastMessage": 1 or 0,
+    "Entropy": [byte array - 48 bytes],
+    "Csrs": [ {"PrivKeyName":"__",
+               "PubKeyName": "__", -optional
+               "Extensions": [
+                               {"TrustLevel": uint32_t },
+                               {
+                                   "KeyUsage":  [uint32_t,uint32_t,unit32_t ],
+                               },
+                               {
+                                   "ExtendedKeyUsage":  [byte array],
+                               }]
+               "Subject": "C=__,ST=__ ,L=__, O=__,OU=__,CN=__,",
+                },
+                { ... },
+                { ... }
+              ],
+    "ROT": "byte array",
+    "Certificates": [ {"Name": "__", "Format":" _","Data":"__", "ACL" : "__"},
+                      {..},
+                      {"Name": "__", "Format":" _","Data":"__", "ACL" : "__"}],
+    "Keys": [ {"Name": "__", "Type":"__", "Format":"__", "Data":"**","ACL" : "__"},
+              {"Name": "__", "Type":"__", "Format":"__", "Data":"**","ACL": "__"},
+               ...
+              {"Name": "__", "Type":"__", "Format":"__", "Data":"**","ACL": "__"}],
+    "ConfigParams": [ {"Name": "__", "Data":"__", "ACL" : "__"},
+                      {"Name": "__", "Format":"__", "Data":"__", "ACL": "__"},
+                       ...,
+                      {"Name": "__", "Format":"__", "Data":"__", "ACL": "__"}],
+    "CertificateChains": [ {"Name": "mbed.CertificateChain",
+                            "DataArray":[h'3081870.....',h'308187020100...',h'308187020....'],
+                            "Format":"Der",
+                            "ACL":"_____"},
+                          {"Name": "mbed.LwM2MCertificateChain",
+                           "DataArray":[h'308187...',h'30818702...',h'308187020...',h'308187020...',h'308187020...'],
+                           "Format":"Der",
+                           "ACL":"_____"}],
+    "Verify":1, 
+    "Disable":1}
+*/
+fcc_status_e fcc_bundle_handler(const uint8_t *encoded_blob, size_t encoded_blob_size, uint8_t **bundle_response_out, size_t *bundle_response_size_out)
+{
+    bool status = false;
+    bool is_fcc_factory_disabled;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    cn_cbor *main_list_cb = NULL;
+    cn_cbor *group_value_cb = NULL;
+    cn_cbor *response_cbor = NULL;
+    cn_cbor_errback err;
+    size_t group_index;
+    fcc_bundle_param_group_type_e group_type;
+    size_t num_of_groups_in_message = 0;
+    const uint8_t *session_id = NULL;
+    size_t session_id_len = 0;
+    bool fcc_verify_status = true; // the default value of verify status is true
+    bool fcc_disable_status = false;// the default value of disable status is false
+
+
+    FCC_SET_START_TIMER(fcc_bundle_timer);
+
+    SA_PV_LOG_INFO_FUNC_ENTER("encoded_blob_size = %" PRIu32 "", (uint32_t)encoded_blob_size);
+
+    // Set *bundle_response_out to NULL before fcc_is_factory_disabled call so that in case factory is disabled - return FCC_STATUS_FACTORY_DISABLED_ERROR and nullify *bundle_response_out
+    if (bundle_response_out != NULL) {
+        // Set to NULL so that the user does not accidentally free a non NULL pointer after the function returns.
+        *bundle_response_out = NULL;
+    }
+
+    // Check if factory flow is disabled, if yes, do not proceed
+    fcc_status = fcc_is_factory_disabled(&is_fcc_factory_disabled);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status, "Failed for fcc_is_factory_disabled");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((is_fcc_factory_disabled), FCC_STATUS_FACTORY_DISABLED_ERROR, "FCC is disabled, service not available");
+
+    // Check params
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((bundle_response_out == NULL), FCC_STATUS_INVALID_PARAMETER, "Invalid bundle_response_out");
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((bundle_response_size_out == NULL), FCC_STATUS_INVALID_PARAMETER, "Invalid bundle_response_size_out");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((encoded_blob == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Invalid encoded_blob");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((encoded_blob_size == 0), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Invalid encoded_blob_size");
+
+    /*Initialize fcc_output_info_s structure , in case of error during store process the
+    function will exit without fcc_verify_device_configured_4mbed_cloud where we perform additional fcc_clean_output_info_handler*/
+    fcc_clean_output_info_handler();
+
+    // Create the CBOR encoder, an empty map
+    response_cbor = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &err);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((response_cbor == NULL), fcc_status = FCC_STATUS_MEMORY_OUT, exit, "Failed to instatiate cbor structure");
+
+    /* Decode CBOR message
+    Check the size of the CBOR structure */
+    main_list_cb = cn_cbor_decode(encoded_blob, encoded_blob_size CBOR_CONTEXT_PARAM, &err);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((main_list_cb == NULL), fcc_status = FCC_STATUS_BUNDLE_ERROR, exit, "cn_cbor_decode failed (%" PRIu32 ")", (uint32_t)err.err);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((main_list_cb->type != CN_CBOR_MAP), fcc_status = FCC_STATUS_BUNDLE_ERROR, free_cbor_list_and_out, "Wrong CBOR structure type");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((main_list_cb->length <= 0 || main_list_cb->length > FCC_MAX_CONFIG_PARAM_GROUP_TYPE *FCC_CBOR_MAP_LENGTH), fcc_status = FCC_STATUS_BUNDLE_ERROR, free_cbor_list_and_out, "Wrong CBOR structure size");
+
+    /* Check scheme version*/
+    status = check_scheme_version(main_list_cb, response_cbor);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), fcc_status = FCC_STATUS_BUNDLE_INVALID_SCHEME, free_cbor_list_and_out, "check_scheme_version failed");
+
+    /* Parse and save is message status */
+    status = parse_keep_alive_session_group(main_list_cb);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((status != true), fcc_status = FCC_STATUS_BUNDLE_INVALID_KEEP_ALIVE_SESSION_STATUS, free_cbor_list_and_out, "parse_keep_alive_session_group failed");
+
+    //Go over parameter groups
+    for (group_index = 0; group_index < FCC_MAX_CONFIG_PARAM_GROUP_TYPE; group_index++) {
+        //Get content of current group (value of map, when key of map is name of group and value is list of params of current group)
+        SA_PV_LOG_INFO(" fcc_groups_lookup_table[group_index].group_name is %s", fcc_groups_lookup_table[group_index].group_name);
+        group_value_cb = cn_cbor_mapget_string(main_list_cb, fcc_groups_lookup_table[group_index].group_name);
+
+        if (group_value_cb != NULL) {
+            //Get type of group
+            group_type = fcc_groups_lookup_table[group_index].group_type;
+            num_of_groups_in_message++;
+
+            switch (group_type) {
+                case FCC_SCHEME_VERSION_TYPE:
+                    break;
+                case FCC_ENTROPY_TYPE: // Entropy for random generator
+                    fcc_status = fcc_bundle_process_sotp_buffer(group_value_cb, SOTP_TYPE_RANDOM_SEED);
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_sotp_buffer failed for entropy");
+                    break;
+                case FCC_ROT_TYPE: // Key for ESFS
+                    fcc_status = fcc_bundle_process_sotp_buffer(group_value_cb, SOTP_TYPE_ROT);
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_sotp_buffer failed for ROT");
+                    break;
+                case FCC_IS_ALIVE_SESSION_GROUP_TYPE:
+                    break;
+                case FCC_KEY_GROUP_TYPE:
+                    FCC_SET_START_TIMER(fcc_gen_timer);
+                    fcc_status = fcc_bundle_process_keys(group_value_cb);
+                    FCC_END_TIMER("Total keys process", 0 ,fcc_gen_timer);
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_keys failed");
+                    break;
+                case FCC_CERTIFICATE_GROUP_TYPE:
+                    FCC_SET_START_TIMER(fcc_gen_timer);
+                    fcc_status = fcc_bundle_process_certificates(group_value_cb);
+                    FCC_END_TIMER("Total certificates process", 0, fcc_gen_timer);
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_certificates failed");
+                    break;
+                case FCC_CONFIG_PARAM_GROUP_TYPE:
+                    FCC_SET_START_TIMER(fcc_gen_timer);
+                    fcc_status = fcc_bundle_process_config_params(group_value_cb);
+                    FCC_END_TIMER("Total config params process", 0, fcc_gen_timer);
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_config_params failed");
+                    break;
+                case FCC_CERTIFICATE_CHAIN_GROUP_TYPE:
+                    FCC_SET_START_TIMER(fcc_gen_timer);
+                    fcc_status = fcc_bundle_process_certificate_chains(group_value_cb);
+                    FCC_END_TIMER("Total certificate chains process", 0, fcc_gen_timer);
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_certificate_chains failed");
+                    break;
+                case FCC_VERIFY_DEVICE_IS_READY_TYPE: //Check if device need to be verified
+                    fcc_status = bundle_process_status_field(group_value_cb, (char*)FCC_VERIFY_DEVICE_IS_READY_GROUP_NAME, strlen((char*)FCC_VERIFY_DEVICE_IS_READY_GROUP_NAME), &fcc_verify_status);
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "process_device_verify failed");
+                    break;
+                case FCC_FACTORY_DISABLE_TYPE://Check if device need to be disabled for factory
+                    fcc_status = bundle_process_status_field(group_value_cb, (char*)FCC_FACTORY_DISABLE_GROUP_NAME, strlen((char*)FCC_FACTORY_DISABLE_GROUP_NAME), &fcc_disable_status);
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_factory_disable failed");
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_disable_status == true && g_is_session_finished == false), fcc_status = FCC_STATUS_BUNDLE_INVALID_KEEP_ALIVE_SESSION_STATUS, free_cbor_list_and_out, "can not disable fcc for intermidiate message");
+                    break;
+                case FCC_FCU_SESSION_ID_GROUP_TYPE:
+                    status = fcc_bundle_process_session_id(group_value_cb, response_cbor, &session_id, &session_id_len);
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((!status), fcc_status = FCC_STATUS_BUNDLE_ERROR, free_cbor_list_and_out, "fcc_bundle_process_session_id failed");
+                    break;
+                case FCC_CSR_REQUESTS_GROUP_TYPE:
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((session_id == NULL), fcc_status = FCC_STATUS_BUNDLE_ERROR, free_cbor_list_and_out, "Session ID is required when providing CSR requests");
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_verify_status || fcc_disable_status), fcc_status = FCC_STATUS_BUNDLE_ERROR, free_cbor_list_and_out, "Verify and Disable flags must not exist with CSR requests");
+                    fcc_status = fcc_bundle_process_csrs(group_value_cb, response_cbor);
+                    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_bundle_process_csrs failed");
+                    break;
+                default:
+                    fcc_status = FCC_STATUS_BUNDLE_UNSUPPORTED_GROUP;
+                    SA_PV_LOG_ERR("Wrong group type");
+                    goto free_cbor_list_and_out;
+            }
+        }
+    }
+
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((num_of_groups_in_message == 0), fcc_status = FCC_STATUS_INVALID_PARAMETER, free_cbor_list_and_out, "No groups in message");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF(((size_t)(main_list_cb->length/FCC_CBOR_MAP_LENGTH)!= num_of_groups_in_message), fcc_status = FCC_STATUS_BUNDLE_INVALID_GROUP, free_cbor_list_and_out, "One ore more names of groups are invalid");
+
+    // If not keep alive
+    if (g_is_session_finished) {
+        // Note that FCC_STATUS_CA_ERROR is being return only in case where the CA already exists
+        // in SOTP, if in the future more error conditions will be attached to FCC_STATUS_CA_ERROR error code
+        // then the logic here MUST be change.
+        // Only if this is the last message - set the certificate ID
+        fcc_status = fcc_trust_ca_cert_id_set();
+        SA_PV_ERR_RECOVERABLE_GOTO_IF(((fcc_status != FCC_STATUS_SUCCESS) && (fcc_status != FCC_STATUS_CA_ERROR)), (fcc_status = fcc_status), free_cbor_list_and_out, "CA store error %u", fcc_status);
+
+    }
+
+    if (fcc_verify_status == true) {
+        // device VERIFY group does NOT exist in the CBOR message and device is NOT disabled.
+        // Perform device verification to keep backward compatibility.
+
+
+        FCC_SET_START_TIMER(fcc_gen_timer);
+        fcc_status = fcc_verify_device_configured_4mbed_cloud();
+        FCC_END_TIMER("Total verify device", 0, fcc_gen_timer);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_verify_device_configured_4mbed_cloud failed");
+    }
+
+    if (fcc_disable_status == true) {
+        fcc_status = fcc_bundle_factory_disable();
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, free_cbor_list_and_out, "fcc_factory_disable failed");
+    }
+
+free_cbor_list_and_out:
+    cn_cbor_free(main_list_cb CBOR_CONTEXT_PARAM);
+exit:
+    //Prepare bundle response message
+    status = prepare_reponse_message(bundle_response_out, bundle_response_size_out, fcc_status, response_cbor, session_id, session_id_len);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((status != true), FCC_STATUS_BUNDLE_RESPONSE_ERROR, "Failed to prepare out response");
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    FCC_END_TIMER("Total fcc_bundle_handler device", 0, fcc_bundle_timer);
+    
+    return fcc_status;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/fcc_bundle_key_utils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,164 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+#ifndef USE_TINY_CBOR
+#include "fcc_bundle_handler.h"
+#include "cn-cbor.h"
+#include "pv_error_handling.h"
+#include "fcc_bundle_utils.h"
+#include "key_config_manager.h"
+#include "fcc_output_info_handler.h"
+#include "general_utils.h"
+#include "fcc_time_profiling.h"
+#include "fcc_utils.h"
+
+#define  FCC_MAX_PEM_KEY_SIZE 1024*2
+/**
+* Names of key types
+*/
+#define FCC_ECC_PRIVATE_KEY_TYPE_NAME  "ECCPrivate"
+#define FCC_ECC_PUBLIC_KEY_TYPE_NAME   "ECCPublic"
+#define FCC_RSA_PRIVATE_KEY_TYPE_NAME  "RSAPrivate"
+#define FCC_RSA_PUBLIC_KEY_TYPE_NAME   "RSAPublic"
+#define FCC_SYMMETRIC_KEY_TYPE_NAME    "Symmetric"
+/**
+* Group lookup record, correlating group's type and name
+*/
+typedef struct fcc_bundle_key_type_lookup_record_ {
+    fcc_bundle_key_type_e key_type;
+    const char *key_type_name;
+} fcc_bundle_key_type_lookup_record_s;
+/**
+* Group lookup table, correlating for each group its type and name
+*/
+static const fcc_bundle_key_type_lookup_record_s fcc_bundle_key_type_lookup_table[FCC_MAX_KEY_TYPE] = {
+    { FCC_ECC_PRIVATE_KEY_TYPE,          FCC_ECC_PRIVATE_KEY_TYPE_NAME },
+    { FCC_ECC_PUBLIC_KEY_TYPE,           FCC_ECC_PUBLIC_KEY_TYPE_NAME },
+    { FCC_RSA_PRIVATE_KEY_TYPE,          FCC_RSA_PRIVATE_KEY_TYPE_NAME },
+    { FCC_RSA_PUBLIC_KEY_TYPE,           FCC_RSA_PUBLIC_KEY_TYPE_NAME },
+    { FCC_SYM_KEY_TYPE,                  FCC_SYMMETRIC_KEY_TYPE_NAME }
+};
+/**  Gets type of key form cbor structure
+*
+* The function goes over all key types and compares it with type inside cbor structure.
+*
+* @param key_type_cb[in]   The cbor structure with key type data.
+* @param key_type[out]     The key type
+*
+* @return
+*     true for success, false otherwise.
+*/
+bool fcc_bundle_get_key_type(const cn_cbor *key_type_cb, fcc_bundle_key_type_e *key_type)
+{
+
+    int key_type_index;
+    bool res;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((key_type_cb == NULL), false, "key_type_cb is null");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((key_type == NULL), false, "key_type is null");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((*key_type != FCC_INVALID_KEY_TYPE), false, "wrong key type value");
+
+    for (key_type_index = 0; key_type_index < FCC_MAX_KEY_TYPE -1; key_type_index++) {
+        res = is_memory_equal(fcc_bundle_key_type_lookup_table[key_type_index].key_type_name,
+                             strlen(fcc_bundle_key_type_lookup_table[key_type_index].key_type_name),
+                             key_type_cb->v.bytes,
+                             (size_t)key_type_cb->length);
+        if (res) {
+            *key_type = fcc_bundle_key_type_lookup_table[key_type_index].key_type;
+            return true;
+        }
+    }
+    SA_PV_LOG_TRACE_FUNC_EXIT("key_type is %d", (int)(*key_type));
+    return false;
+
+}
+
+/** Processes  keys list.
+* The function extracts data parameters for each key and stores its according to it type.
+*
+* @param keys_list_cb[in]   The cbor structure with keys list.
+*
+* @return
+*     true for success, false otherwise.
+*/
+fcc_status_e fcc_bundle_process_keys(const cn_cbor *keys_list_cb)
+{
+
+    bool status = false;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_status_e output_info_fcc_status = FCC_STATUS_SUCCESS;
+    kcm_status_e kcm_result = KCM_STATUS_SUCCESS;
+    uint32_t key_index = 0;
+    cn_cbor *key_cb;
+    fcc_bundle_data_param_s key;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((keys_list_cb == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Invalid keys_list_cb pointer");
+
+    //Initialize data struct
+    memset(&key,0,sizeof(fcc_bundle_data_param_s));
+
+    for (key_index = 0; key_index < (uint32_t)keys_list_cb->length; key_index++) {
+
+        FCC_SET_START_TIMER(fcc_key_timer);
+
+        //fcc_bundle_clean_and_free_data_param(&key);
+
+        //Get key CBOR struct at index key_index
+        key_cb = cn_cbor_index(keys_list_cb, key_index);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((key_cb == NULL), fcc_status = FCC_STATUS_BUNDLE_ERROR, "Failed to get key at index (%" PRIu32 ") ", key_index);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((key_cb->type != CN_CBOR_MAP), fcc_status = FCC_STATUS_BUNDLE_ERROR, "Wrong type of key CBOR struct at index (%" PRIu32 ")", key_index);
+
+        status = fcc_bundle_get_data_param(key_cb, &key);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((status != true), fcc_status = FCC_STATUS_BUNDLE_ERROR, "Failed to get key data at index (%" PRIu32 ") ", key_index);
+
+        switch (key.type) {
+            case FCC_ECC_PRIVATE_KEY_TYPE:
+            case FCC_RSA_PRIVATE_KEY_TYPE:
+                kcm_result = kcm_item_store(key.name, key.name_len, KCM_PRIVATE_KEY_ITEM, true, key.data, key.data_size, key.acl);
+                SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_result != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_result), exit, "Failed to store key private at index (%" PRIu32 ") ", key_index);
+                break;
+
+            case FCC_ECC_PUBLIC_KEY_TYPE:
+            case FCC_RSA_PUBLIC_KEY_TYPE:
+                kcm_result = kcm_item_store(key.name, key.name_len, KCM_PUBLIC_KEY_ITEM, true, key.data, key.data_size, key.acl);
+                SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_result != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_result), exit, "Failed to store key public at index (%" PRIu32 ") ", key_index);
+                break;
+
+            case (FCC_SYM_KEY_TYPE):
+                kcm_result = kcm_item_store(key.name, key.name_len, KCM_SYMMETRIC_KEY_ITEM, true, key.data, key.data_size, key.acl);
+                SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_result != KCM_STATUS_SUCCESS), fcc_status = fcc_convert_kcm_to_fcc_status(kcm_result), exit, "Failed to store symmetric key at index (%" PRIu32 ") ", key_index);
+                break;
+            default:
+                SA_PV_LOG_ERR("Invalid key type (%u)!", key.type);
+                goto exit;
+        }
+        FCC_END_TIMER((char*)key.name, key.name_len, fcc_key_timer);
+    }
+
+exit:
+    if (kcm_result != KCM_STATUS_SUCCESS) {
+        output_info_fcc_status = fcc_bundle_store_error_info(key.name, key.name_len, kcm_result);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((output_info_fcc_status != FCC_STATUS_SUCCESS),
+                                        fcc_status = FCC_STATUS_OUTPUT_INFO_ERROR,
+                                        "Failed to create output kcm_status error %d", kcm_result);
+    }
+    fcc_bundle_clean_and_free_data_param(&key);
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-bundle-handler/source/include/fcc_bundle_utils.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,266 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+#ifndef USE_TINY_CBOR
+
+#ifndef __FCC_BUNDLE_UTILS_H__
+#define __FCC_BUNDLE_UTILS_H__
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include "fcc_status.h"
+#include "key_config_manager.h"
+#include "fcc_sotp.h"
+#include "cn-cbor.h"
+#include "fcc_bundle_fields.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FCC_CBOR_MAP_LENGTH 2
+#define CSR_MAX_NUMBER_OF_CSRS 5
+
+    /**
+* Types of key parameters
+*/
+typedef enum {
+    FCC_BUNDLE_DATA_PARAM_NAME_TYPE,
+    FCC_BUNDLE_DATA_PARAM_SCHEME_TYPE,
+    FCC_BUNDLE_DATA_PARAM_FORMAT_TYPE,
+    FCC_BUNDLE_DATA_PARAM_DATA_TYPE,
+    FCC_BUNDLE_DATA_PARAM_ACL_TYPE,
+    FCC_BUNDLE_DATA_PARAM_ARRAY_TYPE,
+    FCC_BUNDLE_DATA_PARAMETER_PRIVATE_KEY_NAME_TYPE,
+    FCC_BUNDLE_DATA_PARAM_MAX_TYPE
+} fcc_bundle_data_param_type_e;
+
+/**
+* Key lookup record, correlating key's param type and name
+*/
+typedef struct fcc_bundle_data_param_lookup_record_ {
+    fcc_bundle_data_param_type_e data_param_type;
+    const char *data_param_name;
+} fcc_bundle_data_param_lookup_record_s;
+
+/**
+* Key lookup table, correlating for each key its param type and param name
+*/
+static const fcc_bundle_data_param_lookup_record_s fcc_bundle_data_param_lookup_table[FCC_BUNDLE_DATA_PARAM_MAX_TYPE] = {
+    { FCC_BUNDLE_DATA_PARAM_NAME_TYPE,          FCC_BUNDLE_DATA_PARAMETER_NAME },
+    { FCC_BUNDLE_DATA_PARAM_SCHEME_TYPE,        FCC_BUNDLE_DATA_PARAMETER_SCHEME },
+    { FCC_BUNDLE_DATA_PARAM_FORMAT_TYPE,        FCC_BUNDLE_DATA_PARAMETER_FORMAT },
+    { FCC_BUNDLE_DATA_PARAM_DATA_TYPE,          FCC_BUNDLE_DATA_PARAMETER_DATA },
+    { FCC_BUNDLE_DATA_PARAM_ACL_TYPE,           FCC_BUNDLE_DATA_PARAMETER_ACL },
+    { FCC_BUNDLE_DATA_PARAM_ARRAY_TYPE,         FCC_BUNDLE_DATA_PARAMETER_ARRAY },
+    { FCC_BUNDLE_DATA_PARAMETER_PRIVATE_KEY_NAME_TYPE, FCC_BUNDLE_DATA_PARAMETER_PRIVATE_KEY_NAME }
+};
+
+/**
+* Source type of buffer
+*/
+typedef enum {
+    FCC_EXTERNAL_BUFFER_TYPE,
+    FCC_INTERNAL_BUFFER_TYPE,
+    FCC_MAX_BUFFER_TYPE
+} fcc_bundle_buffer_type_e;
+
+/**
+* Data formats supported by FC
+*/
+typedef enum {
+    FCC_INVALID_DATA_FORMAT,
+    FCC_DER_DATA_FORMAT,
+    FCC_PEM_DATA_FORMAT,
+    FCC_MAX_DATA_FORMAT
+} fcc_bundle_data_format_e;
+
+/**
+* Group lookup record, correlating group's type and name
+*/
+typedef struct fcc_bundle_data_format_lookup_record_ {
+    fcc_bundle_data_format_e data_format_type;
+    const char *data_format_name;
+} fcc_bundle_data_format_lookup_record_s;
+
+/**
+* Group lookup table, correlating for each group its type and name
+*/
+static const fcc_bundle_data_format_lookup_record_s fcc_bundle_data_format_lookup_table[FCC_MAX_DATA_FORMAT] = {
+    { FCC_DER_DATA_FORMAT,          FCC_BUNDLE_DER_DATA_FORMAT_NAME },
+    { FCC_PEM_DATA_FORMAT,          FCC_BUNDLE_PEM_DATA_FORMAT_NAME },
+};
+
+/**
+* Key types supported by FC
+*/
+typedef enum {
+    FCC_INVALID_KEY_TYPE,
+    FCC_ECC_PRIVATE_KEY_TYPE,//do not change this type's place.FCC_ECC_PRIVATE_KEY_TYPE should be at first place.
+    FCC_ECC_PUBLIC_KEY_TYPE,
+    FCC_RSA_PRIVATE_KEY_TYPE,
+    FCC_RSA_PUBLIC_KEY_TYPE,
+    FCC_SYM_KEY_TYPE,
+    FCC_MAX_KEY_TYPE
+} fcc_bundle_key_type_e;
+
+typedef struct fcc_bundle_data_param_ {
+    uint8_t                          *name;
+    size_t                           name_len;
+    fcc_bundle_data_format_e         format;
+    fcc_bundle_key_type_e            type;
+    uint8_t                          *data;
+    size_t                           data_size;
+    uint8_t                          *data_der;
+    size_t                           data_der_size;
+    fcc_bundle_buffer_type_e         data_type;
+    uint8_t                          *acl;
+    size_t                           acl_size;
+    cn_cbor                          *array_cn;
+    uint8_t                           *private_key_name;
+    size_t                           private_key_name_len;
+} fcc_bundle_data_param_s;
+
+
+/** Frees all allocated memory of data parameter struct and sets initial values.
+*
+* @param data_param[in/out]    The data parameter structure
+*/
+void fcc_bundle_clean_and_free_data_param(fcc_bundle_data_param_s *data_param);
+
+/** Gets data buffer from cbor struct.
+*
+* @param data_cb[in]          The cbor text structure
+* @param out_data_buffer[out] The out buffer for string data
+* @param out_size[out]        The actual size of output buffer
+*
+* @return
+*     true for success, false otherwise.
+*/
+bool get_data_buffer_from_cbor(const cn_cbor *data_cb, uint8_t **out_data_buffer, size_t *out_size);
+
+/** Processes  keys list.
+* The function extracts data parameters for each key and stores its according to it type.
+*
+* @param keys_list_cb[in]   The cbor structure with keys list.
+*
+* @return
+*     fcc_status_e status.
+*/
+fcc_status_e fcc_bundle_process_keys(const cn_cbor *keys_list_cb);
+
+/** Processes  certificate list.
+* The function extracts data parameters for each certificate and stores it.
+*
+* @param certs_list_cb[in]   The cbor structure with certificate list.
+*
+* @return
+*      fcc_status_e status.
+*/
+fcc_status_e fcc_bundle_process_certificates(const cn_cbor *certs_list_cb);
+/** Processes  certificate chain list.
+* The function extracts data parameters for each certificate chain and stores it.
+*
+* @param certs_list_cb[in]   The cbor structure with certificate chain list.
+*
+* @return
+*      fcc_status_e status.
+*/
+fcc_status_e fcc_bundle_process_certificate_chains(const cn_cbor *cert_chains_list_cb);
+
+/** Processes  configuration parameters list.
+* The function extracts data parameters for each config param and stores it.
+*
+* @param config_params_list_cb[in]   The cbor structure with config param list.
+*
+* @return
+*      fcc_status_e status.
+*/
+fcc_status_e fcc_bundle_process_config_params(const cn_cbor *config_params_list_cb);
+
+/** Gets data parameters.
+*
+* The function goes over all existing parameters (name,type,format,data,acl and etc) and
+* tries to find correlating parameter in cbor structure and saves it to data parameter structure.
+*
+* @param data_param_cb[in]   The cbor structure with relevant data parameters.
+* @param data_param[out]     The data parameter structure
+*
+* @return
+*     true for success, false otherwise.
+*/
+bool fcc_bundle_get_data_param(const cn_cbor *data_param_list_cb, fcc_bundle_data_param_s *data_param);
+
+/**  Gets type of key form cbor structure
+*
+* The function goes over all key types and compares it with type inside cbor structure.
+*
+* @param key_type_cb[in]   The cbor structure with key type data.
+* @param key_type[out]     The key type
+*
+* @return
+*     true for success, false otherwise.
+*/
+bool fcc_bundle_get_key_type(const cn_cbor *key_type_cb, fcc_bundle_key_type_e *key_type);
+
+/** Writes buffer to SOTP
+*
+* @param cbor_bytes[in]   The pointer to a cn_cbor object of type CN_CBOR_BYTES.
+* @param sotp_type[in]    enum representing the type of the item to be stored in SOTP.
+* @return
+*     true for success, false otherwise.
+*/
+
+fcc_status_e fcc_bundle_process_sotp_buffer(cn_cbor *cbor_bytes, sotp_type_e sotp_type);
+
+/** Gets the status groups value
+*
+* - if value is '0' - set status to false
+* - if value is '1' - set status to true
+*
+* @param cbor_blob[in]             The pointer to main CBOR blob.
+* @param cbor_group_name[in]       CBOT group name.
+* @param cbor_group_name_size[in]  CBOR group name size .
+* @param fcc_field_status[out]     Status of the field.
+*
+* @return
+*     One of FCC_STATUS_* error codes
+*/
+fcc_status_e bundle_process_status_field(const cn_cbor *cbor_blob, char *cbor_group_name, size_t cbor_group_name_size, bool *fcc_field_status);
+
+/** The function sets factory disable flag to sotp.
+*
+* @return
+*     One of FCC_STATUS_* error codes
+*/
+fcc_status_e fcc_bundle_factory_disable(void);
+
+/** Process the the CSR requests from the incoming message, generate the keys (and store them) and CSRs, and append the CSRs to the encoder in the proper format.
+* 
+*
+* @param csrs_list_cb[in]   The pointer to a cn_cbor object of type CN_CBOR_ARRAY which is an array of CSR request maps.
+* @param response_encoder[in/out]    encoder that points to the response map.
+* @return
+*     One of FCC_STATUS_* error codes
+*/
+fcc_status_e fcc_bundle_process_csrs(const cn_cbor *csrs_list_cb, cn_cbor *response_encoder);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__FCC_BUNDLE_UTILS_H__
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-output-info-handler/fcc-output-info-handler/fcc_output_info_handler.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,124 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FCC_OUTPUT_INFO_HANDLER_H__
+#define __FCC_OUTPUT_INFO_HANDLER_H__
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include  "kcm_status.h"
+#include "fcc_output_info_handler_defines.h"
+#include "fcc_defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+*   Initializes resources of output info handler
+*/
+void  fcc_init_output_info_handler( void );
+
+/**
+*  Finalizes resources of output info handler
+*/
+void  fcc_clean_output_info_handler( void );
+
+/**
+*  Returns true if FCC was initialized false otherwise
+*/
+bool is_fcc_initialized(void);
+
+/**  The function stores the name of failed item and kcm error string in global variables
+* The error returned by fcc_bundle_handler API.
+*
+* @param failed_item_name[in]          The name of failed item 
+* @param failed_item_name_size[in]     The size of failed item name.
+* @param kcm_status[in]                The kcm status value.
+*
+* @return
+*     true for success, false otherwise.
+*/
+fcc_status_e fcc_bundle_store_error_info(const uint8_t *failed_item_name, size_t failed_item_name_size, kcm_status_e kcm_status);
+
+/**  The function stores the name of failed item and fcc error string in global variables
+*The error returned by fcc_verify_device_configured_4mbed_cloud API.
+
+* @param failed_item_name[in]          The name of failed item. If NULL, error will be stored without an item name.
+* @param failed_item_name_size[in]     The size of failed item name.
+* @param fcc_status[in]               The fcc status value.
+*
+* @return
+*     true for success, false otherwise.
+*/
+fcc_status_e fcc_store_error_info(const uint8_t *failed_item_name, size_t failed_item_name_size, fcc_status_e fcc_status);
+
+/**  The function stores the all collected warnings and relevant item names during fcc_verify_device_configured_4mbed_cloud API.
+*
+* @param failed_item_name[in]          The name of failed item
+* @param failed_item_name_size[in]     The size of failed item name.
+* @param fcc_status[in]               The fcc status value.
+*
+* @return
+*     true for success, false otherwise.
+*/
+fcc_status_e fcc_store_warning_info(const uint8_t *failed_item_name, size_t failed_item_name_size, const char *warning_string);
+/**  The function return saved failed item name
+*
+* @return
+*     NULL if no errors or char* pointer to the saved item name
+*/
+char* fcc_get_output_error_info( void );
+/**  The function return saved warnings as single string
+*
+* @return
+*     NULL  if no warnings exist or char* pointer to the string of all warnings
+*/
+char*  fcc_get_output_warning_info(void);
+
+/**  The function returns relevant pointer to string of passed fcc_status.
+*
+* @return
+*     string /NULL in case the fcc_status string wasn't found
+*/
+char* fcc_get_fcc_error_string(fcc_status_e fcc_status);
+
+/**  The function returns relevant pointer to string of passed kcm_status.
+*
+* @return
+*     string /NULL in case the kcm_status string wasn't found
+*/
+char* fcc_get_kcm_error_string(kcm_status_e kcm_status);
+
+/**  The function gets output info structure
+*
+* @return
+*/
+fcc_output_info_s* get_output_info(void);
+
+/**  The function gets status of warning info
+*
+* @return
+*    true - if warnings were stored, false in case of no warning
+*/
+bool fcc_get_warning_status(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__FCC_OUTPUT_INFO_HANDLER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-output-info-handler/fcc-output-info-handler/fcc_output_info_handler_defines.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,94 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FCC_OUTPUT_INFO_HANDLER_DEFINES_H__
+#define __FCC_OUTPUT_INFO_HANDLER_DEFINES_H__
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include  "kcm_status.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//General error string
+extern const char g_fcc_general_status_error_str[];
+
+//fcc error strings
+extern const char g_fcc_ca_error_str[];
+extern const char g_fcc_rot_error_str[];
+extern const char g_fcc_entropy_error_str[];
+extern const char g_fcc_disabled_error_str[];
+extern const char g_fcc_invalid_certificate_error_str[];
+extern const char g_fcc_item_not_exists_error_str[];
+extern const char g_fcc_meta_data_not_exists_error_str[];
+extern const char g_fcc_meta_data_size_error_str[];
+extern const char g_fcc_wrong_item_size_error_str[];
+extern const char g_fcc_empty_item_error_str[];
+extern const char g_fcc_uri_wrong_format_error_str[];
+extern const char g_fcc_first_to_claim_not_allowed_error_str[];
+extern const char g_fcc_wrong_utc_offset_value_error_str[];
+extern const char g_fcc_wrong_ca_certificate_error_str[];
+extern const char g_fcc_invalid_cn_certificate_error_str[];
+extern const char g_fcc_crypto_public_key_correlation_error_str[];
+extern const char g_fcc_internal_storage_error_str[];
+extern const char g_fcc_csr_requests_too_many[];
+
+//kcm crypto error strings
+extern const char g_fcc_kcm_file_exist_error_str[];
+extern const char g_fcc_kcm_key_exist_error_str[];
+extern const char g_fcc_kcm_invalid_num_of_cert_in_chain_str[];
+extern const char g_fcc_crypto_empty_item_error_str[];
+extern const char g_fcc_crypto_unsupported_hash_mode_error_str[];
+extern const char g_fcc_crypto_parsing_der_pivate_key_error_str[];
+extern const char g_fcc_crypto_parsing_der_public_key_error_str[];
+extern const char g_fcc_crypto_verify_private_key_error_str[];
+extern const char g_fcc_crypto_verify_public_key_error_str[];
+extern const char g_fcc_crypto_unsupported_curve_error_str[];
+extern const char g_fcc_crypto_parsing_der_cert_error_str[];
+extern const char g_fcc_crypto_cert_expired_error_str[];
+extern const char g_fcc_crypto_cert_future_error_str[];
+extern const char g_fcc_crypto_cert_md_alg_error_str[];
+extern const char g_fcc_crypto_cert_public_key_type_error_str[];
+extern const char g_fcc_crypto_cert_public_key_error_str[];
+extern const char g_fcc_crypto_cert_not_trusted_error_str[];
+extern const char g_fcc_crypto_invalid_x509_attr_error_str[];
+extern const char g_fcc_wrong_bootstrap_use_value_error_str[];
+extern const char g_fcc_crypto_invalid_pk_key_format_error_str[];
+extern const char g_fcc_crypto_invalid_public_key_error_str[];
+extern const char g_fcc_crypto_ecp_invalid_key_error_str[];
+extern const char g_fcc_crypto_pk_key_invalid_version_error_str[];
+extern const char g_fcc_crypto_pk_password_requerd_error_str[];
+extern const char g_fcc_crypto_unknown_pk_algorithm_error_str[];
+extern const char g_fcc_crypto_chain_validation_error_str[];
+extern const char g_fcc_self_generated_certificate_validation_error_str[];
+//warning strings
+extern const char g_fcc_item_not_set_warning_str[];
+extern const char g_fcc_bootstrap_mode_false_warning_str[];
+extern const char g_fcc_time_is_not_set_warning_str[];
+extern const char g_fcc_self_signed_warning_str[];
+extern const char g_fcc_item_is_empty_warning_str[];
+extern const char g_fcc_redundant_item_warning_str[];
+extern const char g_fcc_cert_time_validity_warning_str[];
+extern const char g_fcc_cert_validity_less_10_years_warning_str[];
+extern const char g_fcc_ca_identifier_warning_str[];
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__FCC_OUTPUT_INFO_HANDLER_DEFINES_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/fcc-output-info-handler/source/fcc_output_info_handler.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,624 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include "pv_error_handling.h"
+#include "fcc_status.h"
+#include "fcc_output_info_handler.h"
+#include "fcc_malloc.h"
+#include "kcm_defs.h"
+#include "fcc_bundle_utils.h"
+
+// Macros for stringizing defines
+#define xstr(a) str(a)
+#define str(a) #a
+
+
+//General error string
+const char g_fcc_general_status_error_str[] = "General error:";
+
+//fcc error strings
+const char g_fcc_ca_error_str[] = "CA error:";
+const char g_fcc_rot_error_str[] = "Root of trust error:";
+const char g_fcc_entropy_error_str[] = "Entropy error:";
+const char g_fcc_disabled_error_str[] = "Factory disabled error:";
+const char g_fcc_invalid_certificate_error_str[] = "Certificate invalid:";
+const char g_fcc_item_not_exists_error_str[] = "Item does not exist:";
+const char g_fcc_meta_data_not_exists_error_str[] = "Meta data does not exist:";
+const char g_fcc_meta_data_size_error_str[] = "Meta data does not exist:";
+const char g_fcc_wrong_item_size_error_str[] = "Item size is wrong:";
+const char g_fcc_empty_item_error_str[] = "Item empty:";
+const char g_fcc_uri_wrong_format_error_str[] = "URI format incorrect:";
+const char g_fcc_first_to_claim_not_allowed_error_str[] = "first to claim not allowed:";
+const char g_fcc_wrong_utc_offset_value_error_str[] = "UTC offset incorrect:";
+const char g_fcc_wrong_bootstrap_use_value_error_str[] = "Bootstrap mode value incorrect:";
+const char g_fcc_not_permitted_error_str[] = "Operation not permitted:";
+const char g_fcc_wrong_ca_certificate_error_str[] = "Validation of CA certificate failed:";
+const char g_fcc_invalid_cn_certificate_error_str[] = "Certificate CN attribute invalid:";
+const char g_fcc_crypto_public_key_correlation_error_str[] = "Certificate public key validation failed:";
+const char g_fcc_internal_storage_error_str[] = "Internal storage error:";
+const char g_fcc_csr_requests_too_many[] = "Too many CSR requests. Maximum CSR requests supported is " xstr(CSR_MAX_NUMBER_OF_CSRS);
+
+//kcm crypto error strings
+const char g_fcc_kcm_file_error_str[] = "File operation general error:";
+const char g_fcc_kcm_invalid_file_version_str[] = "File version invalid:";
+const char g_fcc_kcm_file_data_corrupted_str[] = "File data corrupted:";
+const char g_fcc_kcm_file_name_corrupted_str[] = "File name corrupted:";
+const char g_fcc_kcm_not_initialized_str[] = "KCM not initialized:";
+const char g_fcc_kcm_close_incomplete_chain_str[] = "Closing incomplete KCM chain:";
+const char g_fcc_kcm_invalid_chain_str[] = "Corrupted certificate chain file:";
+const char g_fcc_kcm_invalid_num_of_cert_in_chain_str[] = "Maximum chain length supported is " xstr(KCM_MAX_NUMBER_OF_CERTIFICATES_IN_CHAIN) ". Chain length of the item is invalid:";
+const char g_fcc_kcm_file_exist_error_str[] = "Data already exists:";
+const char g_fcc_kcm_key_exist_error_str[] = "Desired generated key name already exists:";
+const char g_fcc_kcm_file_name_too_long_error_str[] = "File name too long:";
+const char g_fcc_crypto_kcm_error_str[] = "KCM crypto error:";
+const char g_fcc_crypto_empty_item_error_str[] = "Item data empty:";
+const char g_fcc_crypto_unsupported_hash_mode_error_str[] = "Hash mode unsupported:";
+const char g_fcc_crypto_parsing_der_pivate_key_error_str[] = "Private key parse failed:";
+const char g_fcc_crypto_parsing_der_public_key_error_str[] = "Public key parse failed:";
+const char g_fcc_crypto_verify_private_key_error_str[] = "Private key verification failed:";
+const char g_fcc_crypto_verify_public_key_error_str[] = "Public key verification failed:";
+const char g_fcc_crypto_unsupported_curve_error_str[] = "Curve unsupported:";
+const char g_fcc_crypto_parsing_der_cert_error_str[] = "Certificate parse failed:";
+const char g_fcc_crypto_cert_expired_error_str[] = "Certificate expired:";
+const char g_fcc_crypto_cert_future_error_str[] = "Certificate will be valid in the future:";
+const char g_fcc_crypto_cert_md_alg_error_str[] = "Certificate MD algorithm error:";
+const char g_fcc_crypto_cert_public_key_type_error_str[] = "Certificate public key type error:";
+const char g_fcc_crypto_cert_public_key_error_str[] = "Certificate public key error:";
+const char g_fcc_crypto_cert_not_trusted_error_str[] = "Certificate not trusted:";
+const char g_fcc_crypto_invalid_x509_attr_error_str[] = "X509 attribute invalid:";
+const char g_fcc_crypto_invalid_pk_key_format_error_str[] = "Public key format invalid:";
+const char g_fcc_crypto_invalid_public_key_error_str[] = "Public key invalid:";
+const char g_fcc_crypto_ecp_invalid_key_error_str[] = "EC key invalid:";
+const char g_fcc_crypto_pk_key_invalid_version_error_str[] = "Public key version invalid:";
+const char g_fcc_crypto_pk_password_requerd_error_str[] = "Public key password required:";
+const char g_fcc_crypto_unknown_pk_algorithm_error_str[] = "Public key algorithm unknown:";
+const char g_fcc_crypto_chain_validation_error_str[] = "Chain validation error:";
+const char g_fcc_self_generated_certificate_validation_error_str[] = "Self-generated certificate validation failed:";
+//warning strings
+const char g_fcc_item_not_set_warning_str[] = "Item not set:";
+
+const char g_fcc_bootstrap_mode_false_warning_str[] = "Bootstrap mode not activated:";
+const char g_fcc_self_signed_warning_str[] = "Certificate is self signed:";
+const char g_fcc_item_is_empty_warning_str[] = "Item empty:";
+const char g_fcc_redundant_item_warning_str[] = "Item redundant:";
+const char g_fcc_cert_time_validity_warning_str[] = "Certificate validity cannot be checked:";
+const char g_fcc_cert_validity_less_10_years_warning_str[] = "Certificate validity is less than 10 years:";
+const char g_fcc_ca_identifier_warning_str[] = "CA identifier wasn't set properly:";
+
+fcc_output_info_s g_output_info;
+
+
+/**  The function frees all allocated buffers
+* @param output_warning_info[in]          The pointer to created fcc_warning_info_s structure
+*/
+static void fcc_free_list_of_warnings(fcc_warning_info_s  *output_warning_info)
+{
+    fcc_warning_info_s *current_node = output_warning_info;
+    fcc_warning_info_s *next_node = output_warning_info->next;
+
+    while (current_node != NULL) {
+        if (current_node->warning_info_string != NULL) {
+            fcc_free(current_node->warning_info_string);
+        }
+        fcc_free(current_node);
+        current_node = next_node;
+        if (current_node != NULL) {
+            next_node = current_node->next;
+        }
+    }
+}
+/**  The function combines message string info and failed item, and sets it to passed pointer.
+* @param message_string[in]          The message string - error or warning
+* @param failed_item_name[in]        The name of item.
+* @param failed_item_name_size[in]   The size of item's name.
+* @param out_string[in/out]          The output string where the combined message should be copied.
+*/
+static fcc_status_e fcc_set_output_string_info(const char *message_string, const uint8_t *failed_item_name, size_t failed_item_name_size, char **out_string)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    //Allocate memory for error info
+    *out_string = fcc_malloc(strlen(message_string) + failed_item_name_size + 1); // 1 char for '\0'
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((out_string == NULL), fcc_status = FCC_STATUS_MEMORY_OUT, "Failed to allocate buffer for output info");
+
+    //Copy to  the global structure error string info
+    strcpy((*out_string), message_string);
+
+    //Copy to  the global structure the name of failed item if it exists.
+    if (failed_item_name != NULL) {
+        memcpy((uint8_t*)(*out_string) + strlen(message_string), failed_item_name, failed_item_name_size);
+        //Set '\0' in the end of error string info
+        (*out_string)[strlen(message_string) + failed_item_name_size] = '\0';
+    }
+
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+static size_t fcc_get_size_of_all_warning_strings()
+{
+    fcc_warning_info_s *current_node = g_output_info.head_of_warning_list;
+    size_t size_of_all_warning_strings = 0;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    while (current_node != NULL) {
+        size_of_all_warning_strings += strlen(current_node->warning_info_string);
+        current_node = current_node->next;
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return size_of_all_warning_strings;
+}
+
+static bool copy_all_warning_to_buffer(char *out_warning_string, size_t size_of_out_warning_string)
+{
+    fcc_warning_info_s *current_node = g_output_info.head_of_warning_list;
+    size_t length_of_iterated_strings = 0;
+
+    memset(out_warning_string, 0, size_of_out_warning_string);
+
+    while (current_node != NULL) {
+        //Calculate size of current warning
+        if (length_of_iterated_strings + strlen(current_node->warning_info_string) + 1 > size_of_out_warning_string) {
+            return false;
+        }
+        strcpy(out_warning_string + length_of_iterated_strings, current_node->warning_info_string);
+        //Set '\n' in the end of warning string info
+        (out_warning_string)[length_of_iterated_strings + strlen(current_node->warning_info_string)] = '\n';
+        length_of_iterated_strings += strlen(current_node->warning_info_string) + 1;
+        current_node = current_node->next;
+    }
+    //Increase the size for '\0'
+    if (length_of_iterated_strings >= size_of_out_warning_string) {
+        return false;
+    }
+    (out_warning_string)[length_of_iterated_strings] = '\0';
+
+    return true;
+}
+/**  The function returns error string according to passed fcc_status.
+* @param fcc_status[in]          The fcc_status
+*
+*/
+
+char* fcc_get_fcc_error_string(fcc_status_e fcc_status)
+{
+    SA_PV_LOG_TRACE_FUNC_ENTER("fcc_status is %d", fcc_status);
+    char *fcc_error_string = NULL;
+
+    switch (fcc_status) {
+        case FCC_STATUS_ERROR:
+        case FCC_STATUS_MEMORY_OUT:
+        case FCC_STATUS_INVALID_PARAMETER:
+        case FCC_STATUS_KCM_ERROR:
+        case FCC_STATUS_BUNDLE_ERROR:
+        case FCC_STATUS_BUNDLE_RESPONSE_ERROR:
+        case FCC_STATUS_BUNDLE_UNSUPPORTED_GROUP:
+        case FCC_STATUS_BUNDLE_INVALID_SCHEME:
+        case FCC_STATUS_BUNDLE_INVALID_KEEP_ALIVE_SESSION_STATUS:
+        case FCC_STATUS_BUNDLE_INVALID_GROUP:
+        case FCC_STATUS_KCM_STORAGE_ERROR:
+        case FCC_STATUS_KCM_FILE_EXIST_ERROR:
+        case FCC_STATUS_NOT_INITIALIZED:
+        case FCC_STATUS_OUTPUT_INFO_ERROR:
+        case FCC_STATUS_WARNING_CREATE_ERROR:
+        case FCC_STATUS_INVALID_CERT_ATTRIBUTE:
+        case FCC_STATUS_INTERNAL_ITEM_ALREADY_EXIST:
+            fcc_error_string = (char*)g_fcc_general_status_error_str;
+            break;
+        case FCC_STATUS_CA_ERROR:
+            fcc_error_string = (char*)g_fcc_ca_error_str;
+            break;
+        case FCC_STATUS_ROT_ERROR:
+            fcc_error_string = (char*)g_fcc_rot_error_str;
+            break;
+        case FCC_STATUS_STORE_ERROR:
+            fcc_error_string = (char*)g_fcc_internal_storage_error_str;
+            break;
+        case FCC_STATUS_KCM_CRYPTO_ERROR:
+            fcc_error_string = (char*)g_fcc_crypto_kcm_error_str;
+            break;
+        case FCC_STATUS_INVALID_CERTIFICATE:
+            fcc_error_string = (char*)g_fcc_invalid_certificate_error_str;
+            break;
+        case FCC_STATUS_INVALID_LWM2M_CN_ATTR:
+            fcc_error_string = (char*)g_fcc_invalid_cn_certificate_error_str;
+            break;
+        case FCC_STATUS_ENTROPY_ERROR:
+            fcc_error_string = (char*)g_fcc_entropy_error_str;
+            break;
+        case FCC_STATUS_FACTORY_DISABLED_ERROR:
+            fcc_error_string = (char*)g_fcc_disabled_error_str;
+            break;
+        case FCC_STATUS_ITEM_NOT_EXIST:
+            fcc_error_string = (char*)g_fcc_item_not_exists_error_str;
+            break;
+        case FCC_STATUS_WRONG_ITEM_DATA_SIZE:
+            fcc_error_string = (char*)g_fcc_wrong_item_size_error_str;
+            break;
+        case FCC_STATUS_EMPTY_ITEM:
+            fcc_error_string = (char*)g_fcc_empty_item_error_str;
+            break;
+        case FCC_STATUS_URI_WRONG_FORMAT:
+            fcc_error_string = (char*)g_fcc_uri_wrong_format_error_str;
+            break;
+        case FCC_STATUS_FIRST_TO_CLAIM_NOT_ALLOWED:
+            fcc_error_string = (char*)g_fcc_first_to_claim_not_allowed_error_str;
+            break;
+        case FCC_STATUS_BOOTSTRAP_MODE_ERROR:
+            fcc_error_string = (char*)g_fcc_wrong_bootstrap_use_value_error_str;
+            break;
+        case FCC_STATUS_UTC_OFFSET_WRONG_FORMAT:
+            fcc_error_string = (char*)g_fcc_wrong_utc_offset_value_error_str;
+            break;
+        case FCC_STATUS_INVALID_CA_CERT_SIGNATURE:
+            fcc_error_string = (char*)g_fcc_wrong_ca_certificate_error_str;
+            break;
+        case FCC_STATUS_EXPIRED_CERTIFICATE:
+            fcc_error_string = (char*)g_fcc_crypto_cert_expired_error_str;
+            break;
+        case FCC_STATUS_CERTIFICATE_PUBLIC_KEY_CORRELATION_ERROR:
+            fcc_error_string = (char*)g_fcc_crypto_public_key_correlation_error_str;
+            break;
+        case FCC_STATUS_TOO_MANY_CSR_REQUESTS:
+            fcc_error_string = (char*)g_fcc_csr_requests_too_many;
+            break;
+        case FCC_STATUS_SUCCESS:
+        case FCC_MAX_STATUS:
+            return fcc_error_string;
+
+    }
+    if (fcc_error_string != NULL) {
+        SA_PV_LOG_TRACE_FUNC_EXIT("fcc_error_string is %s", fcc_error_string);
+    }
+    return fcc_error_string;
+}
+
+/**  The function returns error string according to passed kcm_status.
+* @param kcm_status[in]          The kcm_status
+*
+*/
+
+char* fcc_get_kcm_error_string(kcm_status_e kcm_status)
+{
+    SA_PV_LOG_TRACE_FUNC_ENTER("kcm_status is %d", kcm_status);
+
+    char *kcm_error_string = NULL;
+
+    switch (kcm_status) {
+        case KCM_STATUS_ERROR:
+        case KCM_STATUS_INVALID_PARAMETER:
+        case KCM_STATUS_INSUFFICIENT_BUFFER:
+        case KCM_STATUS_OUT_OF_MEMORY:
+        case KCM_STATUS_INVALID_FILE_ACCESS_MODE:
+        case KCM_STATUS_UNKNOWN_STORAGE_ERROR:
+        case KCM_CRYPTO_STATUS_INVALID_MD_TYPE:
+        case KCM_CRYPTO_STATUS_FAILED_TO_WRITE_SIGNATURE:
+        case KCM_CRYPTO_STATUS_VERIFY_SIGNATURE_FAILED:
+        case KCM_CRYPTO_STATUS_FAILED_TO_WRITE_PRIVATE_KEY:
+        case KCM_CRYPTO_STATUS_FAILED_TO_WRITE_PUBLIC_KEY:
+        case KCM_CRYPTO_STATUS_FAILED_TO_WRITE_CSR:
+        case KCM_CRYPTO_STATUS_INVALID_OID:
+        case KCM_CRYPTO_STATUS_INVALID_NAME_FORMAT:
+            kcm_error_string = (char*)g_fcc_general_status_error_str;
+            break;
+        case KCM_STATUS_SELF_GENERATED_CERTIFICATE_VERIFICATION_ERROR:
+            kcm_error_string = (char*)g_fcc_self_generated_certificate_validation_error_str;
+            break;
+        case KCM_STATUS_STORAGE_ERROR:
+            kcm_error_string = (char*)g_fcc_kcm_file_error_str;
+            break;
+        case KCM_STATUS_INVALID_FILE_VERSION:
+            kcm_error_string = (char*)g_fcc_kcm_invalid_file_version_str;
+            break;
+        case KCM_STATUS_FILE_CORRUPTED:
+            kcm_error_string = (char*)g_fcc_kcm_file_data_corrupted_str;
+            break;
+        case KCM_STATUS_NOT_INITIALIZED:
+            kcm_error_string = (char*)g_fcc_kcm_not_initialized_str;
+            break;
+        case KCM_STATUS_CLOSE_INCOMPLETE_CHAIN:
+            kcm_error_string = (char*)g_fcc_kcm_close_incomplete_chain_str;
+            break;
+        case KCM_STATUS_CORRUPTED_CHAIN_FILE:
+            kcm_error_string = (char*)g_fcc_kcm_invalid_chain_str;
+            break;
+        case KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN:
+            kcm_error_string = (char*)g_fcc_kcm_invalid_num_of_cert_in_chain_str;
+            break;
+        case KCM_STATUS_CERTIFICATE_CHAIN_VERIFICATION_FAILED:
+            kcm_error_string = (char*)g_fcc_crypto_chain_validation_error_str;
+            break;
+        case KCM_STATUS_ITEM_NOT_FOUND:
+            kcm_error_string = (char*)g_fcc_item_not_exists_error_str;
+            break;
+        case KCM_STATUS_META_DATA_NOT_FOUND:
+            kcm_error_string = (char*)g_fcc_meta_data_not_exists_error_str;
+            break;
+        case KCM_STATUS_META_DATA_SIZE_ERROR:
+            kcm_error_string = (char*)g_fcc_meta_data_size_error_str;
+            break;
+        case KCM_STATUS_NOT_PERMITTED:
+            kcm_error_string = (char*)g_fcc_not_permitted_error_str;
+            break;
+        case KCM_STATUS_FILE_EXIST:
+            kcm_error_string = (char*)g_fcc_kcm_file_exist_error_str;
+            break;
+        case KCM_STATUS_KEY_EXIST:
+            kcm_error_string = (char*)g_fcc_kcm_key_exist_error_str;
+            break;
+        case KCM_STATUS_FILE_NAME_CORRUPTED:
+            kcm_error_string = (char*)g_fcc_kcm_file_name_corrupted_str;
+            break;
+        case KCM_STATUS_ITEM_IS_EMPTY:
+            kcm_error_string = (char*)g_fcc_crypto_empty_item_error_str;
+            break;
+        case KCM_STATUS_FILE_NAME_TOO_LONG:
+            kcm_error_string = (char*)g_fcc_kcm_file_name_too_long_error_str;
+            break;
+        case KCM_CRYPTO_STATUS_UNSUPPORTED_HASH_MODE:
+            kcm_error_string = (char*)g_fcc_crypto_unsupported_hash_mode_error_str;
+            break;
+        case KCM_CRYPTO_STATUS_PARSING_DER_PRIVATE_KEY:
+            kcm_error_string = (char*)g_fcc_crypto_parsing_der_pivate_key_error_str;
+            break;
+        case  KCM_CRYPTO_STATUS_PARSING_DER_PUBLIC_KEY:
+            kcm_error_string = (char*)g_fcc_crypto_parsing_der_public_key_error_str;
+            break;
+        case  KCM_CRYPTO_STATUS_PRIVATE_KEY_VERIFICATION_FAILED:
+            kcm_error_string = (char*)g_fcc_crypto_verify_private_key_error_str;
+            break;
+        case  KCM_CRYPTO_STATUS_PUBLIC_KEY_VERIFICATION_FAILED:
+            kcm_error_string = (char*)g_fcc_crypto_verify_public_key_error_str;
+            break;
+        case  KCM_CRYPTO_STATUS_UNSUPPORTED_CURVE:
+            kcm_error_string = (char*)g_fcc_crypto_unsupported_curve_error_str;
+            break;
+        case  KCM_CRYPTO_STATUS_PARSING_DER_CERT:
+            kcm_error_string = (char*)g_fcc_crypto_parsing_der_cert_error_str;
+            break;
+        case  KCM_CRYPTO_STATUS_CERT_EXPIRED:
+            kcm_error_string = (char*)g_fcc_crypto_cert_expired_error_str;
+            break;
+        case  KCM_CRYPTO_STATUS_CERT_FUTURE:
+            kcm_error_string = (char*)g_fcc_crypto_cert_future_error_str;
+            break;
+        case  KCM_CRYPTO_STATUS_CERT_MD_ALG:
+            kcm_error_string = (char*)g_fcc_crypto_cert_md_alg_error_str;
+            break;
+        case  KCM_CRYPTO_STATUS_CERT_PUB_KEY_TYPE:
+            kcm_error_string = (char*)g_fcc_crypto_cert_public_key_type_error_str;
+            break;
+        case  KCM_CRYPTO_STATUS_CERT_PUB_KEY:
+            kcm_error_string = (char*)g_fcc_crypto_cert_public_key_error_str;
+            break;
+        case  KCM_CRYPTO_STATUS_CERT_NOT_TRUSTED:
+            kcm_error_string = (char*)g_fcc_crypto_cert_not_trusted_error_str;
+            break;
+        case  KCM_CRYPTO_STATUS_INVALID_X509_ATTR:
+            kcm_error_string = (char*)g_fcc_crypto_invalid_x509_attr_error_str;
+            break;
+        case KCM_CRYPTO_STATUS_PK_KEY_INVALID_FORMAT:
+            kcm_error_string = (char*)g_fcc_crypto_invalid_pk_key_format_error_str;
+            break;
+        case KCM_CRYPTO_STATUS_INVALID_PK_PUBKEY:
+            kcm_error_string = (char*)g_fcc_crypto_invalid_public_key_error_str;
+            break;
+        case KCM_CRYPTO_STATUS_ECP_INVALID_KEY:
+            kcm_error_string = (char*)g_fcc_crypto_ecp_invalid_key_error_str;
+            break;
+        case KCM_CRYPTO_STATUS_PK_KEY_INVALID_VERSION:
+            kcm_error_string = (char*)g_fcc_crypto_pk_key_invalid_version_error_str;
+            break;
+        case KCM_CRYPTO_STATUS_PK_PASSWORD_REQUIRED:
+            kcm_error_string = (char*)g_fcc_crypto_pk_password_requerd_error_str;
+            break;
+        case KCM_CRYPTO_STATUS_PK_UNKNOWN_PK_ALG:
+            kcm_error_string = (char*)g_fcc_crypto_unknown_pk_algorithm_error_str;
+            break;
+        case KCM_STATUS_SUCCESS:
+        case KCM_MAX_STATUS:
+            return kcm_error_string;
+    }
+
+    if (kcm_error_string != NULL) {
+        SA_PV_LOG_TRACE_FUNC_EXIT("kcm_error_string is %s", kcm_error_string);
+    }
+    return kcm_error_string;
+}
+
+fcc_output_info_s* get_output_info(void)
+{
+    return &g_output_info;
+}
+
+void  fcc_init_output_info_handler()
+{
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    g_output_info.error_string_info = NULL;
+    g_output_info.head_of_warning_list = NULL;
+    g_output_info.tail_of_warning_list = NULL;
+    g_output_info.size_of_warning_info_list = 0;
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+}
+
+void  fcc_clean_output_info_handler()
+{
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    fcc_free(g_output_info.error_string_info);
+    g_output_info.error_string_info = NULL;
+
+    if (g_output_info.head_of_warning_list != NULL) {
+        fcc_free_list_of_warnings(g_output_info.head_of_warning_list);
+    }
+    g_output_info.size_of_warning_info_list = 0;
+    g_output_info.tail_of_warning_list = NULL;
+    g_output_info.head_of_warning_list = NULL;
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+}
+
+fcc_status_e fcc_store_warning_info(const uint8_t *failed_item_name, size_t failed_item_name_size, const char *warning_string)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    fcc_warning_info_s *new_node = NULL;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((warning_string == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Warning string is empty");
+    SA_PV_LOG_INFO_FUNC_ENTER("warning_string is %s", warning_string);
+    //Check parameters (failed_item_name can be NULL)
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((failed_item_name != NULL && failed_item_name_size == 0), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Wrong failed item name parameters");
+
+    //Allocate new node
+    new_node = (fcc_warning_info_s*)fcc_malloc(sizeof(fcc_warning_info_s));
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((new_node == NULL), fcc_status = FCC_STATUS_MEMORY_OUT, "Failed to allocate memory for new warning list");
+
+    //Set the new node with warning info (message and item name)
+    fcc_status = fcc_set_output_string_info(warning_string, failed_item_name, failed_item_name_size, &(new_node->warning_info_string));
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_ERROR, exit_with_error, "Failed to set warning string info\n");
+
+    //Update the list
+    if (g_output_info.head_of_warning_list == NULL) {
+        //In case this is the first node
+        g_output_info.head_of_warning_list = g_output_info.tail_of_warning_list = new_node;
+    } else {
+        //In case this is an additional node
+        g_output_info.tail_of_warning_list->next = new_node;
+        g_output_info.tail_of_warning_list = new_node;
+    }
+    g_output_info.tail_of_warning_list->next = NULL;
+    g_output_info.size_of_warning_info_list++;
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+
+exit_with_error:
+    fcc_free(new_node);
+    return fcc_status;
+}
+
+fcc_status_e fcc_bundle_store_error_info(const uint8_t *failed_item_name, size_t failed_item_name_size, kcm_status_e kcm_status)
+{
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    char *error_string_info = NULL;
+
+    SA_PV_LOG_INFO_FUNC_ENTER("kcm_status is %d", kcm_status);
+
+    //Check parameters (failed_item_name can be NULL)
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_INVALID_PARAMETER, "The fcc_bundle_store_error_info should not be called with success status");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((failed_item_name != NULL && failed_item_name_size == 0), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Wrong failed item name parameters");
+
+    //Get kcm error string
+    error_string_info = fcc_get_kcm_error_string(kcm_status);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((error_string_info == NULL), fcc_status = FCC_STATUS_ERROR, "Failed to get kcm error string");
+
+    //Store kcm error string with item name
+    fcc_status = fcc_set_output_string_info(error_string_info, failed_item_name, failed_item_name_size, &(g_output_info.error_string_info));
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = FCC_STATUS_ERROR, "Failed to set error string info ");
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+fcc_status_e fcc_store_error_info(const uint8_t *failed_item_name, size_t failed_item_name_size, fcc_status_e fcc_status)
+{
+    fcc_status_e fcc_result = FCC_STATUS_SUCCESS;
+    char *error_string_info = NULL;
+
+    SA_PV_LOG_INFO_FUNC_ENTER("fcc_status is %d", fcc_status);
+    //Check parameters (failed_item_name can be NULL)
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_status == FCC_STATUS_SUCCESS), FCC_STATUS_INVALID_PARAMETER, "The fcc_store_error_info should not be called with success status");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((failed_item_name != NULL && failed_item_name_size == 0), FCC_STATUS_INVALID_PARAMETER, "Wrong failed item name parameters");
+
+    //Get fcc error string
+    error_string_info = fcc_get_fcc_error_string(fcc_status);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((error_string_info == NULL), FCC_STATUS_ERROR, "Failed to get fcc error string");
+
+    if (g_output_info.error_string_info == NULL) {
+        //Store fcc error string with item name
+        fcc_result = fcc_set_output_string_info(error_string_info, failed_item_name, failed_item_name_size, &(g_output_info.error_string_info));
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((fcc_result != FCC_STATUS_SUCCESS), FCC_STATUS_ERROR, "Failed to set error string info ");
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return fcc_result;
+}
+
+char* fcc_get_output_error_info()
+{
+    char *error_info = NULL;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    if (g_output_info.error_string_info != NULL) {
+        error_info = g_output_info.error_string_info;
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return error_info;
+}
+
+
+char*  fcc_get_output_warning_info()
+{
+    char *warrning_string_collection = NULL;
+    size_t size_of_warning_string_collection = 0;
+    size_t total_size_of_strings_with_delimeters = 0;
+    bool status = false;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    if (g_output_info.head_of_warning_list == NULL || g_output_info.size_of_warning_info_list == 0) {
+        return NULL;
+    } else {
+        //Get size of all warning
+        size_of_warning_string_collection = fcc_get_size_of_all_warning_strings();
+
+        //total_size_of_strings_with_delimeters -size_of_warning_string_collection +add '\n'  - as delimiter between the warnings and '\0' in the end
+        total_size_of_strings_with_delimeters = size_of_warning_string_collection + g_output_info.size_of_warning_info_list + 1;
+
+        //Allocate memory  buffer for all warnings
+        warrning_string_collection = fcc_malloc(total_size_of_strings_with_delimeters);
+        if (warrning_string_collection == NULL) {
+            SA_PV_LOG_INFO("Failed to allocate memory for warning strings");
+            return warrning_string_collection;
+        }
+        status = copy_all_warning_to_buffer(warrning_string_collection, total_size_of_strings_with_delimeters);
+        if (status != true) {
+            fcc_free(warrning_string_collection);
+            return NULL;
+        }
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return warrning_string_collection;
+}
+
+bool fcc_get_warning_status()
+{
+    if (g_output_info.head_of_warning_list != NULL) {
+        return true;
+    } else {
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/ftcd-comm-base/ftcd-comm-base/ftcd_comm_base.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,197 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FTCD_COMM_BASE_H__
+#define __FTCD_COMM_BASE_H__
+
+#include <stdint.h>
+
+/**
+* @file ftcd_comm_base.h
+*
+*  Token      [64bit]   : The message identifier
+*  Status     [32 bit]  : Status of message parameters (exists in response messages only)
+*  Length     [32bit]   : The message length in bytes
+*  Message    [Length]  : A message to be processed
+*  Signature  [32B]     : The hash (SHA256) value of the message
+*/
+
+
+/** Unique message identifiers
+*/
+#define FTCD_MSG_HEADER_TOKEN_FCC { 0x6d, 0x62, 0x65, 0x64, 0x70, 0x72, 0x6f, 0x76 }
+#define FTCD_MSG_HEADER_TOKEN_SDA { 0x6d, 0x62, 0x65, 0x64, 0x64, 0x62, 0x61, 0x70 }
+#define FTCD_MSG_HEADER_TOKEN_SIZE_BYTES 8
+
+
+typedef enum {
+    FTCD_COMM_STATUS_SUCCESS,
+    FTCD_COMM_STATUS_ERROR, //generic error
+    FTCD_COMM_INVALID_PARAMETER,
+    FTCD_COMM_MEMORY_OUT,
+    FTCD_COMM_FAILED_TO_READ_MESSAGE_SIZE,
+    FTCD_COMM_FAILED_TO_READ_MESSAGE_BYTES,
+    FTCD_COMM_FAILED_TO_READ_MESSAGE_SIGNATURE,
+    FTCD_COMM_FAILED_TO_CALCULATE_MESSAGE_SIGNATURE,
+    FTCD_COMM_INCONSISTENT_MESSAGE_SIGNATURE,
+    FTCD_COMM_FAILED_TO_PROCESS_DATA,
+    FTCD_COMM_FAILED_TO_PROCESS_MESSAGE,
+    FTCD_COMM_FAILED_TO_SEND_VALID_RESPONSE,
+
+    FTCD_COMM_NETWORK_TIMEOUT,          //socket timeout error
+    FTCD_COMM_NETWORK_CONNECTION_ERROR, //socket error
+    FTCD_COMM_NETWORK_CONNECTION_CLOSED, // Socket connection was closed by the client
+    FTCD_COMM_INTERNAL_ERROR,
+
+    FTCD_COMM_STATUS_MAX_ERROR = 0xFFFFFFFF
+} ftcd_comm_status_e;
+
+typedef enum {
+    FTCD_COMM_NET_ENDIANNESS_LITTLE,
+    FTCD_COMM_NET_ENDIANNESS_BIG,
+} ftcd_comm_network_endianness_e;
+
+/**
+* \brief ::FtcdCommBase implements the logic of processing incoming requests from the remote Factory Tool Demo.
+*/
+class FtcdCommBase {
+
+public:
+
+    FtcdCommBase(ftcd_comm_network_endianness_e network_endianness,const uint8_t *header_token = NULL, bool use_signature = false);
+
+    /** Not certain that we need to do anything here, but just in case we need
+     * to do some clean-up at some point.
+     */
+    virtual ~FtcdCommBase() = 0;
+
+    /**
+    * Initializes Network interface and opens socket
+    * Prints IP address
+    */
+    virtual bool init(void);
+
+    /**
+    * Closes the opened socket
+    */
+    virtual void finish(void);
+
+    /** Wait and read complete message from the communication line.
+    * The method waits in blocking mode for new message,
+    * allocate and read the message,
+    * and sets message_out and message_size_out
+    *
+    * @param message_out The message allocated and read from the communication line
+    * @param message_size_out The message size in bytes
+    *
+    * @returns
+    *     FTCD_COMM_STATUS_SUCCESS on success, otherwise appropriate error from  ftcd_comm_status_e
+    */
+    virtual ftcd_comm_status_e wait_for_message(uint8_t **message_out, uint32_t *message_size_out);
+
+    /** Writes a response message to the communication line.
+    * The method build response message with header and signature (if requested)
+    * and writes it to the line
+    *
+    * @param response_message The message to send through the communication line medium
+    * @param response_message_size The message size in bytes
+    *
+    * @returns
+    *     FTCD_COMM_STATUS_SUCCESS on success, otherwise appropriate error from  ftcd_comm_status_e
+    */
+    ftcd_comm_status_e send_response(const uint8_t *response_message, uint32_t response_message_size);
+
+    /** Writes a response message with status to the communication line.
+    * The method build response message with status, header and signature (if requested)
+    * and writes it to the line
+    *
+    * @param response_message The message to send through the communication line medium
+    * @param response_message_size The message size in bytes
+    *
+    * @returns
+    *     FTCD_COMM_STATUS_SUCCESS on success, otherwise appropriate error from  ftcd_comm_status_e
+    */
+    ftcd_comm_status_e send_response(const uint8_t *response_message, uint32_t response_message_size, ftcd_comm_status_e status_code);
+
+    /** Writes an allocated response message to the communication line medium.
+    *
+    * @param response_message The message to send through the communication line medium
+    * @param response_message_size The message size in bytes
+    *
+    * @returns
+    *     true upon success, false otherwise
+    */
+    virtual bool send(const uint8_t *response_message, uint32_t response_message_size) = 0;
+
+    /** Detects the message token from the communication line medium.
+    *
+    * @returns
+    *     zero, if token detected and different value otherwise
+    */
+    virtual ftcd_comm_status_e is_token_detected(void) = 0;
+
+    /** Reads the message size in bytes from the communication line medium.
+    * This is the amount of bytes needed to allocate for the upcoming message bytes.
+    *
+    * @returns
+    *     The message size in bytes in case of success, zero bytes otherwise.
+    */
+    virtual uint32_t read_message_size(void) = 0;
+
+    /** Reads the message size in bytes from the communication line medium.
+    * This is the amount of bytes needed to allocate for the upcoming message bytes.
+    *
+    * @param message_out The buffer to read into and return to the caller.
+    * @param message_size The message size in bytes.
+    *
+    * @returns
+    *     true upon success, false otherwise
+    */
+    virtual bool read_message(uint8_t *message_out, size_t message_size) = 0;
+
+    /** Reads the message size in bytes from the communication line medium.
+    * This is the amount of bytes needed to allocate for the upcoming message bytes.
+    *
+    * @param sig The buffer to read into and return to the caller.
+    * @param sig_size The sig buffer size in bytes.
+    *
+    * @returns
+    *     The message size in bytes in case of success, zero bytes otherwise.
+    */
+    virtual bool read_message_signature(uint8_t *sig, size_t sig_size) = 0;
+
+protected:
+
+    /* Member point to the token array */
+    uint8_t *_header_token;
+
+private:
+
+    /* Internal method that build response message with status, header and signature (if requested)
+    * and writes it to the line */
+    ftcd_comm_status_e _send_response(const uint8_t *response_message, uint32_t response_message_size, bool send_status_code, ftcd_comm_status_e status_code);
+
+    /** Holds the requested network bytes order */
+    ftcd_comm_network_endianness_e _network_endianness;
+
+    /** Holds the requested message format (with token or without) */
+    bool _use_token;
+
+    /** Holds the requested message format (with signature or without) */
+    bool _use_signature;
+};
+
+#endif  // __FTCD_COMM_BASE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/ftcd-comm-base/source/ftcd_comm_base.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,254 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <string.h>
+#include "pv_endian.h"
+#include "pv_log.h"
+#include "ftcd_comm_base.h"
+#include "cs_hash.h"
+#include "fcc_malloc.h"
+
+#define TRACE_GROUP "fcbs"
+
+FtcdCommBase::FtcdCommBase(ftcd_comm_network_endianness_e network_endianness, const uint8_t *header_token, bool use_signature)
+{
+    _network_endianness = network_endianness;
+    _header_token = NULL;
+    _use_token = (header_token != NULL);
+    if (_use_token) {
+        _header_token = (uint8_t*)fcc_malloc(FTCD_MSG_HEADER_TOKEN_SIZE_BYTES);
+        if (_header_token == NULL) {
+            mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed to allocate token buffer");
+        } else {
+            memcpy(_header_token, header_token, FTCD_MSG_HEADER_TOKEN_SIZE_BYTES);
+        }
+    }
+
+    _use_signature = use_signature;
+}
+
+FtcdCommBase::~FtcdCommBase()
+{
+    if (_header_token) {
+        fcc_free(_header_token);
+    }
+}
+
+
+bool FtcdCommBase::init()
+{
+    return true;
+}
+
+void FtcdCommBase::finish()
+{
+}
+
+ftcd_comm_status_e FtcdCommBase::wait_for_message(uint8_t **message_out, uint32_t *message_size_out)
+{
+    bool success = false;
+    ftcd_comm_status_e status_code = FTCD_COMM_STATUS_SUCCESS;
+    uint8_t *message = NULL;
+    uint32_t message_size = 0;
+
+    if (message_out == NULL || message_size_out == NULL) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid parameter");
+        return FTCD_COMM_INVALID_PARAMETER;
+    }
+
+    *message_out = NULL;
+    *message_size_out = 0;
+
+    if (_use_token == true) {
+        //detect token
+        status_code = is_token_detected();
+        if (status_code != FTCD_COMM_STATUS_SUCCESS) {
+            if (status_code != FTCD_COMM_NETWORK_CONNECTION_CLOSED) {
+                mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Network error (%d)", status_code);
+            }
+            return status_code;
+        } 
+    }
+
+    // Read message size
+    message_size = read_message_size();
+    if (_network_endianness == FTCD_COMM_NET_ENDIANNESS_LITTLE) {
+        message_size = pv_le32_to_h(message_size);
+    } else { // big endian
+        message_size = pv_be32_to_h(message_size);
+    }
+    if (message_size == 0) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Unable to read message size (got ZERO)");
+        status_code = FTCD_COMM_FAILED_TO_READ_MESSAGE_SIZE;
+        return status_code;
+    }
+
+    //read message
+    message = (uint8_t *)fcc_malloc(message_size);
+    if (message == NULL) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed to allocate message buffer");
+        status_code = FTCD_COMM_MEMORY_OUT;
+        return status_code;
+    }
+    success = read_message(message, message_size);
+    if (!success) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed getting message bytes");
+        status_code = FTCD_COMM_FAILED_TO_READ_MESSAGE_BYTES;
+        fcc_free(message);
+        return status_code;
+    }
+
+    if (_use_signature == true) {
+        //read message signature
+
+        uint8_t sig_from_message[CS_SHA256_SIZE];
+        success = read_message_signature(sig_from_message, sizeof(sig_from_message));
+        if (!success) {
+            mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed getting signature bytes");
+            status_code = FTCD_COMM_FAILED_TO_READ_MESSAGE_SIGNATURE;
+            fcc_free(message);
+            return status_code;
+        }
+
+        //calculate message signature
+        uint8_t self_calculated_sig[CS_SHA256_SIZE];
+        kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+        kcm_status = cs_hash(CS_SHA256, message, message_size, self_calculated_sig, sizeof(self_calculated_sig));
+        if (kcm_status != KCM_STATUS_SUCCESS) {
+            mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed calculating message signature");
+            status_code = FTCD_COMM_FAILED_TO_CALCULATE_MESSAGE_SIGNATURE;
+            fcc_free(message);
+            return status_code;
+        }
+
+        //compare signatures
+        if (memcmp(self_calculated_sig, sig_from_message, CS_SHA256_SIZE) != 0) {
+            mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Inconsistent message signature");
+            status_code = FTCD_COMM_INCONSISTENT_MESSAGE_SIGNATURE;
+            fcc_free(message);
+            return status_code;
+        }
+    }
+
+    *message_out = message;
+    *message_size_out = message_size;
+    return status_code;
+}
+
+ftcd_comm_status_e FtcdCommBase::send_response(const uint8_t *response_message, uint32_t response_message_size)
+{
+    return _send_response(response_message, response_message_size, false, FTCD_COMM_STATUS_SUCCESS);
+}
+
+ftcd_comm_status_e FtcdCommBase::send_response(const uint8_t *response_message, uint32_t response_message_size, ftcd_comm_status_e status_code)
+{
+    return _send_response(response_message, response_message_size, true, status_code);
+}
+
+ftcd_comm_status_e FtcdCommBase::_send_response(const uint8_t *response_message, uint32_t response_message_size, bool send_status_code, ftcd_comm_status_e status_code)
+{
+    uint32_t response_size = 0;
+    if (_use_token == true) {
+        response_size += (uint32_t)sizeof(uint64_t); // TOKEN
+    }
+    if (send_status_code == true) {
+        response_size += (uint32_t)sizeof(uint32_t); // STATUS
+    }
+    if (status_code == FTCD_COMM_STATUS_SUCCESS) {
+        response_size += (uint32_t)sizeof(uint32_t); // MESSAGE SIZE
+        response_size += response_message_size; // MESSAGE DATA
+        if (_use_signature == true) {
+            response_size += CS_SHA256_SIZE; // SIGNATURE
+        }
+    }
+
+    uint8_t *response = (uint8_t *)fcc_malloc(response_size);
+    if (response == NULL) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed to allocate response message buffer");
+        status_code = FTCD_COMM_MEMORY_OUT;
+        return status_code;
+    }
+
+    uint32_t offset = 0;
+
+    if (_use_token == true) {
+        // TOKEN
+        memcpy(response, _header_token, FTCD_MSG_HEADER_TOKEN_SIZE_BYTES);
+        offset = FTCD_MSG_HEADER_TOKEN_SIZE_BYTES;
+    }
+
+    if (send_status_code == true) {
+        //STATUS
+        uint32_t aligned_status_code = static_cast<uint32_t>(status_code);
+        if (_network_endianness == FTCD_COMM_NET_ENDIANNESS_LITTLE) {
+            aligned_status_code = pv_h_to_le32(aligned_status_code);
+        } else { // big endian
+            aligned_status_code = pv_h_to_be32(aligned_status_code);
+        }
+        memcpy(response + offset, &aligned_status_code, sizeof(uint32_t));
+        offset += (uint32_t)sizeof(status_code);
+    }
+
+    if (status_code == FTCD_COMM_STATUS_SUCCESS) {
+
+        if (response_message != NULL && response_message_size > 0) {
+            // MESSAGE SIZE
+            uint32_t aligned_msg_size = response_message_size;
+            if (_network_endianness == FTCD_COMM_NET_ENDIANNESS_LITTLE) {
+                aligned_msg_size = pv_h_to_le32(aligned_msg_size);
+            } else { // big endian
+                aligned_msg_size = pv_h_to_be32(aligned_msg_size);
+            }
+            memcpy(response + offset, &aligned_msg_size, sizeof(uint32_t));
+            offset += (uint32_t)sizeof(uint32_t);
+
+            // MESSAGE DATA
+            memcpy(response + offset, response_message, response_message_size);
+            offset += response_message_size;
+
+        } else {
+            mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid response message");
+        }
+
+        if (_use_signature == true) {
+            kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+            uint8_t sig[CS_SHA256_SIZE];
+
+            kcm_status = cs_hash(CS_SHA256, response_message, response_message_size, sig, CS_SHA256_SIZE);
+            if (kcm_status != KCM_STATUS_SUCCESS) {
+                mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed calculating response message signature");
+                fcc_free(response);
+                return FTCD_COMM_INTERNAL_ERROR;
+            }
+
+            // SIGNATURE
+            memcpy(response + offset, sig, CS_SHA256_SIZE);
+        }
+    }
+
+    // Send the response...
+    bool success = send(response, response_size);
+
+    fcc_free(response);
+
+    if (!success) {
+        return FTCD_COMM_FAILED_TO_SEND_VALID_RESPONSE;
+    }
+    return FTCD_COMM_STATUS_SUCCESS;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/ftcd-comm-serial/ftcd-comm-serial/ftcd_comm_serial.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,109 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FTCD_COMM_SERIAL_H__
+#define __FTCD_COMM_SERIAL_H__
+
+#include "ftcd_comm_base.h"
+#include <inttypes.h>
+#include "mbed.h"
+
+class FtcdCommSerial : public FtcdCommBase {
+
+public:
+    /** Initialize serial object that communicate via stdin and stdout */
+    FtcdCommSerial(ftcd_comm_network_endianness_e network_endianness, const uint8_t *header_token, bool use_signature);
+
+    /** Deprecated constructor for backward compatibility.
+        Note, the TX, RX and baud params are ignored */
+    FtcdCommSerial(PinName TX, PinName RX, uint32_t baud, ftcd_comm_network_endianness_e network_endianness, const uint8_t *header_token, bool use_signature);
+
+    /** Not certain that we need to do anything here, but just in case we need
+     * to do some clean-up at some point.
+     */
+    virtual ~FtcdCommSerial();
+
+    /** Detects the message token from the communication line medium.
+    *
+    * @returns
+    *     zero, if token detected and different value otherwise
+    */
+    virtual ftcd_comm_status_e is_token_detected(void);
+
+    /** Reads the message size in bytes from the communication line medium.
+    * This is the amount of bytes needed to allocate for the upcoming message bytes.
+    *
+    * @returns
+    *     The message size in bytes in case of success, zero bytes otherwise.
+    */
+    virtual uint32_t read_message_size(void);
+
+    /** Reads the message size in bytes from the communication line medium.
+    * This is the amount of bytes needed to allocate for the upcoming message bytes.
+    *
+    * @param message_out The buffer to read into and return to the caller.
+    * @param message_size The message size in bytes.
+    *
+    * @returns
+    *     true upon success, false otherwise
+    */
+    virtual bool read_message(uint8_t *message_out, size_t message_size);
+
+    /** Reads the message size in bytes from the communication line medium.
+    * This is the amount of bytes needed to allocate for the upcoming message bytes.
+    *
+    * @param sig The buffer to read into and return to the caller.
+    * @param sig_size The sig buffer size in bytes.
+    *
+    * @returns
+    *     The message size in bytes in case of success, zero bytes otherwise.
+    */
+    virtual bool read_message_signature(uint8_t *sig, size_t sig_size);
+
+    /** Writes the given data to the communication line medium.
+    *
+    * @param data The bytes to send through the communication line medium
+    * @param data_size The data size in bytes
+    *
+    * @returns
+    *     true upon success, false otherwise
+    */
+    virtual bool send(const uint8_t *data, uint32_t data_size);
+
+private:
+
+    /** Reads a buffer from the serial line.
+    *
+    * @param buff_out A pointer to the buffer to read into, should be allocated by the caller
+    * @param buff_max_size The max chars to read
+    *
+    * @returns
+    *     the number of chars read, zero in case of an error
+    */
+    size_t _serial_read(char *buff_out, size_t buff_max_size);
+
+    /** Writes a buffer to the serial line.
+    *
+    * @param buff A buffer to write.
+    * @param buff_size The number of chars in buffer
+    *
+    * @returns
+    *     the number of chars that was written, zero in case of an error
+    */
+    size_t _serial_write(const char *buff, size_t buff_size);
+};
+
+#endif  // __FTCD_COMM_SERIAL_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/ftcd-comm-serial/source/ftcd_comm_serial.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,161 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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 macro is needed on armcc to get the the PRI*32 macros
+// from inttypes.h in a C++ code.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <stdio.h>
+#include "pv_log.h"
+#include "ftcd_comm_serial.h"
+
+#define TRACE_GROUP "fcsr"
+
+FtcdCommSerial::FtcdCommSerial(PinName TX, PinName RX, uint32_t baud, ftcd_comm_network_endianness_e network_endianness, const uint8_t *header_token, bool use_signature)
+    : FtcdCommBase(network_endianness, header_token, use_signature)
+{
+}
+
+FtcdCommSerial::FtcdCommSerial(ftcd_comm_network_endianness_e network_endianness, const uint8_t *header_token, bool use_signature)
+    : FtcdCommBase(network_endianness, header_token, use_signature)
+{
+}
+
+FtcdCommSerial::~FtcdCommSerial()
+{
+}
+
+size_t FtcdCommSerial::_serial_read(char *buffOut, size_t buffSize)
+{
+    ssize_t count = 0;
+    size_t left_to_read = buffSize;
+    char* buffer = buffOut;
+    while (left_to_read > 0) {
+        count = read(STDIN_FILENO, buffer, left_to_read);
+        if (count < 0) {
+            break;
+        }
+        buffer += count;
+        left_to_read -= count;
+    }
+
+    return buffSize - left_to_read;
+}
+
+size_t FtcdCommSerial::_serial_write(const char *buff, size_t buffSize)
+{
+    ssize_t count = 0;
+    size_t left_to_write = buffSize;
+    char* buffer = (char*)buff;
+    while (left_to_write > 0) {
+        count = write(STDOUT_FILENO, buffer, left_to_write);
+        if (count < 0) {
+            break;
+        }
+        buffer += count;
+        left_to_write -= count;
+    }
+
+    return buffSize - left_to_write;
+}
+
+ftcd_comm_status_e FtcdCommSerial::is_token_detected()
+{
+    char c;
+    size_t idx = 0;
+
+    //read char by char to detect token
+    while (idx < FTCD_MSG_HEADER_TOKEN_SIZE_BYTES) {
+        _serial_read(&c, 1);
+        if (c == _header_token[idx]) {
+            idx++;
+        } else {
+            idx = 0;
+        }
+    }
+    return FTCD_COMM_STATUS_SUCCESS;
+}
+
+uint32_t FtcdCommSerial::read_message_size()
+{
+    uint32_t message_size = 0;
+
+    size_t read_chars = _serial_read(reinterpret_cast<char*>(&message_size), sizeof(message_size));
+    if (read_chars != sizeof(message_size)) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message size (read %d bytes out of %d)", read_chars, sizeof(message_size));
+        return 0;
+    }
+
+    return message_size;
+}
+
+bool FtcdCommSerial::read_message(uint8_t *message_out, size_t message_size)
+{
+    if (message_out == NULL) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid message buffer");
+        return false;
+    }
+
+    // Read CBOR message bytes
+    // We assume that LENGTH is NOT bigger than INT_MAX
+    size_t read_chars = _serial_read(reinterpret_cast<char*>(message_out), message_size);
+    if (read_chars != message_size) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message bytes (read %d bytes out of %d)", read_chars, message_size);
+        return false;
+    }
+
+    return true;
+}
+
+bool FtcdCommSerial::read_message_signature(uint8_t *sig, size_t sig_size)
+{
+    if (sig == NULL) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid sig buffer");
+        return false;
+    }
+
+    // Read signature from medium
+    size_t read_chars = _serial_read(reinterpret_cast<char*>(sig), sig_size);
+    if (read_chars != sig_size) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message signature bytes (read %d bytes out of %d)", read_chars, sig_size);
+        return false;
+    }
+
+    return true;
+}
+
+bool FtcdCommSerial::send(const uint8_t *data, uint32_t data_size)
+{
+    if (data == NULL) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid response_message");
+        return false;
+    }
+    if (data_size == 0) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Got an empty message");
+        return false;
+    }
+
+    // Send data on the serial medium
+    size_t write_chars = _serial_write(reinterpret_cast<const char*>(data), data_size);
+    if (write_chars != data_size) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed writing message bytes (wrote %" PRIu32 " bytes out of %" PRIu32 ")", (uint32_t)write_chars, data_size);
+        return false;
+    }
+
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/ftcd-comm-socket/ftcd-comm-socket/ftcd_comm_socket.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,184 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FTCD_COMM_SOCKET_H__
+#define __FTCD_COMM_SOCKET_H__
+
+#include "ftcd_comm_base.h"
+#include "pal.h"
+#include <inttypes.h>
+
+#define INFINITE_SOCKET_TIMEOUT -1
+
+/**
+* List of supported networks domains. Current supported domain is ipv4 only.
+*/
+typedef enum {
+    FTCD_AF_UNSPEC = 0,//!< Unspecified IP protocol.
+    FTCD_IPV4 = 2,     //!< Internet IP Protocol.
+} ftcd_socket_domain_e;
+
+/**
+* Type for sockets.
+*/
+typedef void* palSocket_t;
+/**
+* Structure for Ethernet interface info.
+*/
+struct palNetInterfaceInfo;
+/**
+* Class for Ethernet interface.
+*/
+class EthernetInterface;
+
+/** FtcdCommSocket implements the logic of listening for TCP connections and
+*  process incoming messages from the Factory Tool.
+*/
+class FtcdCommSocket : public FtcdCommBase {
+
+public:
+
+    /**
+    * The Socket Constructor
+    * Initializes private variables and sets network interface handler, IP and port number.
+    * If port_num is 0, then random port will be generated.
+    */
+    FtcdCommSocket(const void *interfaceHandler, ftcd_socket_domain_e domain, const uint16_t port_num, ftcd_comm_network_endianness_e network_endianness = FTCD_COMM_NET_ENDIANNESS_BIG, int32_t timeout = INFINITE_SOCKET_TIMEOUT);
+
+    /**
+    * The Socket Constructor
+    * Initializes private variables and sets network interface handler, IP and port number.
+    * If port_num is 0, then random port will be generated.
+    */
+    FtcdCommSocket(const void *interfaceHandler, ftcd_socket_domain_e domain, const uint16_t port_num, ftcd_comm_network_endianness_e network_endianness, const uint8_t *header_token, bool use_signature, int32_t timeout = INFINITE_SOCKET_TIMEOUT);
+
+    /**
+    * The Socket Destructor
+    * Closes opened resources and frees allocated memory.
+    */
+    virtual ~FtcdCommSocket();
+
+    /**
+    * Initializes Network interface and prints its address.
+    */
+    virtual bool init(void);
+
+    /**
+    * Closes opened sockets
+    */
+    virtual void finish(void);
+
+    /** Wait and read complete message from the communication line.
+    * The method waits in blocking mode for new message,
+    * allocate and read the message,
+    * and sets message_out and message_size_out
+    *
+    * @param message_out The message allocated and read from the communication line
+    * @param message_size_out The message size in bytes
+    *
+    * @returns
+    *     FTCD_COMM_STATUS_SUCCESS - On success. In this case the client socket, and accepted connection remain open waiting for the next message with next call.
+    *     FTCD_COMM_NETWORK_TIMEOUT - This means a timeout has occurred, client socket close and next call will create a new socket and accept a new connection.
+    *     Other ftcd_comm_status_e error code - some other error has occurred, client socket will be closed and next call will create and open a new socket, and wait for a new connection.
+    */
+    virtual ftcd_comm_status_e wait_for_message(uint8_t **message_out, uint32_t *message_size_out);
+
+    /** Detects the message token from the communication line medium.
+    *
+    * @returns
+    *     true, if token detected and false otherwise
+    */
+    virtual ftcd_comm_status_e is_token_detected(void);
+
+    /** Reads the message size in bytes from the communication line medium.
+    * This is the amount of bytes needed to allocate for the upcoming message bytes.
+    *
+    * @returns
+    *     The message size in bytes in case of success, zero bytes otherwise.
+    */
+    virtual uint32_t read_message_size(void);
+
+    /** Reads the message size in bytes from the communication line medium.
+    * This is the amount of bytes needed to allocate for the upcoming message bytes.
+    *
+    * @param message_out The buffer to read into and return to the caller.
+    * @param message_size The message size in bytes.
+    *
+    * @returns
+    *     true upon success, false otherwise
+    */
+    virtual bool read_message(uint8_t *message_out, size_t message_size);
+
+    /** Reads the message size in bytes from the communication line medium.
+    * This is the amount of bytes needed to allocate for the upcoming message bytes.
+    *
+    * @param sig The buffer to read into and return to the caller.
+    * @param sig_size The sig buffer size in bytes.
+    *
+    * @returns
+    *     The message size in bytes in case of success, zero bytes otherwise.
+    */
+    virtual bool read_message_signature(uint8_t *sig, size_t sig_size);
+
+    /** Writes the given data to the communication line medium.
+    *
+    * @param data The bytes to send through the communication line medium
+    * @param data_size The data size in bytes
+    *
+    * @returns
+    *     true upon success, false otherwise
+    */
+    virtual bool send(const uint8_t *data, uint32_t data_size);
+
+private:
+    enum connection_state_e {
+        SOCKET_WAIT_FOR_CONNECTION,
+        SOCKET_CONNECTION_ACCEPTED
+    };
+
+    connection_state_e _connection_state;
+    const void *_interface_handler;
+    palSocket_t _server_socket;
+    palSocket_t _client_socket;
+    palNetInterfaceInfo *_net_interface_info;
+    uint16_t _port;
+    ftcd_socket_domain_e _current_domain_type;
+    ftcd_socket_domain_e _required_domain_type;
+    uint32_t _interface_index;
+    int32_t _rcv_timeout;
+
+    /** Starts listening for incoming TCP socket connection
+    *   A single connection allowed at a time
+    *
+    *   @returns
+    *       true, if listen to the socket succeeded.
+    */
+    bool _listen(void);
+
+    /**Reads a requested amount of bytes from a TCP socket
+    *
+    * @param data_out Pre-allocated buffer to be filled
+    * @param data_out_size Buffer length in bytes
+    *
+    * @returns
+    *    0, if the number of bytes read from the socket were exactly bufferOutSize, error status otherwise.
+    */
+    ftcd_comm_status_e _read_from_socket(void *data_out, int data_out_size);
+
+};
+
+
+#endif //__FTCD_COMM_SOCKET_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/ftcd-comm-socket/source/ftcd_comm_socket.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,456 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// 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 macro is needed on armcc to get the the PRI*32 macros
+// from inttypes.h in a C++ code.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <stdlib.h>
+#include "pal.h"
+#include "pv_log.h"
+#include "ftcd_comm_socket.h"
+#include "fcc_malloc.h"
+
+#define NUM_OF_PENDING_CONNECTIONS 1
+#define NUM_OF_TRIES_TO_GET_INTERFACE_INFO 5
+#define TRACE_GROUP "fcsk"
+#define RANDOM_PORT_MIN 1024
+#define RANDOM_PORT_MAX 65535
+
+FtcdCommSocket::FtcdCommSocket(const void *interfaceHandler, ftcd_socket_domain_e domain, const uint16_t port_num, ftcd_comm_network_endianness_e network_endianness, int32_t timeout)
+    : FtcdCommBase(network_endianness, NULL, false)
+{
+    _interface_handler = interfaceHandler;
+    _required_domain_type = domain;
+    _port = port_num;
+    _rcv_timeout = timeout;
+    _current_domain_type = FTCD_AF_UNSPEC;
+    _interface_index = 0;
+    _net_interface_info = NULL;
+    _server_socket = NULL;
+    _client_socket = NULL;
+    _connection_state = SOCKET_WAIT_FOR_CONNECTION;
+}
+
+FtcdCommSocket::FtcdCommSocket(const void *interfaceHandler, ftcd_socket_domain_e domain, const uint16_t port_num, ftcd_comm_network_endianness_e network_endianness, const uint8_t *header_token, bool use_signature, int32_t timeout)
+    : FtcdCommBase(network_endianness, header_token, use_signature)
+
+{
+    _interface_handler = interfaceHandler;
+    _required_domain_type = domain;
+    _port = port_num;
+    _rcv_timeout = timeout;
+    _current_domain_type = FTCD_AF_UNSPEC;
+    _interface_index = 0;
+    _net_interface_info = NULL;
+    _server_socket = NULL;
+    _client_socket = NULL;
+    _connection_state = SOCKET_WAIT_FOR_CONNECTION;
+}
+
+FtcdCommSocket::~FtcdCommSocket()
+{
+
+    if (_net_interface_info != NULL) {
+        fcc_free(_net_interface_info);
+    }
+    if (_server_socket != NULL) {
+        pal_close(&_server_socket);
+    }
+    if (_client_socket != NULL) {
+        pal_close(&_client_socket);
+    }
+}
+
+
+bool FtcdCommSocket::init()
+{
+    int retries = NUM_OF_TRIES_TO_GET_INTERFACE_INFO;
+    palIpV4Addr_t ip_v4_addr;
+    char ip_and_port_string[32] = { 0 };
+    uint32_t index = 0;
+
+    //Call to pal init
+    palStatus_t result = pal_init();
+    if (result != PAL_SUCCESS) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Error initializing pal");
+        return false;
+    }
+
+    // If port is 0, generate random port
+    // Pal currently does not support binding with port 0.
+    if (_port == 0) {
+        srand((unsigned int)pal_osKernelSysTick());
+        // Generate random port int the range [RANDOM_PORT_MIN, RANDOM_PORT_MAX - 1] including.
+        _port = (uint16_t)(rand() % (RANDOM_PORT_MAX - RANDOM_PORT_MIN) + RANDOM_PORT_MIN);
+    }
+
+    //Register connected interface handler
+    result = pal_registerNetworkInterface((void*)_interface_handler, &_interface_index);
+    if (result != 0) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n pal_RegisterNetworkInterface Failed");
+        return false;
+    }
+
+    //Allocate memory for interface info
+    if (_net_interface_info == NULL) {
+        _net_interface_info = (palNetInterfaceInfo_t*)fcc_malloc(sizeof(palNetInterfaceInfo_t));
+        if (_net_interface_info == NULL) {
+            mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Failed to allocate memory for network interface");
+            return false;
+        }
+    }
+
+    //Try to get interface info
+    while (retries--) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Trying receive interface ...");
+        result = pal_getNetInterfaceInfo(_interface_index, _net_interface_info);
+        if (result != 0) {
+            pal_osDelay(200);
+        } else {//In case we have interface info we print it
+            if (_required_domain_type != FTCD_IPV4) {
+                mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Illegal domain type");
+                break;
+            }
+            //Update domain type
+            _current_domain_type = _required_domain_type;
+
+            result = pal_getSockAddrIPV4Addr(&(_net_interface_info->address), ip_v4_addr);
+            if (result != PAL_SUCCESS) {
+                mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n palGetSockAddrIPV4Addr failed");
+                break;
+            }
+            memset(ip_and_port_string, 0, sizeof(ip_and_port_string));
+            index = 0;
+            for (uint32_t i = 0; i < sizeof(palIpV4Addr_t); i++) {
+                if (i < sizeof(palIpV4Addr_t) - 1) {
+                    index += sprintf(&ip_and_port_string[index], "%d.", ip_v4_addr[i]);
+                } else {
+                    index += sprintf(&ip_and_port_string[index], "%d:", ip_v4_addr[i]);
+                    index += sprintf(&ip_and_port_string[index], "%d\n", _port);
+                }
+            }
+
+            mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Factory Client IP Address and Port :  %s", ip_and_port_string);
+            //open and listen to socket
+            if (_listen()) {
+                return true;
+            } else {
+                mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed to listen to socket");
+            }
+
+        }
+
+    }
+
+    mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n FCC did not succeed receive network interface !!!!!!");
+    //If we couldn't get interface info free allocated memory
+    fcc_free(_net_interface_info);
+    _net_interface_info = NULL;
+    return false;
+
+}
+
+void FtcdCommSocket::finish(void)
+{
+    if (_server_socket != NULL) {
+        pal_close(&_server_socket);
+        _server_socket = NULL;
+    }
+    if (_client_socket != NULL) {
+        pal_close(&_client_socket);
+        _client_socket = NULL;
+    }
+    pal_destroy();
+}
+
+// no_open_connection, connection_open, connection_open_timeout
+ftcd_comm_status_e FtcdCommSocket::wait_for_message(uint8_t **message_out, uint32_t *message_size_out)
+{
+    int result = PAL_SUCCESS;
+    ftcd_comm_status_e comm_status = FTCD_COMM_STATUS_SUCCESS;
+    palSocketLength_t addrlen = sizeof(palSocketAddress_t);
+    palSocketAddress_t address = { 0 };
+    bool reiterate;
+
+    do {
+        reiterate = false;
+
+        if (_connection_state == SOCKET_WAIT_FOR_CONNECTION) {
+            // wait to accept connection
+            result = pal_accept(_server_socket, &address, &addrlen, &_client_socket);
+            if (result == PAL_ERR_SOCKET_WOULD_BLOCK) {
+                // Timeout
+                return FTCD_COMM_NETWORK_TIMEOUT;
+            } else if (result != PAL_SUCCESS) {
+                return FTCD_COMM_NETWORK_CONNECTION_ERROR;
+            }
+
+        }
+
+        // Set state as accepted connection
+        _connection_state = SOCKET_CONNECTION_ACCEPTED;
+
+        // Read the message from an open connection,
+        // if the connection has been closed by the client wait for a new connection
+        comm_status = FtcdCommBase::wait_for_message(message_out, message_size_out);
+        if (comm_status == FTCD_COMM_NETWORK_CONNECTION_CLOSED) {
+            reiterate = true; // Set the reiterate flag so that we will wait for a new connection before returning from function
+        } 
+        if (comm_status != FTCD_COMM_STATUS_SUCCESS) { // If error reading - close the client socket and back to SOCKET_CLOSED state
+            _connection_state = SOCKET_WAIT_FOR_CONNECTION;
+        }
+
+    } while (reiterate);
+    return comm_status;
+}
+
+ftcd_comm_status_e FtcdCommSocket::is_token_detected()
+{
+    char c;
+    ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS;
+    size_t idx = 0;
+
+    //read char by char to detect token
+    while (idx < FTCD_MSG_HEADER_TOKEN_SIZE_BYTES) {
+        result = _read_from_socket(reinterpret_cast<void*>(&c), 1);
+        
+        if (result != FTCD_COMM_STATUS_SUCCESS) {
+            return result;
+        }
+
+        if (c == _header_token[idx]) {
+            idx++;
+        } else {
+            idx = 0;
+        }
+    }
+    return result;
+}
+
+
+uint32_t FtcdCommSocket::read_message_size(void)
+{
+    uint32_t message_size = 0;
+    ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS;
+
+    result = _read_from_socket(reinterpret_cast<void*>(&message_size), sizeof(message_size));
+    if (result != FTCD_COMM_STATUS_SUCCESS) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message size");
+        return 0;
+    }
+
+    return message_size;
+}
+
+bool FtcdCommSocket::read_message(uint8_t *message_out, size_t message_size)
+{
+    ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS;
+
+    if (message_out == NULL) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid message buffer");
+        return false;
+    }
+
+    // Read CBOR message bytes
+    // We assume that message_size is NOT bigger than INT_MAX
+    result = _read_from_socket(reinterpret_cast<void*>(message_out), (int)message_size);
+    if (result != FTCD_COMM_STATUS_SUCCESS) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message bytes");
+        return false;
+    }
+    return true;
+}
+
+
+bool FtcdCommSocket::read_message_signature(uint8_t *sig, size_t sig_size)
+{
+    ftcd_comm_status_e result = FTCD_COMM_STATUS_SUCCESS;
+
+    if (sig == NULL) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Invalid sig buffer");
+        return false;
+    }
+
+    // Read signature from medium
+    // We assume that sig_size is NOT bigger than INT_MAX
+    result = _read_from_socket(reinterpret_cast<void*>(sig), (int)sig_size);
+    if (result != FTCD_COMM_STATUS_SUCCESS) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed reading message signature bytes");
+        return false;
+    }
+    return true;
+}
+
+
+bool FtcdCommSocket::send(const uint8_t *data, uint32_t data_size)
+{
+    bool success = true;
+    palStatus_t result = PAL_SUCCESS;
+    size_t sent_bytes = 0;
+    size_t remaind_bytes = (size_t)data_size;
+
+    do {
+        if (_connection_state != SOCKET_CONNECTION_ACCEPTED) {
+            return FTCD_COMM_NETWORK_CONNECTION_CLOSED;
+        }
+        result = pal_send(_client_socket, data, remaind_bytes, &sent_bytes);
+        if (result != PAL_SUCCESS) {
+            // Drop current client for all errors
+            _connection_state = SOCKET_WAIT_FOR_CONNECTION;
+            mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed pal_send");
+            success = false;
+            break;
+        }
+
+        if (sent_bytes == 0 || sent_bytes > remaind_bytes) {
+            mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Sending response message failed");
+            success = false;
+            break;
+        }
+        remaind_bytes = remaind_bytes - sent_bytes;
+        data += sent_bytes;
+
+    } while (remaind_bytes != 0);
+
+    return success;
+}
+
+bool FtcdCommSocket::_listen(void)
+{
+    int status;
+    palStatus_t result = PAL_SUCCESS;
+    palSocketAddress_t address = { 0 };
+    palIpV4Addr_t ipv4 = { 0 };
+    int enable_reuseaddr = 1;
+
+    //Check port number and domain type
+    if (_port == 0) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Wrong port number");
+        return false;
+    }
+
+    if (_current_domain_type != FTCD_IPV4) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "\n Wrong domain type");
+        return false;
+    }
+
+    //Open server and client sockets
+    result = pal_socket((palSocketDomain_t)_current_domain_type, PAL_SOCK_STREAM_SERVER, false, _interface_index, &_server_socket);
+    if (result != PAL_SUCCESS) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_socket failed");
+        return false;
+    }
+
+    result = pal_socket((palSocketDomain_t)_current_domain_type, PAL_SOCK_STREAM, false, _interface_index, &_client_socket);
+    if (result != PAL_SUCCESS) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_socket failed");
+        return false;
+    }
+    // reset connection state
+    _connection_state = SOCKET_WAIT_FOR_CONNECTION;
+
+    status = pal_setSocketOptions(_server_socket, PAL_SO_REUSEADDR, &enable_reuseaddr, sizeof(enable_reuseaddr));
+    if (status != 0) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Failed to set SO_REUSEADDR (status %d)", status);
+        return false;
+    }
+
+    //Get ipv4 format address from interface info structure
+    status = pal_getSockAddrIPV4Addr(&(_net_interface_info->address), ipv4);
+    if (status != 0) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot palGetSockAddrIPV4Addr (status %d)", status);
+        return false;
+    }
+
+    //Set the retrieved address to pal socket address
+    status = pal_setSockAddrIPV4Addr(&address, ipv4);
+    if (status != 0) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot set socket ipv4 address (status %d)", status);
+        return false;
+    }
+
+    //Set current port number to pal socket address
+    status = pal_setSockAddrPort(&address, _port);
+    if (status != 0) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot set socket port address (status %d)", status);
+        return false;
+    }
+
+    //set server socket timeout
+    if (_rcv_timeout >= 0) {
+        status = pal_setSocketOptions(_server_socket, PAL_SO_RCVTIMEO, &_rcv_timeout, sizeof(_rcv_timeout));
+        if (status != 0) {
+            mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Cannot set server socket timeout (status %d)", status);
+            return false;
+        }
+    }
+
+    status = pal_bind(_server_socket, &address, _net_interface_info->addressSize);
+    if (status != 0) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_bind failed (status %d)", status);
+        return false;
+    }
+
+    status = pal_listen(_server_socket, NUM_OF_PENDING_CONNECTIONS);
+    if (status != 0) {
+        mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "pal_listen failed (status %d)", status);
+        return false;
+    }
+
+    mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Factory Client is waiting for incoming connection...");
+
+    return true;
+}
+
+
+ftcd_comm_status_e FtcdCommSocket::_read_from_socket(void * data_out, int data_out_size)
+{
+    palStatus_t pal_status = PAL_SUCCESS;
+    size_t bytes_received = 0;
+    size_t left_to_read = data_out_size;
+    uint8_t* buffer = (uint8_t*)data_out;
+    while (left_to_read > 0) {
+        if (_connection_state != SOCKET_CONNECTION_ACCEPTED) {
+            return FTCD_COMM_NETWORK_CONNECTION_CLOSED;
+        }
+        bytes_received = 0;
+        pal_status = pal_recv(_client_socket, buffer, left_to_read, &bytes_received);
+        if (pal_status == PAL_ERR_SOCKET_CONNECTION_CLOSED) {
+            // Drop current client
+            _connection_state = SOCKET_WAIT_FOR_CONNECTION;
+            return FTCD_COMM_NETWORK_CONNECTION_CLOSED;
+        }
+        else if (pal_status == PAL_ERR_SOCKET_WOULD_BLOCK) {
+            mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Receive socket timeout");
+            return FTCD_COMM_NETWORK_TIMEOUT;
+        } else if (pal_status != PAL_SUCCESS) {
+            mbed_tracef(TRACE_LEVEL_CMD, TRACE_GROUP, "Receive socket error, (status = 0x%" PRIx32 ")", (uint32_t)pal_status);
+            return FTCD_COMM_NETWORK_CONNECTION_ERROR;
+        }
+        buffer += bytes_received;
+        if (left_to_read < bytes_received) {
+            return FTCD_COMM_INTERNAL_ERROR;
+        }
+        left_to_read -= bytes_received;
+    }
+
+    return FTCD_COMM_STATUS_SUCCESS;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/key-config-manager/key-config-manager/kcm_defs.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,123 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __KCM_DEFS_H__
+#define __KCM_DEFS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    /**
+    * @file kcm_defs.h
+    *  \brief Keys and configuration manager (KCM) definitions.
+    */
+
+    /**
+    * KCM item types
+    */
+    typedef enum {
+        KCM_PRIVATE_KEY_ITEM,          //!< KCM private key item type. KCM Supports ECC keys with curves defined in palGroupIndex_t(pal_Crypto.h)
+        KCM_PUBLIC_KEY_ITEM,           //!< KCM public key item type.  KCM Supports ECC keys with curves defined in palGroupIndex_t(pal_Crypto.h)
+        KCM_SYMMETRIC_KEY_ITEM,        //!< KCM symmetric key item type.
+        KCM_CERTIFICATE_ITEM,          //!< KCM certificate item type. Supported x509 certificates in der format.
+        KCM_CONFIG_ITEM,               //!< KCM configuration parameter item type.
+        KCM_LAST_ITEM                  //!< KCM not defined item type.
+    } kcm_item_type_e;
+
+
+
+    /** supported message digests */
+    typedef enum {
+        KCM_MD_NONE = 0x0,
+        KCM_MD_SHA256 = 0x1               //!< KCM SHA256 message digest.
+    } kcm_md_type_e;
+
+
+    /** key usage extension bit-mask options */
+    typedef enum {
+        KCM_CSR_KU_NONE = 0x0,
+        KCM_CSR_KU_DIGITAL_SIGNATURE = 0x1, //!< Digital signature key usage extension bit        
+        KCM_CSR_KU_NON_REPUDIATION = 0x2,   //!< Non repudiation key usage extension bit
+        KCM_CSR_KU_KEY_CERT_SIGN = 0x4      //!< Certificate signing key usage extension bit
+    } kcm_csr_key_usage_e;
+
+
+    /** extended key usage extension bit-mask options */
+    typedef enum {
+        KCM_CSR_EXT_KU_NONE =             0,
+        KCM_CSR_EXT_KU_ANY =              (1 << 0),
+        KCM_CSR_EXT_KU_SERVER_AUTH =      (1 << 1), //!< SSL / TLS Web Server Authentication
+        KCM_CSR_EXT_KU_CLIENT_AUTH =      (1 << 2), //!< SSL / TLS Web Client Authentication
+        KCM_CSR_EXT_KU_CODE_SIGNING =     (1 << 3), //!< Code signing
+        KCM_CSR_EXT_KU_EMAIL_PROTECTION = (1 << 4), //!< E - mail Protection(S / MIME)
+        KCM_CSR_EXT_KU_TIME_STAMPING =    (1 << 8), //!< Trusted Time stamping
+        KCM_CSR_EXT_KU_OCSP_SIGNING =     (1 << 9)  //!< OCSP Signing
+    } kcm_csr_ext_key_usage_e;
+
+    /**
+    * Security descriptor - contains different ACLs such as remote ACL, local ACL and audit.
+    * Currently defined to `void*.`
+    * May be changed in the future.
+    */
+    typedef void* kcm_security_desc_s;
+
+
+    /** Cryptographic scheme types
+    *   Currently only ECC-256 curve is supported.
+    *   More schemes can be added later on.
+    */
+    typedef enum {
+        KCM_SCHEME_NONE,
+        KCM_SCHEME_EC_SECP256R1,       //!< KCM ECC cryptographic scheme, 256-bits NIST curve.
+    }kcm_crypto_key_scheme_e;
+
+    /*
+    * Maximal file name length that can be saved in the KCM
+    */
+#define KCM_MAX_FILENAME_SIZE  1012
+
+    /*
+    * Maximal length of the certificate chain in the device
+    */
+#define KCM_MAX_NUMBER_OF_CERTIFICATES_IN_CHAIN 5
+
+    /*
+    * Certificate chain handle
+    */
+    typedef void* kcm_cert_chain_handle;
+
+    /** This struct contains CSR parameters for future generated CSR
+    *
+    *      @param subject String that contains the subject (distinguished name) of the certificate in predefined format.
+    *                     The format should be as the following example: “C=US,ST=California,L=San Francisco,O=Wikimedia Foundation,Inc.,CN=*.wikipedia.org”.
+    *      @param md_type Message digest selected from `kcm_md_type_e`.
+    *      @param key_usage Key usage extension selected from `kcm_csr_key_usage_e`.
+    *      @param ext_key_usage Extended key usage flags selected from `kcm_csr_ext_key_usage_e`.
+    */
+    typedef struct kcm_csr_params_ {
+        char *subject;
+        kcm_md_type_e md_type;
+        uint32_t key_usage;
+        uint32_t ext_key_usage;
+    } kcm_csr_params_s;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__KCM_DEFS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/key-config-manager/key-config-manager/kcm_status.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,94 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __KCM_STATUS_H__
+#define __KCM_STATUS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* @file kcm_status.h
+*  \brief Keys and configuration manager (KCM) status/error codes.
+* This list may grow as needed.
+*/
+
+typedef enum {
+    KCM_STATUS_SUCCESS,                                       //!< Operation completed successfully.
+    KCM_STATUS_ERROR,                                         //!< Operation ended with an unspecified error.
+    KCM_STATUS_INVALID_PARAMETER,                             //!< A parameter provided to the function was invalid.
+    KCM_STATUS_INSUFFICIENT_BUFFER,                           //!< The provided buffer size was insufficient for the required output.
+    KCM_STATUS_OUT_OF_MEMORY,                                 //!< An out-of-memory condition occurred.
+    KCM_STATUS_ITEM_NOT_FOUND,                                //!< The item was not found in the storage.
+    KCM_STATUS_META_DATA_NOT_FOUND,                           //!< The meta data was not found in the file.
+    KCM_STATUS_META_DATA_SIZE_ERROR,                          //!< The meta data found but the size is different then expected.
+    KCM_STATUS_FILE_EXIST,                                    //!< Trying to store an item that is already in the storage.
+    KCM_STATUS_KEY_EXIST,                                     //!< Trying to generate a key for a CSR, but the requesested output key name already exists in the storage.
+    KCM_STATUS_NOT_PERMITTED,                                 //!< Trying to access an item without proper permissions.
+    KCM_STATUS_STORAGE_ERROR,                                 //!< File error occurred.
+    KCM_STATUS_ITEM_IS_EMPTY,                                 //!< The data of current item is empty.
+    KCM_STATUS_INVALID_FILE_VERSION,                          //!< Invalid file version, the file can not be read
+    KCM_STATUS_FILE_CORRUPTED,                                //!< File data corrupted, the file can not be read
+    KCM_STATUS_FILE_NAME_CORRUPTED,                           //!< File name corrupted, the file can not be read
+    KCM_STATUS_INVALID_FILE_ACCESS_MODE,                      //!< Invalid file access mode
+    KCM_STATUS_UNKNOWN_STORAGE_ERROR,                         //!< KCM can not translate current storage error
+    KCM_STATUS_NOT_INITIALIZED,                               //!< KCM did not initialized.
+    KCM_STATUS_CLOSE_INCOMPLETE_CHAIN,                        //!< Closing KCM chain with less certificates than declared in create
+    KCM_STATUS_CORRUPTED_CHAIN_FILE,                          //!< KCM attempted to open an invalid chain file
+    KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN,                  //!< Operation failed due to invalid number of certificates.
+    KCM_STATUS_CERTIFICATE_CHAIN_VERIFICATION_FAILED,         //!< At least one of the certificates fails to verify its predecessor.
+    KCM_STATUS_FILE_NAME_TOO_LONG,                            //!< Provided a file name that is longer than permitted. 
+    KCM_CRYPTO_STATUS_UNSUPPORTED_HASH_MODE,                  //!< Operation was called with unsupported hash mode.
+    KCM_CRYPTO_STATUS_PARSING_DER_PRIVATE_KEY,                //!< Operation failed to parse private der key.
+    KCM_CRYPTO_STATUS_PARSING_DER_PUBLIC_KEY,                 //!< Operation failed to parse public der key.
+    KCM_CRYPTO_STATUS_PK_KEY_INVALID_FORMAT,                  //!< Operation failed due to invalid pk key format.
+    KCM_CRYPTO_STATUS_INVALID_PK_PUBKEY,                      //!< Operation failed due to invalid pk public key.
+    KCM_CRYPTO_STATUS_ECP_INVALID_KEY,                        //!< Operation failed due to invalid ECP key.
+    KCM_CRYPTO_STATUS_PK_KEY_INVALID_VERSION,                 //!< Operation failed due to invalid pk version of key.
+    KCM_CRYPTO_STATUS_PK_PASSWORD_REQUIRED,                   //!< Operation failed due to missing password.
+    KCM_CRYPTO_STATUS_PRIVATE_KEY_VERIFICATION_FAILED,        //!< Operation failed to verify private key.
+    KCM_CRYPTO_STATUS_PUBLIC_KEY_VERIFICATION_FAILED,         //!< Operation failed to verify public key.
+    KCM_CRYPTO_STATUS_PK_UNKNOWN_PK_ALG,                      //!< Operation failed due to unknown pk algorithm,
+    KCM_CRYPTO_STATUS_UNSUPPORTED_CURVE,                      //!< Unsupported curve.
+    KCM_CRYPTO_STATUS_PARSING_DER_CERT,                       //!< Operation failed to parse der certificate.
+    KCM_CRYPTO_STATUS_CERT_EXPIRED,                           //!< Certificate validity is expired.
+    KCM_CRYPTO_STATUS_CERT_FUTURE,                            //!< Certificate validity starts in future.
+    KCM_CRYPTO_STATUS_CERT_MD_ALG,                            //!< Certificate with bad MD algorithm.
+    KCM_CRYPTO_STATUS_CERT_PUB_KEY_TYPE,                      //!< Certificate with unsupported public key PK type.
+    KCM_CRYPTO_STATUS_CERT_PUB_KEY,                           //!< Certificate with bad public key data (size or curve).
+    KCM_CRYPTO_STATUS_CERT_NOT_TRUSTED,                       //!< Certificate is not trusted.
+    KCM_CRYPTO_STATUS_INVALID_X509_ATTR,                      //!< Certificate with bad x509 attribute
+    KCM_CRYPTO_STATUS_VERIFY_SIGNATURE_FAILED,                //!< Operation failed to check the signature.
+    KCM_CRYPTO_STATUS_INVALID_MD_TYPE,                        //!< Operation failed in check of ecc md type.
+    KCM_CRYPTO_STATUS_FAILED_TO_WRITE_SIGNATURE,              //!< Operation failed to calculate signature.
+    KCM_CRYPTO_STATUS_FAILED_TO_WRITE_PRIVATE_KEY,            //!< Operation failed to write private key to DER buffer.
+    KCM_CRYPTO_STATUS_FAILED_TO_WRITE_PUBLIC_KEY,             //!< Operation failed to write public key to DER buffer.
+    KCM_CRYPTO_STATUS_FAILED_TO_WRITE_CSR,                    //!< Operation failed to write CSR to DER buffer.
+    KCM_CRYPTO_STATUS_INVALID_OID,                            //!< Operation failed due to invalid OID.
+    KCM_CRYPTO_STATUS_INVALID_NAME_FORMAT,                    //!< Operation failed due to invalid name format.
+    KCM_STATUS_SELF_GENERATED_CERTIFICATE_VERIFICATION_ERROR, //!< Verification of self-generated certificate against stored private key failed
+    KCM_MAX_STATUS,
+} kcm_status_e;
+
+//The macro defined for backward compatibility. Will be deprecated.
+#define KCM_STATUS_ESFS_ERROR KCM_STATUS_STORAGE_ERROR
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__KCM_STATUS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/key-config-manager/key-config-manager/key_config_manager.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,347 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __KEYS_CONFIG_MANAGER_H__
+#define __KEYS_CONFIG_MANAGER_H__
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include "kcm_status.h"
+#include "kcm_defs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    /**
+    * @file key_config_manager.h
+    *  \brief Keys and Configuration Manager (KCM) APIs.
+    */
+
+    /* === Initialization and Finalization === */
+
+    /**
+    *   Initiate the KCM module.
+    *   Allocates and initializes file storage resources.
+    *
+    *    @returns
+    *       KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.
+    */
+    kcm_status_e kcm_init(void);
+
+    /**
+    *   Finalize the KCM module.
+    *   Finalizes and frees file storage resources.
+    *
+    *    @returns
+    *       KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.
+    */
+    kcm_status_e kcm_finalize(void);
+
+    /* === Keys, Certificates and Configuration data storage === */
+
+    /** Store the KCM item into a secure storage.
+    *
+    *    @param[in] kcm_item_name KCM item name.
+    *    @param[in] kcm_item_name_len KCM item name length.
+    *    @param[in] kcm_item_type KCM item type as defined in `::kcm_item_type_e`
+    *    @param[in] kcm_item_is_factory True if the KCM item is a factory item, otherwise false.
+    *    @param[in] kcm_item_data KCM item data buffer. Can be NULL if `kcm_item_data_size` is 0.
+    *    @param[in] kcm_item_data_size KCM item data buffer size in bytes. Can be 0 if you wish to store an empty file.
+    *    @param[in] security_desc Security descriptor.
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.
+    */
+    kcm_status_e kcm_item_store(const uint8_t *kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type, bool kcm_item_is_factory, const uint8_t *kcm_item_data, size_t kcm_item_data_size, const kcm_security_desc_s security_desc);
+
+    /* === Keys, Certificates and Configuration data retrieval === */
+
+    /** Retrieve the KCM item data size from a secure storage.
+    *
+    *    @param[in] kcm_item_name KCM item name.
+    *    @param[in] kcm_item_name_len KCM item name length.
+    *    @param[in] kcm_item_type KCM item type as defined in `::kcm_item_type_e`
+    *    @param[out] kcm_item_data_size_out KCM item data size in bytes.
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.
+    */
+    kcm_status_e kcm_item_get_data_size(const uint8_t *kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type, size_t *kcm_item_data_size_out);
+
+    /** Retrieve KCM item data from a secure storage.
+    *
+    *    @param[in] kcm_item_name KCM item name.
+    *    @param[in] kcm_item_name_len KCM item name length.
+    *    @param[in] kcm_item_type KCM item type as defined in `::kcm_item_type_e`
+    *    @param[out] kcm_item_data_out KCM item data output buffer. Can be NULL if `kcm_item_data_size` is 0.
+    *    @param[in] kcm_item_data_max_size The maximum size of the KCM item data output buffer in bytes.
+    *    @param[out] kcm_item_data_act_size_out Actual KCM item data output buffer size in bytes.
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.
+    */
+    kcm_status_e kcm_item_get_data(const uint8_t *kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type, uint8_t *kcm_item_data_out, size_t kcm_item_data_max_size, size_t * kcm_item_data_act_size_out);
+
+    /* === Keys, Certificates and Configuration delete === */
+
+    /** Delete a KCM item from a secure storage.
+    *
+    *    @param[in] kcm_item_name KCM item name.
+    *    @param[in] kcm_item_name_len KCM item name length.
+    *    @param[in] kcm_item_type KCM item type as defined in `::kcm_item_type_e`
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS status in case of success or one of ::kcm_status_e errors otherwise.
+    */
+    kcm_status_e kcm_item_delete(const uint8_t *kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type);
+
+    /* === Certificates chain APIs === */
+
+    /** The API initializes chain context for write chain operation,
+    *   This API should be called prior to ::kcm_cert_chain_add_next API.
+    *
+    *    @param[out] kcm_chain_handle                 pointer to certificate chain handle.
+    *    @param[in]  kcm_chain_name                   pointer to certificate chain name.
+    *    @param[in]  kcm_chain_name_len               length of certificate name buffer.
+    *    @param[in]  kcm_chain_len                    number of certificates in the chain.
+    *    @param[in]  kcm_chain_is_factory             True if the KCM chain is a factory item, otherwise false.
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.
+    */
+    kcm_status_e kcm_cert_chain_create(kcm_cert_chain_handle *kcm_chain_handle,
+                                       const uint8_t *kcm_chain_name,
+                                       size_t kcm_chain_name_len,
+                                       size_t kcm_chain_len,
+                                       bool kcm_chain_is_factory);
+
+    /** The API initializes chain context for read chain operation.
+    *   This API should be called prior to ::kcm_cert_chain_get_next_size and ::kcm_cert_chain_get_next_data APIs
+    *
+    *    @param[out] kcm_chain_handle                  pointer to certificate chain handle.
+    *    @param[in]  kcm_chain_name                    pointer to certificate chain name.
+    *    @param[in]  kcm_chain_name_len                size of certificate name buffer.
+    *    @param[out] kcm_chain_len                     length of certificate chain.
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.
+    */
+    kcm_status_e kcm_cert_chain_open(kcm_cert_chain_handle *kcm_chain_handle,
+                                     const uint8_t *kcm_chain_name,
+                                     size_t kcm_chain_name_len,
+                                     size_t *kcm_chain_len_out);
+
+    /** This API adds next certificate of chain to the storage. 
+    *
+    *  It also validates the previous certificate (unless it is the first certificate) with the public key from kcm_cert_data.
+    *  The certificates should be added in the order from lowest child, followed by the certificate that signs it and so on, all the way to the root of the chain.
+    *
+    *    @param[in] kcm_chain_handle                 certificate chain handle.
+    *    @param[in] kcm_cert_data                    pointer to certificate data in DER format.
+    *    @param[in] kcm_cert_data_size               size of certificate data buffer.
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS in case of success. 
+    *        KCM_STATUS_CERTIFICATE_CHAIN_VERIFICATION_FAILED in case that one of the certificate in the chain failed to verify its predecessor
+    *        In other casese - one of the `::kcm_status_e` errors.
+    *       
+    */
+    kcm_status_e kcm_cert_chain_add_next(kcm_cert_chain_handle kcm_chain_handle,
+                                         const uint8_t *kcm_cert_data,
+                                         size_t kcm_cert_data_size);
+
+    /** The API deletes all certificates of the chain from the storage.
+    *
+    *    @param[in] kcm_chain_name                pointer to certificate chain name.
+    *    @param[in] kcm_chain_name_len            length of certificate chain name.
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.
+    */
+    kcm_status_e kcm_cert_chain_delete(const uint8_t *kcm_chain_name,
+                                       size_t kcm_chain_name_len);
+
+    /** The API returns size of the next certificate in the chain.
+    *  This API should be called prior to ::kcm_cert_chain_get_next_data.
+    *  This operation does not increase chain's context iterator.
+    *
+    *    @param[in]  kcm_chain_handle        certificate chain handle.
+    *    @param[out] kcm_cert_data_size      pointer size of next certificate.
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS in case of success.
+    *        KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN in case we reached the end of the chain
+    *        Otherwise one of the `::kcm_status_e` errors.
+    */
+    kcm_status_e kcm_cert_chain_get_next_size(kcm_cert_chain_handle kcm_chain_handle,
+                                              size_t *kcm_cert_data_size);
+
+    /** The API returns data of the next certificate in the chain.
+    *   To get exact size of a next certificate use ::kcm_cert_chain_get_next_size.
+    *   In the end of get data operation, chain context points to the next certificate of current chain.
+    *
+    *    @param[in] kcm_chain_handle                    certificate chain handle.
+    *    @param[in/out] kcm_cert_data                   pointer to certificate data in DER format.
+    *    @param[in] kcm_max_cert_data_size              max size of certificate data buffer.
+    *    @param[out] kcm_actual_cert_data_size          actual size of certificate data.
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS in case of success.
+    *        KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN in case we reached the end of the chain
+    *        Otherwise one of the `::kcm_status_e` errors.
+    */
+    kcm_status_e kcm_cert_chain_get_next_data(kcm_cert_chain_handle kcm_chain_handle,
+                                              uint8_t *kcm_cert_data,
+                                              size_t kcm_max_cert_data_size,
+                                              size_t *kcm_actual_cert_data_size);
+
+
+    /** The API releases the context and frees allocated resources.
+    *   When operation type is creation--> if total number of added/stored certificates is not equal to number
+    *   of certificates in the chain, the API will return an error.
+    *
+    *    @param[in] kcm_chain_handle                    certificate chain handle.
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS in case of success.
+    *        KCM_STATUS_CLOSE_INCOMPLETE_CHAIN in case of not all certificates were saved. In this case the chain will be deleted.
+    *        Otherwise one of the `::kcm_status_e` errors.
+    */
+    kcm_status_e kcm_cert_chain_close(kcm_cert_chain_handle kcm_chain_handle);
+
+
+    /* === Factory Reset === */
+
+    /**  Reset the KCM secure storage to factory state.
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.
+    */
+    kcm_status_e kcm_factory_reset(void);
+
+
+    /** Generate a key pair complying the given cryptographic scheme in DER format.
+    *    Saves private key and public key if provided.
+    *
+    *      @param key_scheme The cryptographic scheme.
+    *      @param private_key_name The private key name for which a key pair is generated.
+    *      @param private_key_name_len Private key name length
+    *      @param public_key_name The public key name for which a key pair is generated.
+    *      This parameter is optional. If not provided, the key will be generated, but not stored.
+    *      @param public_key_name_len Public key name length.
+    *      Must be 0, if ::public_key_name not provided.
+    *      @param kcm_item_is_factory True if the KCM item is a factory item, otherwise false.
+    *      @param kcm_params Additional kcm_params. Currently void.
+    *
+    *      @returns
+    *         KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.
+    */
+    kcm_status_e kcm_key_pair_generate_and_store(
+        const kcm_crypto_key_scheme_e     key_scheme,
+        const uint8_t                     *private_key_name,
+        size_t                            private_key_name_len,
+        const uint8_t                     *public_key_name,
+        size_t                            public_key_name_len,
+        bool                              kcm_item_is_factory,
+        const kcm_security_desc_s         *kcm_params
+    );
+
+
+    /** Generate a general CSR from the given private key.
+   *
+   *     @param private_key_name The private key name to fetch from storage.
+   *     @param private_key_name_len The private key name len.
+   *     @param csr_params CSR parameters.
+   *     @param csr_buff_out Pointer to generated CSR buffer to fill.
+   *     @param csr_buff_max_size Size of the supplied CSR buffer.
+   *     @param csr_buff_act_size Actual size of the filled CSR buffer.
+   *
+   *     @returns
+   *         KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.
+   */
+    kcm_status_e kcm_csr_generate(
+        const uint8_t              *private_key_name,
+        size_t                     private_key_name_len,
+        const kcm_csr_params_s     *csr_params,
+        uint8_t                    *csr_buff_out,
+        size_t                     csr_buff_max_size,
+        size_t                     *csr_buff_act_size
+    );
+
+
+    /** Generate private and public key and CSR from the generated keys.
+    *
+    *     @param key_scheme The cryptographic scheme.
+    *     @param private_key_name The private key name to generate.
+    *     @param private_key_name_len The private key name len.
+    *     @param public_key_name The public key name for which a key pair is generated.
+    *     This parameter is optional. If not provided, the key will be generated, but not stored.
+    *     @param public_key_name_len Public key name length.
+    *     Must be 0, if ::public_key_name not provided.
+    *     @param kcm_item_is_factory True if the KCM item is a factory item, otherwise false.
+    *     @param csr_params CSR parameters.
+    *     @param csr_buff_out Pointer to generated CSR buffer to fill.
+    *     @param csr_buff_max_size Size of the supplied CSR buffer.
+    *     @param csr_buff_act_size Actual size of the filled CSR buffer.
+    *     @param kcm_data_pkcm_params Additional kcm_params. Currently void.
+    *
+    *     @returns
+    *         KCM_STATUS_SUCCESS in case of success or one of the `::kcm_status_e` errors otherwise.
+    */
+    kcm_status_e kcm_generate_keys_and_csr(
+        kcm_crypto_key_scheme_e     key_scheme,
+        const uint8_t               *private_key_name,
+        size_t                      private_key_name_len,
+        const uint8_t               *public_key_name,
+        size_t                      public_key_name_len,
+        bool                        kcm_item_is_factory,
+        const kcm_csr_params_s      *csr_params,
+        uint8_t                     *csr_buff_out,
+        size_t                      csr_buff_max_size,
+        size_t                      *csr_buff_act_size_out,
+        const kcm_security_desc_s   *kcm_params
+    );
+
+    /** Verify the device-generated certificate against given private key name from storage.
+    * This function can be called when certificate creation is initiated by device using `kcm_generate_keys_and_csr` or `kcm_csr_generate` functions.
+    * In this case, the function checks correlation between certificate's public key and given private key generated by the device and saved in device storage.
+    *
+    *    @param[in] kcm_cert_data DER certificate data buffer.
+    *    @param[in] kcm_cert_data_size DER certificate data buffer size in bytes.
+    *    @param[in] kcm_priv_key_name Private key name of the certificate, the function assumes that the key was generated by the device and saved in the storage.
+    *    @param[in] kcm_priv_key_name_len Private key name length of the certificate.
+    *
+    *    @returns
+    *        KCM_STATUS_SUCCESS in case of success.
+    *        KCM_STATUS_ITEM_NOT_FOUND  in case private key wasn't found in the storage,
+    *            otherwise one of the `::kcm_status_e` errors.
+    */
+    kcm_status_e kcm_certificate_verify_with_private_key(
+        const uint8_t * kcm_cert_data,
+        size_t kcm_cert_data_size,
+        const uint8_t * kcm_priv_key_name,
+        size_t kcm_priv_key_name_len);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__KEYS_CONFIG_MANAGER_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/key-config-manager/source/include/kcm_internal.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,133 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef KEYS_CONFIG_MANAGER_INTERNAL_H
+#define KEYS_CONFIG_MANAGER_INTERNAL_H
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include "esfs.h"
+#include "cs_hash.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === Definitions and Prototypes === */
+
+/* === Defines === */
+#define FCC_ENTROPY_SIZE                   48
+#define FCC_ROT_SIZE                       16
+#define FCC_CA_IDENTIFICATION_SIZE         33 //PAL_CERT_ID_SIZE
+
+/* === EC max sizes === */
+#define KCM_EC_SECP256R1_MAX_PRIV_KEY_DER_SIZE           130
+#define KCM_EC_SECP256R1_MAX_PUB_KEY_RAW_SIZE            65
+#define KCM_EC_SECP256R1_MAX_PUB_KEY_DER_SIZE            91
+#define KCM_ECDSA_SECP256R1_MAX_SIGNATURE_SIZE_IN_BYTES  (256/8)*2 + 10 //74 bytes
+
+/**
+* KCM file prefixes defines
+*/
+#define KCM_FILE_PREFIX_PRIVATE_KEY       "PrvKey_"
+#define KCM_FILE_PREFIX_PUBLIC_KEY        "PubKey_"
+#define KCM_FILE_PREFIX_SYMMETRIC_KEY     "SymKey_"
+#define KCM_FILE_PREFIX_CERTIFICATE       "Cert_"
+#define KCM_FILE_PREFIX_CONFIG_PARAM      "CfgParam_"
+#define KCM_FILE_PREFIX_CERT_CHAIN_0      KCM_FILE_PREFIX_CERTIFICATE
+#define KCM_FILE_PREFIX_CERT_CHAIN_X      "Crt1_" // must be same length as KCM_FILE_PREFIX_CERT_CHAIN_0
+#define KCM_FILE_PREFIX_CERT_CHAIN_X_OFFSET 3
+
+#define KCM_FILE_PREFIX_MAX_SIZE 12
+
+
+// Make sure that pointer_to_complete_name points to a type of size 1 (char or uint8_t) so that arithmetic works correctly
+#define KCM_FILE_BASENAME(pointer_to_complete_name, prefix_define) (pointer_to_complete_name + sizeof(prefix_define) - 1)
+// Complete name is the prefix+name (without '/0')
+#define KCM_FILE_BASENAME_LEN(complete_name_size, prefix_define) (complete_name_size - (sizeof(prefix_define) - 1))
+
+
+    typedef enum {
+        /* KCM_LOCAL_ACL_MD_TYPE,
+           KCM_REMOTE_ACL_MD_TYPE,
+           KCM_AUDIT_MD_TYPE,
+           KCM_NAME_MD_TYPE,
+           KCM_USAGE_MD_TYPE,*/
+        KCM_CERT_CHAIN_LEN_MD_TYPE,
+        KCM_MD_TYPE_MAX_SIZE // can't be bigger than ESFS_MAX_TYPE_LENGTH_VALUES
+    } kcm_meta_data_type_e;
+
+#if ESFS_MAX_TYPE_LENGTH_VALUES < KCM_MD_TYPE_MAX_SIZE
+#error "KCM_MD_TYPE_MAX_SIZE can't be greater than ESFS_MAX_TYPE_LENGTH_VALUES"
+#endif
+
+    typedef struct kcm_meta_data_ {
+        kcm_meta_data_type_e type;
+        size_t data_size;
+        uint8_t *data;
+    } kcm_meta_data_s;
+
+    typedef struct kcm_meta_data_list_ {
+        // allocate a single meta data for each type
+        kcm_meta_data_s meta_data[KCM_MD_TYPE_MAX_SIZE];
+        size_t meta_data_count;
+    } kcm_meta_data_list_s;
+
+    typedef struct kcm_ctx_ {
+        esfs_file_t esfs_file_h;
+        size_t file_size;
+        bool is_file_size_checked;
+    } kcm_ctx_s;
+
+    typedef enum {
+        KCM_CHAIN_OP_TYPE_CREATE = 1,
+        KCM_CHAIN_OP_TYPE_OPEN,
+        KCM_CHAIN_OP_TYPE_MAX
+    } kcm_chain_operation_type_e;
+
+
+    /*
+    * Structure containing all necessary data of a child X509 Certificate to be validated with its signers public key
+    */
+    typedef struct kcm_cert_chain_prev_params_int_ {
+        uint8_t signature[KCM_ECDSA_SECP256R1_MAX_SIGNATURE_SIZE_IN_BYTES]; //!< The signature of certificate.
+        size_t signature_actual_size;                                      //!< The size of signature.
+        uint8_t htbs[CS_SHA256_SIZE];                                      //!< The hash of certificate's tbs.
+        size_t htbs_actual_size;                                           //!< The size of hash digest.
+    } kcm_cert_chain_prev_params_int_s;
+
+
+    /** The chain context used internally only and should not be changed by user.
+    */
+    typedef struct kcm_cert_chain_context_int_ {
+        uint8_t *chain_name;                      //!< The name of certificate chain.
+        size_t  chain_name_len;                   //!< The size of certificate chain name.
+        size_t num_of_certificates_in_chain;      //!< The number of certificate in the chain.
+        kcm_ctx_s current_kcm_ctx;                //!< Current KCM operation context.
+        uint32_t current_cert_index;              //!< Current certificate iterator.
+        kcm_chain_operation_type_e operation_type;//!< Type of Current operation.
+        bool chain_is_factory;                    //!< Is chain is a factory item, otherwise false.
+        kcm_cert_chain_prev_params_int_s prev_cert_params; //!< Saved params of previous parsed certificate. used only in create operation
+    } kcm_cert_chain_context_int_s;
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //KEYS_CONFIG_MANAGER_INTERNAL_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/key-config-manager/source/key_config_manager.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1104 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// 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.
+// ----------------------------------------------------------------------------
+#include <stdbool.h>
+#include "key_config_manager.h"
+#include "storage.h"
+#include "pv_error_handling.h"
+#include "cs_der_certs.h"
+#include "cs_der_keys_and_csrs.h"
+#include "fcc_malloc.h"
+#include "pal.h"
+#include "cs_utils.h"
+
+typedef enum {
+    KCM_PRIVATE_KEY_DATA,
+    KCM_PUBLIC_KEY_DATA,
+    KCM_SYMMETRIC_KEY_DATA,
+    KCM_CERTIFICATE_DATA,
+    KCM_CONFIG_DATA,
+} kcm_data_type;
+
+static bool kcm_initialized = false;
+
+// The func create new name by adding kcm prefix
+static kcm_status_e kcm_create_complete_name(const uint8_t *kcm_name, size_t kcm_name_len, const char *prefix, uint8_t **kcm_buffer_out, size_t *kcm_buffer_size_allocated_out)
+{
+    size_t prefix_length = 0;
+    size_t total_length = 0;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER("name len=%" PRIu32 "", (uint32_t)kcm_name_len);
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_buffer_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_buffer_out parameter");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_buffer_size_allocated_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_buffer_size_allocated_out parameter");
+
+    // Check that name is not too long. This is done only in this function since all KCM APIs using file names go through here.
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_name_len > KCM_MAX_FILENAME_SIZE), KCM_STATUS_FILE_NAME_TOO_LONG, "kcm_item_name_len must be %d or less", KCM_MAX_FILENAME_SIZE);
+
+    prefix_length = strlen(prefix);
+    total_length = kcm_name_len + prefix_length;
+
+    // This Should never happen. This means that the total larger than permitted was used.
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((total_length > STORAGE_FILENAME_MAX_SIZE), KCM_STATUS_INVALID_PARAMETER, "KCM file name too long");
+
+    *kcm_buffer_out = (uint8_t *)fcc_malloc(total_length);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((*kcm_buffer_out == NULL), KCM_STATUS_OUT_OF_MEMORY, "Failed allocating kcm_buffer_out");
+
+    /* Append prefix and name to allocated buffer */
+    memcpy(*kcm_buffer_out, (uint8_t *)prefix, prefix_length);
+    memcpy(*kcm_buffer_out + prefix_length, kcm_name, kcm_name_len);
+
+    *kcm_buffer_size_allocated_out = total_length;
+
+    SA_PV_LOG_TRACE_FUNC_EXIT("kcm_buffer_size_allocated_out=  %" PRIu32 "", (uint32_t)*kcm_buffer_size_allocated_out);
+    return KCM_STATUS_SUCCESS;
+}
+
+
+static kcm_status_e kcm_item_name_get_prefix(kcm_item_type_e kcm_item_type, const char** prefix)
+{
+    kcm_status_e status = KCM_STATUS_SUCCESS;
+
+    switch (kcm_item_type) {
+        case KCM_PRIVATE_KEY_ITEM:
+            *prefix = KCM_FILE_PREFIX_PRIVATE_KEY;
+            break;
+        case KCM_PUBLIC_KEY_ITEM:
+            *prefix = KCM_FILE_PREFIX_PUBLIC_KEY;
+            break;
+        case KCM_SYMMETRIC_KEY_ITEM:
+            *prefix = KCM_FILE_PREFIX_SYMMETRIC_KEY;
+            break;
+        case KCM_CERTIFICATE_ITEM:
+            *prefix = KCM_FILE_PREFIX_CERTIFICATE;
+            break;
+        case KCM_CONFIG_ITEM:
+            *prefix = KCM_FILE_PREFIX_CONFIG_PARAM;
+            break;
+        default:
+            status = KCM_STATUS_INVALID_PARAMETER;
+            break;
+    }
+    return status;
+}
+
+kcm_status_e kcm_init(void)
+{
+    kcm_status_e status = KCM_STATUS_SUCCESS;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    if (!kcm_initialized) {
+        palStatus_t pal_status;
+
+        //Initialize PAL
+        pal_status = pal_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((pal_status != PAL_SUCCESS), KCM_STATUS_ERROR, "Failed initializing PAL (%" PRIu32 ")", pal_status);
+
+        //Initialize back-end storage
+        status = storage_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), status, "Failed initializing storage\n");
+
+        // Mark as "initialized"
+        kcm_initialized = true;
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return status;
+}
+
+kcm_status_e kcm_finalize(void)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    if (kcm_initialized) {
+
+        kcm_status = storage_finalize();
+        if (kcm_status != KCM_STATUS_SUCCESS) {
+            SA_PV_LOG_ERR("Failed finalizing storage\n");
+        }
+
+        //Finalize PAL
+        pal_destroy();
+
+        // Mark as "not initialized"
+        kcm_initialized = false;
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+}
+
+kcm_status_e kcm_item_store(const uint8_t * kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type, bool kcm_item_is_factory, const uint8_t * kcm_item_data, size_t kcm_item_data_size, const kcm_security_desc_s security_desc)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    kcm_ctx_s ctx;
+    uint8_t *kcm_complete_name = NULL; // Filename including prefix
+    size_t kcm_complete_name_size;
+    const char *prefix;
+    bool kcm_item_is_encrypted = true; //encrypt by default
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len");
+    SA_PV_LOG_INFO_FUNC_ENTER("item name =  %.*s len=%" PRIu32 ", data size=%" PRIu32 "", (int)kcm_item_name_len, (char*)kcm_item_name, (uint32_t)kcm_item_name_len, (uint32_t)kcm_item_data_size);
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+
+    // Validate function parameters
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(((kcm_item_data == NULL) && (kcm_item_data_size > 0)), KCM_STATUS_INVALID_PARAMETER, "Provided kcm_item_data NULL and kcm_item_data_size greater than 0");
+
+    //temporary check that security descriptor is NULL
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((security_desc != NULL), KCM_STATUS_INVALID_PARAMETER, "Security descriptor is not NULL!");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type != KCM_CONFIG_ITEM && kcm_item_data_size == 0), KCM_STATUS_ITEM_IS_EMPTY, "The data of current item is empty!");
+
+    switch (kcm_item_type) {
+        case KCM_PRIVATE_KEY_ITEM:
+            kcm_status = cs_der_priv_key_verify(kcm_item_data, kcm_item_data_size);
+            SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Private key validation failed");
+            break;
+        case KCM_PUBLIC_KEY_ITEM:
+            kcm_status = cs_der_public_key_verify(kcm_item_data, kcm_item_data_size);
+            SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Public key validation failed");
+            kcm_item_is_encrypted = false; //do not encrypt public key
+            break;
+        case KCM_SYMMETRIC_KEY_ITEM:
+            //currently possible to write a symmetric key of size 0 since we do not check format
+            break;
+        case KCM_CERTIFICATE_ITEM:
+            kcm_status = cs_check_der_x509_format(kcm_item_data, kcm_item_data_size);
+            SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Certificate validation failed");
+            kcm_item_is_encrypted = false; //do not encrypt certificates
+            break;
+        case KCM_CONFIG_ITEM:
+            break;
+        default:
+            SA_PV_ERR_RECOVERABLE_RETURN_IF((true), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
+    }
+
+    kcm_status = kcm_item_name_get_prefix(kcm_item_type, &prefix);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_item_name_get_prefix");
+
+    kcm_status = kcm_create_complete_name(kcm_item_name, kcm_item_name_len, prefix, &kcm_complete_name, &kcm_complete_name_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_create_complete_name");
+
+    kcm_status = storage_file_write(&ctx, kcm_complete_name, kcm_complete_name_size, kcm_item_data, kcm_item_data_size, NULL, kcm_item_is_factory, kcm_item_is_encrypted);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed writing file to storage");
+
+Exit:
+    fcc_free(kcm_complete_name);
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+}
+
+kcm_status_e kcm_item_get_data_size(const uint8_t *kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type, size_t *kcm_item_data_size_out)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    uint8_t *kcm_complete_name = NULL; // Filename including prefix
+    size_t kcm_complete_name_size;
+    kcm_ctx_s ctx;
+    size_t kcm_data_size = 0;
+    const char *prefix;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len");
+    SA_PV_LOG_INFO_FUNC_ENTER("item name = %.*s len=%" PRIu32 "", (int)kcm_item_name_len, (char*)kcm_item_name, (uint32_t)kcm_item_name_len);
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    // Validate function parameters
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_data_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Kcm size out pointer is NULL");
+
+    kcm_status = kcm_item_name_get_prefix(kcm_item_type, &prefix);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_item_name_get_prefix");
+
+    kcm_status = kcm_create_complete_name(kcm_item_name, kcm_item_name_len, prefix, &kcm_complete_name, &kcm_complete_name_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_create_complete_name");
+
+    kcm_status = storage_file_size_get(&ctx, kcm_complete_name, kcm_complete_name_size, &kcm_data_size);
+    if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
+        goto Exit;
+    }
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Exit, "Failed getting file size");
+
+    *kcm_item_data_size_out = kcm_data_size;
+    SA_PV_LOG_INFO_FUNC_EXIT("kcm data size = %" PRIu32 "", (uint32_t)*kcm_item_data_size_out);
+
+Exit:
+    fcc_free(kcm_complete_name);
+
+    return kcm_status;
+}
+
+
+kcm_status_e kcm_item_get_data(const uint8_t * kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type, uint8_t * kcm_item_data_out, size_t kcm_item_data_max_size, size_t * kcm_item_data_act_size_out)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    uint8_t *kcm_complete_name = NULL; // Filename including prefix
+    size_t kcm_complete_name_size;
+    kcm_ctx_s ctx;
+    const char *prefix;
+    size_t meta_data_size;
+    uint16_t chain_len_to_read;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len");
+    SA_PV_LOG_INFO_FUNC_ENTER("item name = %.*s len = %" PRIu32 ", data max size = %" PRIu32 "", (int)kcm_item_name_len, (char*)kcm_item_name, (uint32_t)kcm_item_name_len, (uint32_t)kcm_item_data_max_size);
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    // Validate function parameters
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_data_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_data_act_size_out");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(((kcm_item_data_out == NULL) && (kcm_item_data_max_size > 0)), KCM_STATUS_INVALID_PARAMETER, "Provided kcm_item_data NULL and kcm_item_data_size greater than 0");
+
+    kcm_status = kcm_item_name_get_prefix(kcm_item_type, &prefix);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_item_name_get_prefix");
+
+    kcm_status = kcm_create_complete_name(kcm_item_name, kcm_item_name_len, prefix, &kcm_complete_name, &kcm_complete_name_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_create_complete_name");
+
+    kcm_status = storage_file_open(&ctx, kcm_complete_name, kcm_complete_name_size);
+    if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
+        goto Exit;
+    }
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Exit, "Failed to open the given file");
+
+    if (kcm_item_type == KCM_CERTIFICATE_ITEM) {
+        // check if there is meta data
+        kcm_status = storage_file_get_meta_data_size(&ctx, KCM_CERT_CHAIN_LEN_MD_TYPE, &meta_data_size);
+        if (kcm_status == KCM_STATUS_SUCCESS) {
+            kcm_status = storage_file_read_meta_data_by_type(&ctx, KCM_CERT_CHAIN_LEN_MD_TYPE, (uint8_t*)&chain_len_to_read, meta_data_size, &meta_data_size);
+            if (kcm_status == KCM_STATUS_SUCCESS && chain_len_to_read > 1) {
+                SA_PV_LOG_WARN("Warning: Reading certificate chain using single certificate API");
+            }
+        }
+    }
+
+    kcm_status = storage_file_read_with_ctx(&ctx, kcm_item_data_out, kcm_item_data_max_size, kcm_item_data_act_size_out);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed reading file from storage (%d)", kcm_status);
+
+    SA_PV_LOG_INFO_FUNC_EXIT("kcm data size = %" PRIu32 "", (uint32_t)*kcm_item_data_act_size_out);
+Exit:
+    if (kcm_status != KCM_STATUS_ITEM_NOT_FOUND) {
+        storage_file_close(&ctx);
+    }
+    fcc_free(kcm_complete_name);
+
+    return kcm_status;
+}
+
+
+kcm_status_e kcm_item_delete(const uint8_t * kcm_item_name, size_t kcm_item_name_len, kcm_item_type_e kcm_item_type)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    uint8_t *kcm_complete_name = NULL; // Filename including prefix
+    size_t kcm_complete_name_size;
+    kcm_ctx_s ctx; // FIXME - Currently not implemented
+    const char *prefix;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_name_len");
+    SA_PV_LOG_INFO_FUNC_ENTER("item name = %.*s len = %" PRIu32 "", (int)kcm_item_name_len, (char*)kcm_item_name, (uint32_t)kcm_item_name_len);
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    // Validate function parameters
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_item_type >= KCM_LAST_ITEM), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_item_type");
+
+    kcm_status = kcm_item_name_get_prefix(kcm_item_type, &prefix);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_item_name_get_prefix");
+
+    kcm_status = kcm_create_complete_name(kcm_item_name, kcm_item_name_len, prefix, &kcm_complete_name, &kcm_complete_name_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_create_complete_name");
+
+    kcm_status = storage_file_delete(&ctx, kcm_complete_name, kcm_complete_name_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed deleting kcm data");
+
+Exit:
+    fcc_free(kcm_complete_name);
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+}
+
+kcm_status_e kcm_factory_reset(void)
+{
+    kcm_status_e status = KCM_STATUS_SUCCESS;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((status != KCM_STATUS_SUCCESS), status, "KCM initialization failed\n");
+    }
+
+    status = storage_factory_reset();
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((status != KCM_STATUS_SUCCESS), (status = status), Exit, "Failed perform factory reset");
+
+Exit:
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return status;
+}
+
+// Internal function to update file name prefix according to chain index
+void kcm_cert_chain_update_name_prefix(uint8_t *complete_file_name, uint32_t index)
+{
+    if (index == 0) {
+        memcpy(complete_file_name, KCM_FILE_PREFIX_CERT_CHAIN_0, strlen(KCM_FILE_PREFIX_CERT_CHAIN_0));
+        return;
+    }
+    memcpy(complete_file_name, KCM_FILE_PREFIX_CERT_CHAIN_X, strlen(KCM_FILE_PREFIX_CERT_CHAIN_X));
+    complete_file_name[KCM_FILE_PREFIX_CERT_CHAIN_X_OFFSET] = (uint8_t)('0' + (uint8_t)index);
+}
+
+static void kcm_cert_chain_files_delete(kcm_cert_chain_context_int_s *chain_context)
+{
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    do {
+        kcm_cert_chain_update_name_prefix(chain_context->chain_name, chain_context->current_cert_index);
+        storage_file_delete(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len);
+        if (chain_context->current_cert_index == 0) {
+            break;
+        }
+        chain_context->current_cert_index--;
+    } while (true);
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+}
+
+kcm_status_e kcm_cert_chain_create(kcm_cert_chain_handle *kcm_chain_handle, const uint8_t *kcm_chain_name, size_t kcm_chain_name_len, size_t kcm_chain_len, bool kcm_chain_is_factory)
+{
+    kcm_cert_chain_context_int_s *chain_context = NULL;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    uint8_t *kcm_complete_name = NULL; // Filename including prefix
+    size_t kcm_complete_name_size;
+    kcm_meta_data_list_s kcm_meta_data;
+    uint16_t chain_len_to_write = (uint16_t)kcm_chain_len;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name len");
+    SA_PV_LOG_INFO_FUNC_ENTER("chain name =  %.*s, chain len =%" PRIu32 "", (int)kcm_chain_name_len, kcm_chain_name, (uint32_t)kcm_chain_len);
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid handle");
+    *kcm_chain_handle = NULL;
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    // Validate function parameters
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_len == 0 || kcm_chain_len > KCM_MAX_NUMBER_OF_CERTIFICATES_IN_CHAIN), KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN, "Invalid chain len");
+
+    kcm_status = kcm_create_complete_name(kcm_chain_name, kcm_chain_name_len, KCM_FILE_PREFIX_CERT_CHAIN_0, &kcm_complete_name, &kcm_complete_name_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_create_complete_name");
+
+    // allocate the context
+    chain_context = (kcm_cert_chain_context_int_s*)fcc_malloc(sizeof(kcm_cert_chain_context_int_s));
+    memset(chain_context, 0, sizeof(kcm_cert_chain_context_int_s));
+
+    // Prepare one meta data item for saving kcm_chain_len as meta data of the first file
+    kcm_meta_data.meta_data[0].type = KCM_CERT_CHAIN_LEN_MD_TYPE;
+    kcm_meta_data.meta_data[0].data_size = sizeof(chain_len_to_write);
+    kcm_meta_data.meta_data[0].data = (uint8_t*)&chain_len_to_write;
+    kcm_meta_data.meta_data_count = 1;
+
+    kcm_status = storage_file_create(&chain_context->current_kcm_ctx, kcm_complete_name, kcm_complete_name_size, &kcm_meta_data, kcm_chain_is_factory, false);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed creating kcm chain file");
+
+    chain_context->operation_type = KCM_CHAIN_OP_TYPE_CREATE;
+    chain_context->chain_name = kcm_complete_name;
+    chain_context->chain_name_len = kcm_complete_name_size;
+    chain_context->num_of_certificates_in_chain = kcm_chain_len;
+    chain_context->current_cert_index = 0;
+    chain_context->chain_is_factory = kcm_chain_is_factory;
+
+Exit:
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        fcc_free(kcm_complete_name);
+        fcc_free(chain_context);
+        *kcm_chain_handle = NULL;
+    } else {
+        // set the handle only if success
+        *kcm_chain_handle = (kcm_cert_chain_handle)chain_context;
+    }
+
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+}
+
+
+kcm_status_e kcm_cert_chain_open(kcm_cert_chain_handle *kcm_chain_handle, const uint8_t *kcm_chain_name, size_t kcm_chain_name_len, size_t *kcm_chain_len_out)
+{
+    kcm_cert_chain_context_int_s *chain_context = NULL;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    uint8_t *kcm_complete_name = NULL; // Filename including prefix
+    size_t kcm_complete_name_size;
+    size_t meta_data_size;
+    uint16_t chain_len_to_read;
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid chain name len");
+    SA_PV_LOG_INFO_FUNC_ENTER("chain name =  %.*s", (int)kcm_chain_name_len, kcm_chain_name);
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid handle");
+    *kcm_chain_handle = NULL;
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    // Validate function parameters
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_len_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain len out");
+
+    kcm_status = kcm_create_complete_name(kcm_chain_name, kcm_chain_name_len, KCM_FILE_PREFIX_CERT_CHAIN_0, &kcm_complete_name, &kcm_complete_name_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed during kcm_create_complete_name");
+
+    // allocate the context
+    chain_context = (kcm_cert_chain_context_int_s*)fcc_malloc(sizeof(kcm_cert_chain_context_int_s));
+    memset(chain_context, 0, sizeof(kcm_cert_chain_context_int_s));
+
+    kcm_status = storage_file_open(&chain_context->current_kcm_ctx, kcm_complete_name, kcm_complete_name_size);
+    if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
+        // skip the error log msg
+        goto Exit;
+    }
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed opening kcm chain file");
+
+    kcm_status = storage_file_get_meta_data_size(&chain_context->current_kcm_ctx, KCM_CERT_CHAIN_LEN_MD_TYPE, &meta_data_size);
+    if (kcm_status == KCM_STATUS_META_DATA_NOT_FOUND) {
+        // treat single cert as chain with size 1
+        chain_len_to_read = 1;
+        kcm_status = KCM_STATUS_SUCCESS;
+    } else {
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed getting kcm meta data size");
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((meta_data_size != sizeof(chain_len_to_read)), (kcm_status = KCM_STATUS_META_DATA_SIZE_ERROR), Exit, "Wrong meta data size");
+
+        kcm_status = storage_file_read_meta_data_by_type(&chain_context->current_kcm_ctx, KCM_CERT_CHAIN_LEN_MD_TYPE, (uint8_t*)&chain_len_to_read, meta_data_size, &meta_data_size);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed reading file's metadata");
+        // Test if the read len is legitimate number
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((chain_len_to_read == 0 || chain_len_to_read > KCM_MAX_NUMBER_OF_CERTIFICATES_IN_CHAIN), (kcm_status = KCM_STATUS_CORRUPTED_CHAIN_FILE), Exit, "Illegitimate chain len in file's metadata");
+    }
+
+    chain_context->operation_type = KCM_CHAIN_OP_TYPE_OPEN;
+    chain_context->chain_name = kcm_complete_name;
+    chain_context->chain_name_len = kcm_complete_name_size;
+    chain_context->num_of_certificates_in_chain = (size_t)chain_len_to_read;
+    chain_context->current_cert_index = 0;
+
+Exit:
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        storage_file_close(&chain_context->current_kcm_ctx);
+        fcc_free(kcm_complete_name);
+        fcc_free(chain_context);
+        *kcm_chain_handle = NULL;
+    } else {
+        *kcm_chain_len_out = chain_context->num_of_certificates_in_chain;
+        // set the handle only if success
+        *kcm_chain_handle = (kcm_cert_chain_handle)chain_context;
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+}
+
+/*
+* If not first certificate in chain:
+*     1. Validate previously added certificate with the public key inside kcm_cert_data
+*     2. Set the chain_context->prev_cert_params to be the params of the current certificate so it can be validated with next call to this function.
+*     3. Store the current certificate
+*     4. Update the index of the chain handle iterator for next use of this function
+* If is first certificate in chain:
+*    File already open - skip step 1 (no previous cert available). Note in this case the file should already be open so no need to reopen it
+*/
+kcm_status_e kcm_cert_chain_add_next(kcm_cert_chain_handle kcm_chain_handle, const uint8_t *kcm_cert_data, size_t kcm_cert_data_size)
+{
+    kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    palX509Handle_t cert;
+
+    SA_PV_LOG_INFO_FUNC_ENTER("cert_data_size =%" PRIu32 "", (uint32_t)kcm_cert_data_size);
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm context");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data == NULL || kcm_cert_data_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data or kcm_cert_data_size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_CREATE), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->current_cert_index >= chain_context->num_of_certificates_in_chain), KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN, "Invalid certificate index");
+
+    // Parse the X509 and make sure it is of correct structure
+    kcm_status = cs_create_handle_from_der_x509_cert(kcm_cert_data, kcm_cert_data_size, &cert);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to parsing cert");
+
+    if (chain_context->current_cert_index > 0) {
+        // If not first certificate - validate based on params of previous certificate
+        kcm_status = cs_x509_cert_verify_signature(cert, chain_context->prev_cert_params.htbs,
+                                                   chain_context->prev_cert_params.htbs_actual_size,
+                                                   chain_context->prev_cert_params.signature,
+                                                   chain_context->prev_cert_params.signature_actual_size);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status == KCM_CRYPTO_STATUS_VERIFY_SIGNATURE_FAILED), (kcm_status = KCM_STATUS_CERTIFICATE_CHAIN_VERIFICATION_FAILED), Clean_X509, "Failed verifying child signature");
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Clean_X509, "Failed verifying child signature");
+        // only on the first certificate, the file is open
+        // update file name by changing last char suffix and create the file
+        kcm_cert_chain_update_name_prefix(chain_context->chain_name, chain_context->current_cert_index);
+        kcm_status = storage_file_create(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len, NULL, chain_context->chain_is_factory, false);
+        if (kcm_status == KCM_STATUS_FILE_EXIST) {
+            // trying to recover by deleting the existing file
+            SA_PV_LOG_INFO("Certificate chain file for index %" PRIu32 " already exists. File will be overwritten.", (uint32_t)chain_context->current_cert_index);
+
+            kcm_status = storage_file_delete(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len);
+            SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Clean_X509, "Failed to delete existing kcm chain file");
+
+            kcm_status = storage_file_create(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len, NULL, chain_context->chain_is_factory, false);
+        }
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Clean_X509, "Failed creating kcm chain file");
+    }
+
+    // Save params only if certificate is not last in chain 
+    if(chain_context->current_cert_index < chain_context->num_of_certificates_in_chain - 1) {
+        // Get params needed for validation by the signer
+        // These will be used to validate this certificate in the chain when parsing the next one
+        kcm_status = cs_child_cert_params_get(cert, &chain_context->prev_cert_params);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed to retrieve child cert params");
+    }
+    kcm_status = storage_file_write_with_ctx(&chain_context->current_kcm_ctx, kcm_cert_data, kcm_cert_data_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed writing kcm chain file");
+
+    kcm_status = storage_file_close(&chain_context->current_kcm_ctx);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed closing kcm chain file");
+
+    // file written, increase current_cert_index
+    chain_context->current_cert_index++;
+
+
+Exit:
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        if (chain_context->current_cert_index > 0) {
+            storage_file_close(&chain_context->current_kcm_ctx);
+        }
+    }
+
+Clean_X509:
+    cs_close_handle_x509_cert(&cert);
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+    return kcm_status;
+}
+
+
+kcm_status_e kcm_cert_chain_delete(const uint8_t *kcm_chain_name, size_t kcm_chain_name_len)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    kcm_status_e first_status_err = KCM_STATUS_SUCCESS;
+    kcm_cert_chain_handle kcm_chain_handle;
+    kcm_cert_chain_context_int_s *chain_context;
+    size_t kcm_chain_len = 0;
+    uint8_t *kcm_complete_name = NULL; // Filename including prefix
+    size_t kcm_complete_name_size;
+    kcm_ctx_s kcm_ctx;
+
+    // Validate function parameters
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_chain_name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_chain_name_len");
+    SA_PV_LOG_INFO_FUNC_ENTER("chain name =  %.*s", (int)kcm_chain_name_len, kcm_chain_name);
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    // open the first file and read the kcm_chain_len from meta data
+    kcm_status = kcm_cert_chain_open(&kcm_chain_handle, kcm_chain_name, kcm_chain_name_len, &kcm_chain_len);
+    if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
+        return kcm_status;
+    } else if (kcm_status != KCM_STATUS_SUCCESS) {
+        kcm_status = kcm_create_complete_name(kcm_chain_name, kcm_chain_name_len, KCM_FILE_PREFIX_CERT_CHAIN_0, &kcm_complete_name, &kcm_complete_name_size);
+        if (kcm_status == KCM_STATUS_SUCCESS) {
+            kcm_status = storage_file_delete(&kcm_ctx, kcm_complete_name, kcm_complete_name_size);
+            fcc_free(kcm_complete_name);
+        }
+        first_status_err = kcm_status;
+        goto Exit;
+    }
+
+    chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle;
+
+    if (kcm_status == KCM_STATUS_SUCCESS) {
+        // close the file before calling delete
+        storage_file_close(&chain_context->current_kcm_ctx);
+    }
+
+    for (; chain_context->current_cert_index < kcm_chain_len; chain_context->current_cert_index++) {
+        kcm_cert_chain_update_name_prefix(chain_context->chain_name, chain_context->current_cert_index);
+        kcm_status = storage_file_delete(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len);
+        // if there was an error, return the first one that occur
+        if (kcm_status != KCM_STATUS_SUCCESS && first_status_err == KCM_STATUS_SUCCESS) {
+            first_status_err = kcm_status;
+        }
+    }
+
+    // close the chain to release the context
+    kcm_cert_chain_close(kcm_chain_handle);
+
+Exit:
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((first_status_err != KCM_STATUS_SUCCESS), first_status_err, "Delete chain but with errors");
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return first_status_err;
+}
+
+
+kcm_status_e kcm_cert_chain_get_next_size(kcm_cert_chain_handle kcm_chain_handle, size_t *kcm_cert_data_size)
+{
+    kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid num_of_certificates_in_chain");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data_size == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data_size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_OPEN), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->current_cert_index >= chain_context->num_of_certificates_in_chain), KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN, "Invalid certificate index");
+
+    if (chain_context->current_cert_index > 0) {
+        // only on the first certificate, the file is open
+        // update file name by changing last char suffix and open the file
+        kcm_cert_chain_update_name_prefix(chain_context->chain_name, chain_context->current_cert_index);
+        kcm_status = storage_file_open(&chain_context->current_kcm_ctx, chain_context->chain_name, chain_context->chain_name_len);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed opening kcm chain file");
+    }
+
+    kcm_status = storage_file_size_get_with_ctx(&chain_context->current_kcm_ctx, kcm_cert_data_size);
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        if (chain_context->current_cert_index > 0) {
+            // close the file only if was open in that function
+            storage_file_close(&chain_context->current_kcm_ctx);
+        }
+        SA_PV_ERR_RECOVERABLE_RETURN(kcm_status, "Failed getting kcm chain file size");
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+}
+
+
+kcm_status_e kcm_cert_chain_get_next_data(kcm_cert_chain_handle kcm_chain_handle, uint8_t *kcm_cert_data, size_t kcm_max_cert_data_size, size_t *kcm_actual_cert_data_size)
+{
+    kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    size_t expected_data_size = 0;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_chain_handle == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid chain handle");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid num_of_certificates_in_chain");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_max_cert_data_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_max_cert_data_size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_actual_cert_data_size == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_actual_cert_data_size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->operation_type != KCM_CHAIN_OP_TYPE_OPEN), KCM_STATUS_INVALID_PARAMETER, "Invalid operation type");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->current_cert_index >= chain_context->num_of_certificates_in_chain), KCM_STATUS_INVALID_NUM_OF_CERT_IN_CHAIN, "Invalid certificate index");
+
+    if (chain_context->current_kcm_ctx.is_file_size_checked == false) {
+        // if user skip call to kcm_cert_chain_get_next_size
+        kcm_status = kcm_cert_chain_get_next_size((kcm_cert_chain_handle*)chain_context, &expected_data_size);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed getting kcm chain file size");
+    } else {
+        expected_data_size = chain_context->current_kcm_ctx.file_size;
+    }
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_max_cert_data_size < expected_data_size), KCM_STATUS_INSUFFICIENT_BUFFER, "Certificate data buffer too small");
+
+    kcm_status = storage_file_read_with_ctx(&chain_context->current_kcm_ctx, kcm_cert_data, kcm_max_cert_data_size, kcm_actual_cert_data_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed read kcm chain file");
+
+    kcm_status = storage_file_close(&chain_context->current_kcm_ctx);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed closing kcm chain file");
+
+    // file read, increase current_cert_index
+    chain_context->current_cert_index++;
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+
+}
+
+
+kcm_status_e kcm_cert_chain_close(kcm_cert_chain_handle kcm_chain_handle)
+{
+    kcm_cert_chain_context_int_s *chain_context = (kcm_cert_chain_context_int_s*)kcm_chain_handle;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    if (kcm_chain_handle == NULL) {
+        goto Exit; // and return KCM_STATUS_SUCCESS
+    }
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((chain_context->num_of_certificates_in_chain == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid num_of_certificates_in_chain");
+
+    if (chain_context->current_cert_index == 0 ||
+        (chain_context->operation_type == KCM_CHAIN_OP_TYPE_OPEN &&
+        chain_context->current_cert_index < chain_context->num_of_certificates_in_chain &&
+        chain_context->current_kcm_ctx.is_file_size_checked)) {
+        // close open file (after create/open or between get_next_size to get_next_data)
+        // if is_file_size_checked is true, the file had open before
+        kcm_status = storage_file_close(&chain_context->current_kcm_ctx);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed closing kcm chain file");
+    }
+
+    if (chain_context->operation_type == KCM_CHAIN_OP_TYPE_CREATE &&
+        chain_context->current_cert_index < chain_context->num_of_certificates_in_chain) {
+        // user added less certificates than num_of_certificates_in_chain, delete all and return error
+        kcm_cert_chain_files_delete(chain_context);
+        SA_PV_ERR_RECOVERABLE_GOTO_IF(true, (kcm_status = KCM_STATUS_CLOSE_INCOMPLETE_CHAIN), Exit, "Closing incomplete kcm chain");
+    }
+
+Exit:
+    if (chain_context != NULL) {
+        fcc_free(chain_context->chain_name);
+        fcc_free(chain_context);
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+
+}
+
+
+kcm_status_e kcm_key_pair_generate_and_store(
+    const kcm_crypto_key_scheme_e    key_scheme,
+    const uint8_t                    *private_key_name,
+    size_t                            private_key_name_len,
+    const uint8_t                    *public_key_name,
+    size_t                            public_key_name_len,
+    bool                              kcm_item_is_factory,
+    const kcm_security_desc_s        *kcm_params)
+
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    size_t actual_kcm_priv_key_size = 0;
+    size_t actual_kcm_pub_key_size = 0;
+    uint8_t priv_key_buffer[KCM_EC_SECP256R1_MAX_PRIV_KEY_DER_SIZE];
+    uint8_t pub_key_buffer[KCM_EC_SECP256R1_MAX_PUB_KEY_DER_SIZE];
+    bool pub_key_exists = false;
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    //temporary check that kcm_params is NULL                                                                                                   
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_params != NULL), KCM_STATUS_INVALID_PARAMETER, "kcm_params is not NULL!");
+
+    //check input params
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((key_scheme != KCM_SCHEME_EC_SECP256R1), KCM_STATUS_INVALID_PARAMETER, "Invalid key_scheme");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name_len");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(((public_key_name != NULL) && (public_key_name_len == 0)), KCM_STATUS_INVALID_PARAMETER, "public_key_name is not NULL, but its size is 0");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(((public_key_name == NULL) && (public_key_name_len != 0)), KCM_STATUS_INVALID_PARAMETER, "public_key_name is NULL, but its size is not 0");
+
+    SA_PV_LOG_INFO_FUNC_ENTER("priv_key_name = %.*s priv_key_len = %" PRIu32 ", pub_key_name = %.*s pub_key_len = %" PRIu32,
+        (int)private_key_name_len, (char*)private_key_name, (uint32_t)private_key_name_len, (int)public_key_name_len, (char*)public_key_name, (uint32_t)public_key_name_len);
+
+    pub_key_exists = ((public_key_name != NULL) && (public_key_name_len != 0));
+
+    //check private key existence
+    kcm_status = kcm_item_get_data_size(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM,
+                                        &actual_kcm_priv_key_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_KEY_EXIST, "private key already exists");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_ITEM_NOT_FOUND), kcm_status, "failed to check private key existence");
+
+    //fetch public key if exists
+    if (pub_key_exists) {
+        kcm_status = kcm_item_get_data_size(public_key_name, public_key_name_len, KCM_PUBLIC_KEY_ITEM,
+                                            &actual_kcm_pub_key_size);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_KEY_EXIST, "public key already exists");
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_ITEM_NOT_FOUND), kcm_status, "failed to check public key existence");
+    }
+
+    //generate key pair
+    kcm_status = cs_key_pair_generate(key_scheme, priv_key_buffer, sizeof(priv_key_buffer), &actual_kcm_priv_key_size, pub_key_buffer, sizeof(pub_key_buffer), &actual_kcm_pub_key_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to generate key pair");
+
+    //store private key
+    kcm_status = kcm_item_store(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM, kcm_item_is_factory, priv_key_buffer, actual_kcm_priv_key_size, NULL);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to store private key");
+
+    //store public key if exists
+    if (pub_key_exists) {
+        kcm_status = kcm_item_store(public_key_name, public_key_name_len, KCM_PUBLIC_KEY_ITEM, kcm_item_is_factory, pub_key_buffer, actual_kcm_pub_key_size, NULL);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to store public key");
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+}
+
+
+kcm_status_e kcm_csr_generate(
+    const uint8_t            *private_key_name,
+    size_t                   private_key_name_len,
+    const kcm_csr_params_s   *csr_params,
+    uint8_t                  *csr_buff_out,
+    size_t                   csr_buff_max_size,
+    size_t                   *csr_buff_act_size)
+{
+
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    size_t prv_key_size, actual_prv_key_size = 0;
+    uint8_t priv_key_buffer[KCM_EC_SECP256R1_MAX_PRIV_KEY_DER_SIZE];
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name_len");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_params");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->subject == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid subject name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->md_type == KCM_MD_NONE), KCM_STATUS_INVALID_PARAMETER, "Invalid md type");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_out");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_max_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_max_size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_act_size == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_act_size");
+
+    SA_PV_LOG_INFO_FUNC_ENTER("priv_key_name = %.*s priv_key_len = %" PRIu32", csr_buff_max_size = %" PRIu32,
+        (int)private_key_name_len, (char*)private_key_name, (uint32_t)private_key_name_len, (uint32_t)csr_buff_max_size);
+
+    //fetch private key size
+    kcm_status = kcm_item_get_data_size(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM,
+                                        &prv_key_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to get private key data size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((prv_key_size == 0), kcm_status, "Size of private key is 0");
+
+    //fetch private key
+    kcm_status = kcm_item_get_data(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM, priv_key_buffer,
+                                   prv_key_size, &actual_prv_key_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to get private key");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((actual_prv_key_size == 0), kcm_status = KCM_STATUS_ITEM_IS_EMPTY, "Size of private key is 0");
+
+    //generate csr
+    kcm_status = cs_csr_generate(priv_key_buffer, actual_prv_key_size, csr_params, csr_buff_out, csr_buff_max_size, csr_buff_act_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to generate CSR");
+
+    SA_PV_LOG_INFO_FUNC_EXIT("csr_buff_act_size = %" PRIu32 "", (uint32_t)*csr_buff_act_size);
+
+    return kcm_status;
+
+}
+
+
+kcm_status_e kcm_generate_keys_and_csr(
+    kcm_crypto_key_scheme_e   key_scheme,
+    const uint8_t             *private_key_name,
+    size_t                    private_key_name_len,
+    const uint8_t             *public_key_name,
+    size_t                    public_key_name_len,
+    bool                      kcm_item_is_factory,
+    const kcm_csr_params_s    *csr_params,
+    uint8_t                   *csr_buff_out,
+    size_t                    csr_buff_max_size,
+    size_t                    *csr_buff_act_size_out,
+    const kcm_security_desc_s *kcm_params)
+{
+
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    size_t actual_kcm_key_size = 0;
+    size_t priv_key_act_size_out = 0;
+    size_t pub_key_act_size_out = 0;
+    uint8_t priv_key_buffer[KCM_EC_SECP256R1_MAX_PRIV_KEY_DER_SIZE];
+    uint8_t pub_key_buffer[KCM_EC_SECP256R1_MAX_PUB_KEY_DER_SIZE];
+    bool pub_key_exists = false;
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    //temporary check that kcm_params is NULL                                                                                                   
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_params != NULL), KCM_STATUS_INVALID_PARAMETER, "kcm_params is not NULL!");
+
+    //check input params
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((key_scheme != KCM_SCHEME_EC_SECP256R1), KCM_STATUS_INVALID_PARAMETER, "Invalid key_scheme");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((private_key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid private_key_name_len");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(((public_key_name != NULL) && (public_key_name_len == 0)), KCM_STATUS_INVALID_PARAMETER, "public_key_name is not NULL, but its size is 0");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(((public_key_name == NULL) && (public_key_name_len != 0)), KCM_STATUS_INVALID_PARAMETER, "public_key_name is NULL, but its size is not 0");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_params");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->subject == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid subject name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_params->md_type == KCM_MD_NONE), KCM_STATUS_INVALID_PARAMETER, "Invalid md type");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_out");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_max_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_max_size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((csr_buff_act_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid csr_buff_act_size");
+
+    SA_PV_LOG_INFO_FUNC_ENTER("priv_key_name = %.*s priv_key_len = %" PRIu32 ", pub_key_name = %.*s pub_key_len = %" PRIu32,
+        (int)private_key_name_len, (char*)private_key_name, (uint32_t)private_key_name_len, (int)public_key_name_len, (char*)public_key_name, (uint32_t)public_key_name_len);
+
+    pub_key_exists = ((public_key_name != NULL) && (public_key_name_len != 0));
+
+    //check private key existence
+    kcm_status = kcm_item_get_data_size(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM,
+                                        &actual_kcm_key_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_KEY_EXIST, "private key already exists");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_ITEM_NOT_FOUND), kcm_status, "failed to check private key existence");
+
+    //check public key existence
+    if (pub_key_exists) {
+        kcm_status = kcm_item_get_data_size(public_key_name, public_key_name_len, KCM_PUBLIC_KEY_ITEM,
+                                            &actual_kcm_key_size);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status == KCM_STATUS_SUCCESS), KCM_STATUS_KEY_EXIST, "public key already exists");
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_ITEM_NOT_FOUND), kcm_status, "failed to check public key existence");
+    }
+
+    //generat keys and csr
+    kcm_status = cs_generate_keys_and_csr(key_scheme, csr_params, priv_key_buffer, sizeof(priv_key_buffer), &priv_key_act_size_out, pub_key_buffer, sizeof(pub_key_buffer), &pub_key_act_size_out, csr_buff_out, csr_buff_max_size, csr_buff_act_size_out);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to generate keys and csr");
+
+    //store private key
+    kcm_status = kcm_item_store(private_key_name, private_key_name_len, KCM_PRIVATE_KEY_ITEM, kcm_item_is_factory, priv_key_buffer, sizeof(priv_key_buffer), NULL);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to store private key");
+
+    //store public key
+    if (pub_key_exists) {
+        kcm_status = kcm_item_store(public_key_name, public_key_name_len, KCM_PUBLIC_KEY_ITEM, kcm_item_is_factory, pub_key_buffer, sizeof(pub_key_buffer), NULL);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "failed to store public key");
+    }
+
+
+    SA_PV_LOG_INFO_FUNC_EXIT("csr_buff_act_size_out = %" PRIu32 "", (uint32_t)*csr_buff_act_size_out);
+    return kcm_status;
+
+}
+
+kcm_status_e kcm_certificate_verify_with_private_key(
+    const uint8_t * kcm_cert_data,
+    size_t kcm_cert_data_size,
+    const uint8_t * kcm_priv_key_name,
+    size_t kcm_priv_key_name_len)
+{
+
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    size_t priv_key_data_size = 0;
+    uint8_t *priv_key_data = NULL;
+    size_t act_priv_key_data_size = 0;
+    palX509Handle_t x509_cert;
+
+    // Check if KCM initialized, if not initialize it
+    if (!kcm_initialized) {
+        kcm_status = kcm_init();
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "KCM initialization failed\n");
+    }
+
+    //check input params
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_cert_data_size == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_cert_data_size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_priv_key_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_priv_key_name");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_priv_key_name_len == 0), KCM_STATUS_INVALID_PARAMETER, "Invalid kcm_priv_key_name_len");
+    SA_PV_LOG_INFO_FUNC_ENTER("priv key name =  %.*s, cert size=%" PRIu32 "", (int)kcm_priv_key_name_len, (char*)kcm_priv_key_name,(uint32_t)kcm_cert_data_size);
+
+    //Get private key size
+    kcm_status = kcm_item_get_data_size(kcm_priv_key_name,
+        kcm_priv_key_name_len,
+        KCM_PRIVATE_KEY_ITEM,
+        &priv_key_data_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS || priv_key_data_size == 0), kcm_status, "Failed to get kcm private key size");
+
+    //Allocate memory and get private key data
+    priv_key_data = fcc_malloc(priv_key_data_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((priv_key_data == NULL), kcm_status = KCM_STATUS_OUT_OF_MEMORY, "Failed to allocate buffer for private key data");
+
+    //Get private key data
+    kcm_status = kcm_item_get_data(kcm_priv_key_name,
+        kcm_priv_key_name_len,
+        KCM_PRIVATE_KEY_ITEM,
+        priv_key_data,
+        priv_key_data_size,
+        &act_priv_key_data_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS || act_priv_key_data_size != priv_key_data_size), (kcm_status = kcm_status), Exit, "Failed to get private key data");
+
+    //Create certificate handle
+    kcm_status = cs_create_handle_from_der_x509_cert(kcm_cert_data, kcm_cert_data_size, &x509_cert);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = kcm_status), Exit, "Failed to create certificate handle");
+
+    //Check current certificate against given private key
+    kcm_status = cs_check_certifcate_public_key(x509_cert, priv_key_data, priv_key_data_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), (kcm_status = KCM_STATUS_SELF_GENERATED_CERTIFICATE_VERIFICATION_ERROR), Exit, "Certificate verification failed against private key");
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+Exit:
+
+    fcc_free(priv_key_data);
+    cs_close_handle_x509_cert(&x509_cert);
+    return kcm_status;
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/logger/logger/pv_log.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,176 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+/* Logging macros */
+
+#ifndef __PV_LOG_H__
+#define __PV_LOG_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define __PV_LOG_H__INSIDE
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdbool.h>
+#include "pal.h"
+#include "mbed-trace/mbed_trace.h"
+
+#define __SA_PV_FILE__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+
+extern palMutexID_t g_pv_logger_mutex;
+/**
+* Calls to mbed trace print function
+*
+* - The function sets mbed trace level according to log level, compose buffer with general data (line,color, file..) and message
+* and calls to mbed_vtracef.
+*/
+void pv_log_trace(int level, const char* filename, int line, const char *func, const char *format, ...);
+/**
+* Print buffer with mbed trace function
+*
+*/
+void pv_log_trace_buffer(int level, const char* filename, int line, const char *func, const char *color, const char *name, const uint8_t *buff, uint32_t buff_size);
+
+#define _SA_PV_LOG_FUNC_ENTER(level, filename, line, func, format, ...) _SA_PV_LOG(level, filename, line, func, "===> " format, ##__VA_ARGS__)
+
+/**  Exit function logging
+ *
+ * - Should be called in the end of a function, assuming the function doesn't exit early due to an error.
+ * - Should display values of output variables (with meaning, no need to print buffers).
+ * - Usage example (with INFO level): SA_PV_LOG_INFO_FUNC_EXIT("argPointerToInt = %d, argPointerToUnsigned32 = %" PRIu32 "", *argPointerToInt, (uint32_t)*argPointerToUnsigned32);
+ */
+#define _SA_PV_LOG_FUNC_EXIT(level, filename, line, func, format, ...) _SA_PV_LOG(level, filename, line, func, "<=== " format, ##__VA_ARGS__)
+
+// CRITICAL always being output
+#define SA_PV_LOG_CRITICAL(format, ...) \
+        _SA_PV_LOG(TRACE_LEVEL_CMD, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#define SA_PV_LOG_BYTE_BUFF_CRITICAL(name, buff, buff_size) \
+        _SA_PV_BYTE_BUFF_LOG(TRACE_LEVEL_CMD, __SA_PV_FILE__, __LINE__, __func__, name, buff, buff_size)
+#define SA_PV_LOG_CRITICAL_FUNC_EXIT(format, ...) \
+        _SA_PV_LOG_FUNC_EXIT(TRACE_LEVEL_CMD, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+
+#if (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_ERROR)
+#define SA_PV_LOG_ERR(format, ...) \
+        _SA_PV_LOG(TRACE_LEVEL_ERROR, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#define SA_PV_LOG_BYTE_BUFF_ERR(name, buff, buff_size) \
+        _SA_PV_BYTE_BUFF_LOG(TRACE_LEVEL_ERROR, __SA_PV_FILE__, __LINE__, __func__, name, buff, buff_size)
+#define SA_PV_LOG_ERR_FUNC_EXIT(format, ...) \
+        _SA_PV_LOG_FUNC_EXIT(TRACE_LEVEL_ERROR, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+
+#else
+#define SA_PV_LOG_ERR(format, arg...) do {} while (0)
+#define SA_PV_LOG_BYTE_BUFF_ERR(format, arg...) do {} while (0)
+#define SA_PV_LOG_ERR_FUNC_EXIT(format, ...) do {} while (0)
+#endif
+
+#if (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_WARN)
+#define SA_PV_LOG_WARN(format, ...) \
+        _SA_PV_LOG(TRACE_LEVEL_WARN, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#define SA_PV_LOG_BYTE_BUFF_WARN(name, buff, buff_size) \
+        _SA_PV_BYTE_BUFF_LOG(TRACE_LEVEL_WARN, __SA_PV_FILE__, __LINE__, __func__, name, buff, buff_size)
+#define SA_PV_LOG_WARN_FUNC_EXIT(format, ...) \
+        _SA_PV_LOG_FUNC_EXIT(TRACE_LEVEL_WARN, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#else
+#define SA_PV_LOG_WARN(format, ...) do {} while (0)
+#define SA_PV_LOG_BYTE_BUFF_WARN(format, ...) do {} while (0)
+#define SA_PV_LOG_WARN_FUNC_EXIT(format, ...) do {} while (0)
+#endif
+
+#if (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_INFO)
+#define SA_PV_LOG_INFO(format, ...) \
+        _SA_PV_LOG(TRACE_LEVEL_INFO, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#define SA_PV_LOG_INFO_FUNC_ENTER(format, ...) \
+        _SA_PV_LOG_FUNC_ENTER(TRACE_LEVEL_INFO, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#define SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS() \
+        SA_PV_LOG_INFO_FUNC_ENTER("")
+#define SA_PV_LOG_INFO_FUNC_EXIT(format, ...) \
+        _SA_PV_LOG_FUNC_EXIT(TRACE_LEVEL_INFO, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#define SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS() \
+        SA_PV_LOG_INFO_FUNC_EXIT("")
+#define SA_PV_LOG_BYTE_BUFF_INFO(name, buff, buff_size) \
+        _SA_PV_BYTE_BUFF_LOG(TRACE_LEVEL_INFO, __SA_PV_FILE__, __LINE__, __func__, name, buff, buff_size)
+#else
+#define SA_PV_LOG_INFO(format, ...) do {} while (0)
+#define SA_PV_LOG_INFO_FUNC_ENTER(format, ...) do {} while (0)
+#define SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS() do {} while (0)
+#define SA_PV_LOG_INFO_FUNC_EXIT(format, ...) do {} while (0)
+#define SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS() do {} while (0)
+#define SA_PV_LOG_BYTE_BUFF_INFO(format, ...) do {} while (0)
+#endif
+
+#if (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_DEBUG)
+#define SA_PV_LOG_TRACE(format, ...) \
+        _SA_PV_LOG(TRACE_LEVEL_DEBUG, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#define SA_PV_LOG_TRACE_FUNC_ENTER(format, ...) \
+        _SA_PV_LOG_FUNC_ENTER(TRACE_LEVEL_DEBUG, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#define SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS() \
+        SA_PV_LOG_TRACE_FUNC_ENTER("")
+#define SA_PV_LOG_TRACE_FUNC_EXIT(format, ...) \
+        _SA_PV_LOG_FUNC_EXIT(TRACE_LEVEL_DEBUG, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#define SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS() \
+        SA_PV_LOG_TRACE_FUNC_EXIT("")
+#define SA_PV_LOG_BYTE_BUFF_TRACE(name, buff, buff_size) \
+        _SA_PV_BYTE_BUFF_LOG(TRACE_LEVEL_DEBUG, __SA_PV_FILE__, __LINE__, __func__, name, buff, buff_size)
+
+#else
+#define SA_PV_LOG_TRACE(format, ...) do {} while (0)
+#define SA_PV_LOG_TRACE_FUNC_ENTER(format, ...) do {} while (0)
+#define SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS() do {} while (0)
+#define SA_PV_LOG_TRACE_FUNC_EXIT(format, ...) do {} while (0)
+#define SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS() do {} while (0)
+#define SA_PV_LOG_BYTE_BUFF_TRACE(format, ...) do {} while (0)
+#endif
+
+#if (MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_DEBUG)
+#define SA_PV_LOG_DATA(format, ...) \
+        _SA_PV_LOG(TRACE_LEVEL_DEBUG, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#define SA_PV_LOG_DATA_FUNC_ENTER(format, ...) \
+  _SA_PV_LOG_FUNC_ENTER(TRACE_LEVEL_DEBUG, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#define SA_PV_LOG_DATA_FUNC_ENTER_NO_ARGS() \
+        SA_PV_LOG_DATA_FUNC_ENTER("")
+#define SA_PV_LOG_DATA_FUNC_EXIT(format, ...) \
+        _SA_PV_LOG_FUNC_EXIT(TRACE_LEVEL_DEBUG, __SA_PV_FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
+#define SA_PV_LOG_DATA_FUNC_EXIT_NO_ARGS() \
+        SA_PV_LOG_DATA_FUNC_EXIT("")
+#define SA_PV_LOG_BYTE_BUFF_DATA(name, buff, buff_size) \
+        _SA_PV_BYTE_BUFF_LOG(TRACE_LEVEL_DEBUG, __SA_PV_FILE__, __LINE__, __func__, name, buff, buff_size)
+#else
+#define SA_PV_LOG_DATA(format, ...) do {} while (0)
+#define SA_PV_LOG_DATA_FUNC_ENTER(format, ...) do {} while (0)
+#define SA_PV_LOG_DATA_FUNC_ENTER_NO_ARGS() do {} while (0)
+#define SA_PV_LOG_DATA_FUNC_EXIT(format, ...) do {} while (0)
+#define SA_PV_LOG_DATA_FUNC_EXIT_NO_ARGS() do {} while (0)
+#define SA_PV_LOG_BYTE_BUFF_DATA(format, ...) do {} while (0)
+#endif
+
+/* Should only be called once, additional calls do nothing. */
+#define _SA_PV_LOG(level, file, line, func, format, ...) \
+do{ \
+        mbed_tracef(level, "fcc","%s:%d:%s:"format, file, line, func, ##__VA_ARGS__);\
+} while (0)
+
+#define _SA_PV_BYTE_BUFF_LOG(level, file, line, func, name, buff, buff_size) ( mbed_tracef(level, "fcc", "%s"name, mbed_trace_array(buff, buff_size)))
+
+#undef __PV_LOG_H__INSIDE
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__PV_LOG_H__*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,4 @@
+CMakeFiles/*
+Docs/*
+Test/*
+out/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/CMakeLists.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,75 @@
+
+
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/source/include)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/source/sotp)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Test/Unity/src)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Test/Unity/extras/fixture/src)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../mbed-trace)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../nanostack-libservice/mbed-client-libservice)
+
+# temp workaround
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../mbed-client-pal/Source/Port/Platform-API)
+
+ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/source/include)
+
+set (PAL_TESTS_SOURCE_DIR  ${CMAKE_CURRENT_SOURCE_DIR}/../../mbed-client-pal/Test/Unitest)
+
+#SET(SOTP_DEBUG_FLAGS "-DESFS_INTERACTIVE_TEST")
+add_definitions(${SOTP_DEBUG_FLAGS})
+
+add_definitions(-DSOTP_TESTING)
+
+FILE(
+	GLOB_RECURSE  
+	esfs_src
+	"${CMAKE_CURRENT_SOURCE_DIR}/source/*.c"
+	"${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp"
+	"${CMAKE_CURRENT_SOURCE_DIR}/source/*.h"
+)
+
+message ( "********************************************************************* ")
+message ("esfs_src = [[${esfs_src}]]")
+message ( "********************************************************************* ")
+
+CREATE_LIBRARY(esfs "${esfs_src}" "")
+
+
+if(DEFINED ENV{ESFS_TESTS_ENABLED})
+
+# ESFS_TESTS_ENABLED is an environment variable.
+# define ESFS_TESTS_ENABLED only if you would like to build ESFS unit-tests.
+# By default, ESFS_TESTS_ENABLED is NOT defined, meaning ESFS's tests are disabled and compiled out. 
+
+FILE(
+	GLOB_RECURSE  
+	esfs_test_src
+	"${CMAKE_CURRENT_SOURCE_DIR}/Test/Unitest/*.c"
+	"${CMAKE_CURRENT_SOURCE_DIR}/Test/Unitest/*.cpp"
+	"${CMAKE_CURRENT_SOURCE_DIR}/Test/Unitest/*.h"
+
+	"${CMAKE_CURRENT_SOURCE_DIR}/Test/linux/*.h"
+	"${CMAKE_CURRENT_SOURCE_DIR}/Test/linux/*.c"
+	"${CMAKE_CURRENT_SOURCE_DIR}/Test/linux/*.cpp"
+	
+	"${CMAKE_CURRENT_SOURCE_DIR}/Test/Unity/src/*.c"
+	"${CMAKE_CURRENT_SOURCE_DIR}/Test/Unity/src/*.h"
+
+	"${CMAKE_CURRENT_SOURCE_DIR}/Test/Unity/extras/fixture/src/*.c"
+	"${CMAKE_CURRENT_SOURCE_DIR}/Test/Unity/extras/fixture/src/*.h"
+
+	${PAL_TESTS_SOURCE_DIR}/TestRunner/pal_test${OS_BRAND}.c 
+)
+
+message ( "********************************************************************* ")
+message ("esfs_test_src = [[${esfs_test_src}]]")
+message ( "********************************************************************* ")
+
+set (ESFS_TEST_FLAGS
+    -DPAL_RUN_ALL_TESTS
+)	
+
+CREATE_TEST_LIBRARY(esfs_tests "${esfs_test_src}" "${ESFS_TEST_FLAGS}")
+ADD_DEPENDENCIES(esfs_tests esfs)
+
+endif()
Binary file simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/Tools/FRDM-K64FfreeRTOS_Create2Partitions has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/esfs.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2576 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+
+
+// ----------------------------------------------------------- Includes -----------------------------------------------------------
+
+#ifdef MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#include MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#endif
+
+
+#include "pal.h"
+#include "esfs.h"
+#include "esfs_file_name.h"
+
+#include "mbed-trace/mbed_trace.h"
+
+
+#include <string.h>  // For memcmp and strncat
+
+
+
+// --------------------------------------------------------- Definitions ----------------------------------------------------------
+
+
+#define TRACE_GROUP                     "esfs"  // Maximum 4 characters
+
+// We do not really know what other uses (if any) the file system card will have.
+// We will assume that it may contain other files and we will keep all ESFS files in one directory.
+// A future enhancement could be to put files that are not to be removed at factory reset in a separate directory.
+#if !defined(ESFS_WORKING_DIRECTORY)
+#define ESFS_WORKING_DIRECTORY          "WORKING"
+#endif
+
+#if !defined(ESFS_BACKUP_DIRECTORY)
+#define ESFS_BACKUP_DIRECTORY           "BACKUP"
+#endif
+
+#define FACTORY_RESET_DIR               "FR"
+#define FACTORY_RESET_FILE              "fr_on"
+
+// We choose a size that does not take up too much stack, but minimizes the number of reads.
+#define ESFS_READ_CHUNK_SIZE_IN_BYTES   (64)
+
+#define ESFS_BITS_IN_BYTE               (8)
+#define ESFS_AES_BLOCK_SIZE_BYTES       (16)
+#define ESFS_AES_IV_SIZE_BYTES          (16)
+#define ESFS_AES_COUNTER_INDEX_IN_IV    ESFS_AES_NONCE_SIZE_BYTES
+#define ESFS_AES_COUNTER_SIZE_BYTES     (8)
+#define ESFS_AES_KEY_SIZE_BYTES         (16)
+#define ESFS_AES_KEY_SIZE_BITS          (ESFS_AES_KEY_SIZE_BYTES * ESFS_BITS_IN_BYTE)
+
+// Defines the size in bytes of buffers for AES encryption / decryption.
+// In case we have to encrypt / decrypt a bigger amount of bytes, we loop over the buffer
+// and encrypt / decrypt up to ESFS_AES_BUF_SIZE_BYTES bytes on each step
+#define ESFS_AES_BUF_SIZE_BYTES         (256)
+
+// This should be incremented when the file format changes
+#define ESFS_FILE_FORMAT_VERSION        (1)
+
+#define ESFS_FILE_COPY_CHUNK_SIZE       (256)
+
+#define MAX_FULL_PATH_SIZE (PAL_MAX_FOLDER_DEPTH_CHAR + \
+                            1 + \
+                            PAL_MAX(sizeof(ESFS_BACKUP_DIRECTORY), sizeof(ESFS_WORKING_DIRECTORY)) + \
+                            PAL_MAX(sizeof(FACTORY_RESET_DIR) + sizeof(FACTORY_RESET_FILE), ESFS_QUALIFIED_FILE_NAME_LENGTH))
+
+static bool esfs_initialize = false;
+
+
+
+// -------------------------------------------------- Functions Implementation ----------------------------------------------------
+
+
+//      ---------------------------------------------------------------
+//                              Helper Functions
+//      ---------------------------------------------------------------
+
+
+esfs_result_e esfs_init(void)
+{
+    esfs_result_e result = ESFS_SUCCESS;
+    tr_info("esfs_init - enter");
+    if (!esfs_initialize)
+    {
+        palStatus_t pal_result = PAL_SUCCESS;
+        esfs_file_t file_handle = {0};
+        char dir_path[MAX_FULL_PATH_SIZE] = { 0 };
+
+        pal_result = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, dir_path);
+        if (pal_result != PAL_SUCCESS)
+        {
+            tr_err("esfs_init() - pal_fsGetMountPoint() for working directory failed with pal_status = 0x%x", (unsigned int)pal_result);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+
+        strncat(dir_path, "/" ESFS_WORKING_DIRECTORY, sizeof(ESFS_WORKING_DIRECTORY));
+
+        //Looping on first file system operation to work around IOTMORF-914 - sd-driver initialization
+        for(int i=0 ; i<100; i++)
+        {
+            // Create the esfs subfolder working
+            pal_result = pal_fsMkDir(dir_path);
+            if ((pal_result == PAL_SUCCESS) || (pal_result == PAL_ERR_FS_NAME_ALREADY_EXIST))
+            {
+                break;
+            }
+            tr_err("esfs_init() %d", i);
+            pal_osDelay(50);
+
+        }
+
+        if ((pal_result != PAL_SUCCESS) && (pal_result != PAL_ERR_FS_NAME_ALREADY_EXIST))
+        {
+                tr_err("esfs_init() - pal_fsMkDir() for working directory failed with pal_status = 0x%x", (unsigned int)pal_result);
+                result = ESFS_ERROR;
+                goto errorExit;
+        }
+
+        pal_result = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, dir_path);
+        if (pal_result != PAL_SUCCESS)
+        {
+
+            tr_err("esfs_init() - pal_fsGetMountPoint() for backup directory failed with pal_status = 0x%x", (unsigned int)pal_result);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+
+        strncat(dir_path, "/" ESFS_BACKUP_DIRECTORY, sizeof(ESFS_BACKUP_DIRECTORY));
+
+        // Create the directory ESFS_BACKUP_DIRECTORY
+        pal_result = pal_fsMkDir(dir_path);
+        if (pal_result != PAL_SUCCESS)
+        {
+            // Any error apart from file exist returns error.
+            if (pal_result != PAL_ERR_FS_NAME_ALREADY_EXIST)
+            {
+                tr_err("esfs_init() - pal_fsMkDir() for backup directory failed with pal_status = 0x%x", (unsigned int)pal_result);
+                result = ESFS_ERROR;
+                goto errorExit;
+            }
+        }
+
+        // create the correct path for factory reset file fr_on
+        strncat(dir_path, "/" FACTORY_RESET_DIR "/" FACTORY_RESET_FILE, sizeof(FACTORY_RESET_DIR) + sizeof(FACTORY_RESET_FILE));
+        pal_result = pal_fsFopen(dir_path, PAL_FS_FLAG_READONLY, &(file_handle.file));
+        // (res == PAL_SUCCESS) : flag file can be opened for reading --> file \FR\fr_on found
+        //                        previous factory reset failed during execution
+        // (res == PAL_ERR_FS_NO_FILE) : flag file was not found --> good scenario
+        // (res != PAL_ERR_FS_NO_FILE) : file system problem
+        if (pal_result == PAL_SUCCESS)
+        {
+            //  Close the file before factory reset
+            pal_result = pal_fsFclose(&(file_handle.file));
+            if (pal_result != PAL_SUCCESS)
+            {
+                tr_err("esfs_init() - unexpected filesystem behavior pal_fsFclose() failed with pal_status = 0x%x", (unsigned int)pal_result);
+                result = ESFS_ERROR;
+                goto errorExit;
+            }
+            // previous factory reset failed during execution - therefore we call this factory_reset again
+            result = esfs_factory_reset();
+            if (result != ESFS_SUCCESS)
+            {
+                tr_err("esfs_init() - esfs_factory_reset() failed with esfs_result_e = 0x%x", result);
+                result = ESFS_ERROR;
+                goto errorExit;
+            }
+        } else if (pal_result != PAL_ERR_FS_NO_FILE)
+        {
+            tr_err("esfs_init() - unexpected filesystem behavior pal_fsFopen() failed with pal_status = 0x%x", (unsigned int)pal_result);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+
+        esfs_initialize = true;
+    }
+    return ESFS_SUCCESS;
+
+errorExit:
+    return result;
+
+}
+
+esfs_result_e esfs_finalize(void)
+{
+    esfs_initialize = false;
+    tr_info("esfs_finalize - enter");
+    return ESFS_SUCCESS;
+}
+
+// Validate that a file handle has been initialized by create or open.
+// Parameters : file_handle - [IN] A pointer to a file handle for which we calculate the size.
+// Return     : ESFS_SUCCESS on success. Error code otherwise
+static esfs_result_e esfs_validate(esfs_file_t *file_handle)
+{
+    if(file_handle && file_handle->blob_name_length > 0)
+    {
+        return ESFS_SUCCESS;
+    }
+    else
+    {
+        return ESFS_ERROR;
+    }
+}
+
+
+//Function   : esfs_not_encrypted_file_header_size
+//
+//Description: This function returns the size in bytes of the file header without the metadata values part.
+//             This is actually the non-encrypted part of the file header.
+//             It is useful for calculation the file pointer position for AES encryption / decryption which starts only from the
+//             encrypted part of the file.
+//
+//Parameters : file_handle - [IN] A pointer to a file handle for which we calculate the size.
+//
+//Return     : The size in bytes of the non-encrypted part of the file header
+static size_t esfs_not_encrypted_file_header_size(esfs_file_t *file_handle)
+{
+    esfs_tlv_properties_t *tlv_properties = &(file_handle->tlv_properties);
+
+    return ( file_handle->blob_name_length         +                                              // Name length field
+             sizeof(file_handle->blob_name_length) +                                              // Name field
+             sizeof(uint16_t)                      +                                              // Version field
+             sizeof(uint16_t)                      +                                              // Mode field
+             (((file_handle->esfs_mode & ESFS_ENCRYPTED) != 0) ? ESFS_AES_NONCE_SIZE_BYTES : 0) + // Nonce field [non mandatory field] 
+             sizeof(tlv_properties->number_of_items)                                    +         // Metadata number of elements field
+             (tlv_properties->number_of_items * sizeof(tlv_properties->tlv_items[0]))             // Metadata tlv headers
+           );
+}
+
+// Returns the size in bytes of the file header.
+// This can only be called after the header has been read.
+// Parameters :
+// file_handle - [IN] A pointer to a file handle for which we calculate the size.
+static size_t esfs_file_header_size(esfs_file_t *file_handle)
+{
+    size_t metadata_size = 0;
+    esfs_tlv_properties_t *tlv_properties = &file_handle->tlv_properties;
+
+    for(int i = 0; i < tlv_properties->number_of_items; i++)
+    {
+        metadata_size += tlv_properties->tlv_items[i].length_in_bytes;
+    }
+
+    return esfs_not_encrypted_file_header_size(file_handle) + metadata_size;
+}
+
+// Helper function to calculate the cmac on data that is written.
+// Parameters :
+// pbuf        - [IN] A pointer to a buffer
+// num_bytes   - [IN] number of bytes that we request to write.
+// file_handle - [IN] A pointer to a file handle for which we calculate the size.
+// Return     : ESFS_SUCCESS on success. Error code otherwise
+static esfs_result_e esfs_fwrite_and_calc_cmac(const void *pbuf, size_t num_bytes, esfs_file_t *file_handle)
+{
+    palStatus_t res = pal_CMACUpdate(file_handle->signature_ctx, pbuf, num_bytes);
+    if(res != PAL_SUCCESS)
+    {
+        tr_err("esfs_fwrite_and_calc_cmac() - pal_CMACUpdate failed with result = 0x%x", (unsigned int)res);
+        return ESFS_ERROR;
+    }
+
+    size_t num_bytes_written;
+    res = pal_fsFwrite(&file_handle->file, pbuf, num_bytes, &num_bytes_written);
+    if(res != PAL_SUCCESS || num_bytes != num_bytes_written)
+    {
+        tr_err("esfs_fwrite_and_calc_cmac() - pal_fsFwrite failed, status = 0x%x, written bytes = %zu, expected = %zu",
+                (unsigned int)res, num_bytes_written, num_bytes);
+        return ESFS_ERROR;
+    }
+
+    return ESFS_SUCCESS;
+}
+
+
+// Helper function to start a cmac run.
+// Moves the file position to the start of the file.
+// Parameters :
+// file_handle - [IN] A pointer to a file handle.
+// If successful it creates a cmac context which must be destroyed with a call to esfs_cmac_finish
+// Return     : ESFS_SUCCESS on success. Error code otherwise.
+static esfs_result_e esfs_cmac_start(esfs_file_t *file_handle)
+{
+    unsigned char key[ESFS_CMAC_SIZE_IN_BYTES];
+
+    // Get CMAC key from PAL
+    palStatus_t res = pal_osGetDeviceKey(palOsStorageSignatureKey128Bit, &key[0], ESFS_CMAC_SIZE_IN_BYTES);
+    if(res != PAL_SUCCESS)
+    {
+        tr_err("esfs_start_cmac() - pal_osGetDeviceKey() failed with pal_status = 0x%x", (unsigned int)res);
+        return  ESFS_ERROR;
+    }
+
+    // Start CMAC with the key. Initializes signature_ctx
+    res = pal_CMACStart(&file_handle->signature_ctx, &key[0], 128, PAL_CIPHER_ID_AES);
+    if(res != PAL_SUCCESS)
+    {
+        tr_err("esfs_start_cmac() - pal_CMACStart() failed with pal_status = 0x%x", (unsigned int)res);
+        return  ESFS_ERROR;
+    }
+
+    // Seek to the start of the file
+    res = pal_fsFseek(&file_handle->file, 0, PAL_FS_OFFSET_SEEKSET);
+    if(res != PAL_SUCCESS)
+    {
+        tr_err("esfs_start_cmac() - pal_fsFseek() failed with pal status 0x%x", (unsigned int)res);
+
+        // Clean up the cmac context
+        size_t num_bytes;
+        // Ignore error. Sets file_handle->signature_ctx to 0 on success
+        (void)pal_CMACFinish(&file_handle->signature_ctx, &key[0], &num_bytes);
+        return  ESFS_ERROR;
+    }
+
+    return  ESFS_SUCCESS;
+}
+
+// Helper function to read and calculate the cmac on data that is read.
+// The function will not update the cmac if there is no CMAC context in the file handle.
+// Updates the file position.
+// Parameters :
+// file_handle    - [IN]   A pointer to a file handle for which we calculate the cmac.
+// pbuf           - [OUT]  A pointer to a buffer containing the data that is read.
+// num_bytes      - [IN]   number of bytes that we request to read.
+// num_bytes_read - [OUT]  A pointer to a location in which will be written the number of bytes actually read.
+// Return     : ESFS_SUCCESS on success. Error code otherwise
+static esfs_result_e esfs_cmac_read(esfs_file_t *file_handle, void *pbuf, size_t num_bytes, size_t *num_bytes_read)
+{
+    palStatus_t res = pal_fsFread(&file_handle->file, pbuf, num_bytes, num_bytes_read);
+    if(res != PAL_SUCCESS)
+    {
+        tr_err("esfs_cmac_read() - pal_fsFread failed with status = 0x%x", (unsigned int)res);
+        return ESFS_ERROR;
+    }
+
+    // Update the CMAC only if there is a context. (It is allowed to read the file without calculating CMAC if
+    // it does not need to checked.)
+    if(file_handle->signature_ctx)
+    {
+        res = pal_CMACUpdate(file_handle->signature_ctx, pbuf, *num_bytes_read);
+        if(res != PAL_SUCCESS)
+        {
+            tr_err("esfs_cmac_read() - pal_CMACUpdate failed with status = 0x%x", (unsigned int)res);
+            return ESFS_ERROR;
+        }
+    }
+
+    return ESFS_SUCCESS;
+}
+
+
+// Helper function to skip past a part of the file while calculating the cmac on the skipped data.
+// Updates the file position.
+// Parameters :
+// file_handle - [IN]   A pointer to a file handle.
+// to          - [IN]   The absolute position from the start of the file to which skip.
+//                      It must be greater than the current position and no longer that the file size.
+// Return     : ESFS_SUCCESS on success. Error code otherwise.
+static esfs_result_e esfs_cmac_skip_to(esfs_file_t *file_handle, int32_t to)
+{
+    // Get current position
+    int32_t current_pos;
+    palStatus_t res = pal_fsFtell(&file_handle->file, &current_pos);
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_cmac_skip_to() - pal_fsFtell() failed with pal_status = 0x%x", (unsigned int)res);
+        return  ESFS_ERROR;
+    }
+
+    // Iterate over the rest of file in chunks to calculate the cmac
+    // buffer will contain only data read form the file
+    for (int32_t i = to - current_pos; i > 0; i -= ESFS_READ_CHUNK_SIZE_IN_BYTES)
+    {
+        // Read a chunk
+        // Here we read the file as is - plain text or encrypted
+        uint8_t buffer[ESFS_READ_CHUNK_SIZE_IN_BYTES];
+        size_t num_bytes;
+        esfs_result_e res = esfs_cmac_read(file_handle, buffer, PAL_MIN(i, ESFS_READ_CHUNK_SIZE_IN_BYTES), &num_bytes);
+        if (res != ESFS_SUCCESS || num_bytes == 0)
+        {
+            tr_err("esfs_cmac_skip_to() failed  num_bytes bytes = %zu", num_bytes);
+            return  ESFS_ERROR;
+        }
+     }
+    return  ESFS_SUCCESS;
+}
+
+// Helper function to terminate a cmac run and return the resulting cmac.
+// Parameters :
+// file_handle - [IN]   A pointer to a file handle for which we calculate the cmac.
+// pcmac       - [OUT]  A pointer to a buffer into which the cmac will be written. It must be at least ESFS_CMAC_SIZE_IN_BYTES.
+// Return     : ESFS_SUCCESS on success. Error code otherwise
+static esfs_result_e esfs_cmac_finish(esfs_file_t *file_handle, unsigned char *pcmac)
+{
+    size_t num_bytes;
+
+    // Sets file_handle->signature_ctx to 0 on success
+    palStatus_t res = pal_CMACFinish(&file_handle->signature_ctx, pcmac, &num_bytes);
+    if(res != PAL_SUCCESS)
+    {
+        tr_err("esfs_finish_cmac() - pal_CMACFinish() failed with pal_status = 0x%x", (unsigned int)res);
+        return  ESFS_ERROR;
+    }
+    return  ESFS_SUCCESS;
+}
+
+// Helper function to compare the passed cmac against the one in the file and to the one in the file descriptor
+// and then return the file position in the passed value.
+// Updates the file position.
+// Parameters :
+// file_handle - [IN]   A pointer to a file handle for which we check the cmac.
+// pcmac       - [IN]   A pointer to a buffer containing the cmac that will be compared. It must be at least ESFS_CMAC_SIZE_IN_BYTES.
+// position    - [IN]   The absolute position from the start of the file to which we restore the file position.
+// Return     : ESFS_SUCCESS on success. Error code otherwise.
+static esfs_result_e esfs_cmac_check_and_restore(esfs_file_t *file_handle, unsigned char *pcmac, int32_t position)
+{
+    // Read the signature from the file
+    unsigned char file_cmac[ESFS_CMAC_SIZE_IN_BYTES];
+    size_t num_bytes;
+    palStatus_t res = pal_fsFread(&file_handle->file, &file_cmac[0], ESFS_CMAC_SIZE_IN_BYTES, &num_bytes);
+    if (res != PAL_SUCCESS || num_bytes != ESFS_CMAC_SIZE_IN_BYTES)
+    {
+        tr_err("esfs_cmac_check_and_restore() - pal_fsFread() failed with pal result = 0x%x and num_bytes bytes = %zu", (unsigned int)res, num_bytes);
+        return ESFS_ERROR;
+    }
+    // Compare the cmac that we read from the file with the one that is passed and check it against
+    // the one recorded in esfs_open in order to verify that the file is the same as the one that was opened.
+    if(memcmp(&file_cmac[0], pcmac, ESFS_CMAC_SIZE_IN_BYTES) != 0 ||
+            memcmp(&file_cmac[0], &file_handle->cmac[0], ESFS_CMAC_SIZE_IN_BYTES) != 0)
+    {
+        tr_err("esfs_cmac_check_and_restore() - cmac that we read from the file does not match the one that we calculated");
+        return ESFS_CMAC_DOES_NOT_MATCH;
+    }
+
+    // Set the file position to the byte indicated by position.
+    res = pal_fsFseek(&file_handle->file, position, PAL_FS_OFFSET_SEEKSET);
+    if(res != PAL_SUCCESS)
+    {
+        tr_err("esfs_cmac_check_and_restore() - pal_fsFseek() failed with pal status 0x%x", (unsigned int)res);
+        return ESFS_ERROR;
+    }
+
+    return  ESFS_SUCCESS;
+}
+
+//Function   : esfs_memcpy_reverse
+//
+//Description: This function copies the first <len_bytes> bytes from input buffer <src_ptr> to output buffer <dest_ptr> in
+//             reversed order (e.g. '1' '2' '3' data array will be copied as '3' '2' '1').
+//             Note: The function assumes that the memory areas of the input buffers src_ptr and dest_ptr do not overlap.
+//
+//Parameters : dest_ptr  - [IN / OUT] A pointer to the destination buffer to which bytes will be copied.
+//             src_ptr   - [IN]       A pointer to the source buffer from which bytes will be copied.
+//             len_bytes - [IN]       Number of bytes to be copied.
+//
+//Return     : A pointer to the output buffer <dest_ptr>
+static void *esfs_memcpy_reverse(void *dest_ptr, const void *src_ptr, uint32_t len_bytes)
+{
+    uint8_t       *tmp_dest_ptr = (uint8_t *)dest_ptr;
+    const uint8_t *tmp_src_ptr  = (const uint8_t *)src_ptr;
+
+
+    // Make the reverse copy
+    while(len_bytes > 0)
+    {
+        *(tmp_dest_ptr++) = *(tmp_src_ptr + len_bytes - 1);
+        len_bytes--;
+    }
+
+    return dest_ptr;
+}
+
+//Function   : esfs_calc_file_pos_for_aes
+//
+//Description: This function calculates the file position for the purpose of AES encrypt / decrypt:
+//             The returned position is relative to the beginning of the encrypted data.
+//             The file is encrypted starting from the meta data part (the meta data values).
+//
+//Parameters : file_handle - [IN]  A pointer to a file handle on which we calculate the position.
+//             position    - [OUT] A pointer to size_t to be filled in with the returned position.
+//
+//Return     : ESFS_SUCCESS on success. Error code otherwise
+static esfs_result_e esfs_calc_file_pos_for_aes(esfs_file_t *file_handle, size_t *position)
+{
+    palStatus_t pal_status = PAL_SUCCESS;
+
+    size_t non_encrypt_size = 0;
+
+
+    *position = 0;
+
+    // Get current position inside the file
+    pal_status = pal_fsFtell( &(file_handle->file), (int32_t *)position );
+
+    if(pal_status != PAL_SUCCESS)
+    {
+        tr_err("esfs_calc_file_pos_for_aes() - pal_fsFtell() failed with pal_status = 0x%x", (unsigned int)pal_status);
+        return ESFS_ERROR;
+    }
+
+    // Calculate non_encrypt_size to be subtracted from position
+    non_encrypt_size = esfs_not_encrypted_file_header_size(file_handle);
+
+    if(*position < non_encrypt_size)
+    {
+        tr_err("esfs_calc_file_pos_for_aes() - Error. Position is in non encrypted part.");
+        return ESFS_ERROR;
+    }
+
+
+    *position -= non_encrypt_size;
+
+
+    return ESFS_SUCCESS;
+}
+
+
+//Function   : esfs_set_counter_in_iv_by_file_pos
+//
+//Description: This function fills in the last 8 bytes of the IV [iv128_arr] with the counter calculated according to
+//             the input position.
+//
+//Parameters : position  - [IN]     The position in the file when count starts from the encrypted data part (the meta data values).
+//             iv128_arr - [IN/OUT] A 16 bytes buffer holding the IV.
+//                                  First 8 bytes contain the NONCE, and last 8 bytes will be filled in with the counter.
+//
+//Return     : ESFS_SUCCESS on success. Error code otherwise
+static void esfs_set_counter_in_iv_by_file_pos(size_t position, uint8_t *iv128_arr)
+{
+    uint64_t counter = 0;
+
+
+    // Calculate counter part of IV
+    counter = (uint64_t)(position / ESFS_AES_BLOCK_SIZE_BYTES);
+
+
+    // Copy the counter part to the IV
+#if BIG__ENDIAN == 1
+    memcpy(iv128_arr + ESFS_AES_COUNTER_INDEX_IN_IV, &counter, ESFS_AES_COUNTER_SIZE_BYTES);
+#else
+    esfs_memcpy_reverse(iv128_arr + ESFS_AES_COUNTER_INDEX_IN_IV, &counter, ESFS_AES_COUNTER_SIZE_BYTES);
+#endif
+}
+
+
+//Function   : esfs_aes_enc_dec_by_file_pos
+//
+//Description: This function encrypts / decrypts data using AES-CTR.
+//             This is the basic function used for AES encrypt / decrypt.
+//             Due to the nature of AES-CTR which works on blocks, special handling is required in case the data in the file is not
+//             on block boundaries. In this case we encrypt / decrypt this "partial block data" in a temporal buffer after copying
+//             the data to the corresponding index inside this buffer. The rest of the data is being encrypted / decrypted normally.
+//
+//Parameters : aes_ctx     - [IN]  The per-initiated AES context.
+//             buf_in      - [IN]  A buffer containing to data to be encrypted / decrypted.
+//             buf_out     - [OUT] A buffer to be filled in with the encrypted / decrypted data.
+//             len_bytes   - [IN]  Number of bytes to encrypt / decrypt.
+//             position    - [IN]  The position in the file when count starts from the encrypted data part (the meta data values).
+//             nonce64_ptr - [IN]  An 8 bytes buffer holding the NONCE part of the IV.
+//
+//Return     : ESFS_SUCCESS on success. Error code otherwise
+static esfs_result_e esfs_aes_enc_dec_by_file_pos( palAesHandle_t  aes_ctx,
+                                                   const uint8_t  *buf_in,
+                                                   uint8_t        *buf_out,
+                                                   size_t          len_bytes,
+                                                   size_t          position,
+                                                   uint8_t        *nonce64_ptr
+                                                 )
+{
+    palStatus_t pal_status = PAL_SUCCESS;
+
+    uint8_t prev_remainder     = 0;  // Size in bytes of partial block PREVIOUSLY encrypted / decrypted
+    uint8_t partial_block_size = 0;  // Size in bytes of partial block for NEXT encrypt / decrypt
+
+    uint8_t partial_block_size_temp = 0;
+
+    uint8_t partial_block_in[ESFS_AES_BLOCK_SIZE_BYTES]  = {0}; // Will contain data for next partial encrypt / decrypt
+    uint8_t partial_block_out[ESFS_AES_BLOCK_SIZE_BYTES] = {0};
+
+    uint8_t iv_arr[ESFS_AES_IV_SIZE_BYTES] = {0};   // Will contain nonce [bytes 0 - 7] and counter [bytes 8 - 15]
+
+
+//    -------- partial_block_in:  Size = block_size [16 bytes]
+//    |
+//    |
+//   \|/
+//
+//    -----------------------------------------------------------------------------------------
+//    |                      |                                            |                   |
+//    |  0  ...           0  |         Data copied form buf_in            |  0  ...        0  |
+//    |                      |                                            |                   |
+//    -----------------------------------------------------------------------------------------
+//               ^                               ^                                ^
+//               |                               |                                |
+//               |                               |                                |
+//               |                               |                                |
+//        Size: prev_remainder                   |                          Size: might be 0
+//                                               |
+//                                               |
+//                                       Size: partial_block_size
+//                                       (might consume the buffer till its end)
+
+
+    prev_remainder = (position % ESFS_AES_BLOCK_SIZE_BYTES);
+
+    partial_block_size_temp = ESFS_AES_BLOCK_SIZE_BYTES - prev_remainder;
+    partial_block_size      = PAL_MIN(partial_block_size_temp, len_bytes);
+
+    // Prepare partial_block_in: Copy data for next encrypt / decrypt from buf_in to partial_block_in
+    memcpy(partial_block_in + prev_remainder, buf_in, partial_block_size);
+
+    // Prepare iv_arr: Copy nonce into bytes [0 - 7] of IV buffer
+    memcpy(iv_arr, nonce64_ptr, ESFS_AES_NONCE_SIZE_BYTES);
+
+    // Prepare iv_arr: Set counter in bytes [8 - 15] of IV buffer
+    esfs_set_counter_in_iv_by_file_pos(position, iv_arr);
+
+
+    // Encrypt / decrypt partial block [run on entire block, and copy later only desired part)
+    pal_status = pal_aesCTRWithZeroOffset(aes_ctx, partial_block_in, partial_block_out, ESFS_AES_BLOCK_SIZE_BYTES, iv_arr);
+
+    if(pal_status != PAL_SUCCESS)
+    {
+        tr_err("esfs_aes_enc_dec_by_file_pos() - pal_aesCTRWithZeroOffset() failed with pal_status = 0x%x", (unsigned int)pal_status);
+        return ESFS_ERROR;
+    }
+
+    // Copy partial_block_out to buf_out
+    memcpy(buf_out, partial_block_out + prev_remainder, partial_block_size);
+
+
+    // Encrypt / decrypt the rest of the data
+    if(len_bytes > partial_block_size)
+    {
+        // Set updated counter in bytes [8 - 15] of IV buffer
+        esfs_set_counter_in_iv_by_file_pos(position + partial_block_size, iv_arr);
+
+        pal_status = pal_aesCTRWithZeroOffset(aes_ctx, buf_in + partial_block_size, buf_out + partial_block_size, len_bytes - partial_block_size, iv_arr);
+
+        if(pal_status != PAL_SUCCESS)
+        {
+            tr_err("esfs_aes_enc_dec_by_file_pos() - pal_aesCTRWithZeroOffset() failed with pal_status = 0x%x", (unsigned int)pal_status);
+            return ESFS_ERROR;
+        }
+    }
+
+
+    return ESFS_SUCCESS;
+}
+
+
+//Function   : esfs_read_and_decrypt
+//
+//Description: This function reads encrypted data from a file, decrypts it, and writes it into a buffer.
+//
+//Parameters : file_handle    - [IN]  A pointer to a file handle from which we read data.
+//             buffer         - [IN]  The buffer to fill in with decrypted file data.
+//             bytes_to_read  - [IN]  Number of bytes to read from the file.
+//             read_bytes_ptr - [OUT] A pointer to size_t to be filled in with number of bytes actually read from the file.
+//
+//Return     : ESFS_SUCCESS on success. Error code otherwise
+static esfs_result_e esfs_read_and_decrypt(esfs_file_t *file_handle, void *buffer, size_t bytes_to_read, size_t *read_bytes_ptr)
+{
+    esfs_result_e result     = ESFS_SUCCESS;
+
+    size_t position = 0;
+
+
+    // Get file pointer position for AES - Must be done before calling pal_fsFread() which modifies the file pointer position
+    result = esfs_calc_file_pos_for_aes(file_handle, &position);
+
+    if(result != ESFS_SUCCESS)
+    {
+        tr_err("esfs_read_and_decrypt() - esfs_calc_file_pos_for_aes() failed with status = 0x%x", result);
+        return result;
+    }
+
+
+    // Read file's encrypted data into buffer
+    result = esfs_cmac_read(file_handle, buffer, bytes_to_read, read_bytes_ptr );
+
+    if((result != ESFS_SUCCESS) || (*read_bytes_ptr != bytes_to_read))
+    {
+        tr_err("esfs_read_and_decrypt() - esfs_cmac_read() failed with ESFS_status = 0x%x", (unsigned int)result);
+        return ESFS_ERROR;
+    }
+
+
+    // AES decrypt in-place - decrypt the encrypted data inside buffer, into buffer [out parameter]
+    result = esfs_aes_enc_dec_by_file_pos(file_handle->aes_ctx, buffer, buffer, bytes_to_read, position, file_handle->nonce);
+
+    if(result != ESFS_SUCCESS)
+    {
+        tr_err("esfs_read_and_decrypt() - esfs_aes_enc_dec_by_file_pos() failed with status = 0x%x", (unsigned int)result);
+        return result;
+    }
+
+
+    return ESFS_SUCCESS;
+}
+
+
+//Function   : esfs_encrypt_fwrite_and_calc_cmac
+//
+//Description: This function takes a plain text buffer, encrypts it, writes the encrypted data to a file, and updates the
+//             CMAC signature.
+//
+//             Since we cannot modify the data of the input buffer (const), this operation cannot be done in-place, so we need
+//             to use another buffer for the encryption result. In order to avoid dynamically allocation, we use a buffer
+//             of size ESFS_AES_BUF_SIZE_BYTES statically allocated on the stack. This forces us to encrypt and write in a loop -
+//             each iteration encrypts and writes maximum size of ESFS_AES_BUF_SIZE_BYTES bytes.
+//
+//Parameters : buffer         - [IN]     The buffer to encrypt and write to the file.
+//             bytes_to_write - [IN]     The number of bytes to write.
+//             file_handle    - [IN]     A pointer to a file handle to which we write the data.
+//
+//Return     : ESFS_SUCCESS on success. Error code otherwise
+static esfs_result_e esfs_encrypt_fwrite_and_calc_cmac(const void *buffer, size_t bytes_to_write, esfs_file_t *file_handle)
+{
+    esfs_result_e result = ESFS_SUCCESS;
+
+    size_t position    = 0;
+    size_t remaining_bytes_to_write = bytes_to_write;
+
+    const uint8_t *buffer_tmp_ptr = (uint8_t *)buffer;  // Will point to the next reading point in buffer as we read it
+
+    uint8_t encrypted_data[ESFS_AES_BUF_SIZE_BYTES] = {0}; // Will hold encrypted data to be written to the file
+
+
+    if(buffer == NULL)
+    {
+        tr_err("esfs_encrypt_fwrite_and_calc_cmac() - Bad arguments error. Input buffer is NULL.");
+        return ESFS_ERROR;
+    }
+
+
+    // Get file pointer position for AES - Must be done before calling esfs_fwrite_and_calc_cmac() which modifies the file pointer position
+    result = esfs_calc_file_pos_for_aes(file_handle, &position);
+
+    if(result != ESFS_SUCCESS)
+    {
+        tr_err("esfs_encrypt_fwrite_and_calc_cmac() - esfs_calc_file_pos_for_aes failed with result=0x%x", result);
+        return result;
+    }
+
+
+    // On every iteration in the loop, encrypt ESFS_AES_BUF_SIZE_BYTES bytes, and write them to the file
+    while(remaining_bytes_to_write >= ESFS_AES_BUF_SIZE_BYTES)
+    {
+        // AES encrypt into encrypted_data
+        result = esfs_aes_enc_dec_by_file_pos(file_handle->aes_ctx, buffer_tmp_ptr, encrypted_data, ESFS_AES_BUF_SIZE_BYTES, position, file_handle->nonce);
+
+        if(result != ESFS_SUCCESS)
+        {
+            tr_err("esfs_encrypt_fwrite_and_calc_cmac() - esfs_aes_enc_dec_by_file_pos failed with result=0x%x", result);
+            return result;
+        }
+
+        // Write the encrypted data to the file
+        result = esfs_fwrite_and_calc_cmac(encrypted_data, ESFS_AES_BUF_SIZE_BYTES, file_handle);
+
+        if((result != ESFS_SUCCESS))
+        {
+            tr_err("esfs_encrypt_fwrite_and_calc_cmac() - esfs_fwrite_and_calc_cmac() status = 0x%x", (unsigned int)result);
+
+            // esfs_fwrite_and_calc_cmac() failed so we cannot be sure of the state of the file - mark the file as invalid
+            file_handle->file_invalid = 1;
+
+            return ESFS_ERROR;
+        }
+
+        position       += ESFS_AES_BUF_SIZE_BYTES;
+        buffer_tmp_ptr += ESFS_AES_BUF_SIZE_BYTES;
+
+        remaining_bytes_to_write -= ESFS_AES_BUF_SIZE_BYTES;
+    }
+
+
+    // AES encrypt the leftover of buffer
+    if(remaining_bytes_to_write > 0)
+    {
+        // AES encrypt into encrypted_data
+        result = esfs_aes_enc_dec_by_file_pos(file_handle->aes_ctx, buffer_tmp_ptr, encrypted_data, remaining_bytes_to_write, position, file_handle->nonce);
+
+        if(result != ESFS_SUCCESS)
+        {
+            tr_err("esfs_encrypt_fwrite_and_calc_cmac() - esfs_aes_enc_dec_by_file_pos failed with result=0x%x", result);
+            return result;
+        }
+
+
+        // Write the encrypted data to the file
+        result = esfs_fwrite_and_calc_cmac(encrypted_data, remaining_bytes_to_write, file_handle);
+
+        if((result != ESFS_SUCCESS))
+        {
+            tr_err("esfs_encrypt_fwrite_and_calc_cmac() - esfs_fwrite_and_calc_cmac() status = 0x%x", (unsigned int)result);
+
+            // esfs_fwrite_and_calc_cmac() failed so we cannot be sure of the state of the file - mark the file as invalid
+            file_handle->file_invalid = 1;
+
+            return ESFS_ERROR;
+        }
+    }
+
+    return ESFS_SUCCESS;
+}
+
+
+esfs_result_e esfs_reset(void)
+{
+    esfs_result_e result = ESFS_SUCCESS;
+    palStatus_t pal_result = PAL_SUCCESS;
+    char dir_path[MAX_FULL_PATH_SIZE] = { 0 };
+    tr_info("esfs_reset - enter");
+    pal_result = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, dir_path);
+    if (pal_result != PAL_SUCCESS)
+    {
+        tr_err("esfs_reset() - pal_fsGetMountPoint() for working directory failed with pal_status = 0x%x", (unsigned int)pal_result);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    strncat(dir_path, "/" ESFS_WORKING_DIRECTORY, sizeof(ESFS_WORKING_DIRECTORY));
+
+    // delete the files in working dir
+    pal_result = pal_fsRmFiles(dir_path);
+    // the use case is that esfs folder may not exist
+    if ((pal_result != PAL_SUCCESS) && (pal_result != PAL_ERR_FS_NO_FILE) && (pal_result != PAL_ERR_FS_NO_PATH))
+    {
+        tr_err("esfs_reset() - pal_fsRmFiles(ESFS_WORKING_DIRECTORY) failed with pal_status = 0x%x", (unsigned int)pal_result);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    // delete working directory
+    pal_result = pal_fsRmDir(dir_path);
+    if (pal_result != PAL_SUCCESS)
+    {
+        // Any error apart from dir not exist returns error.
+        if ((pal_result != PAL_ERR_FS_NO_FILE) && (pal_result != PAL_ERR_FS_NO_PATH))
+        {
+            tr_err("esfs_reset() - pal_fsRmDir(ESFS_WORKING_DIRECTORY) failed with pal_status = 0x%x", (unsigned int)pal_result);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+    }
+
+    pal_result = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, dir_path);
+    if (pal_result != PAL_SUCCESS)
+    {
+
+        tr_err("esfs_reset() - pal_fsGetMountPoint() for backup directory failed with pal_status = 0x%x", (unsigned int)pal_result);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    strncat(dir_path, "/" ESFS_BACKUP_DIRECTORY, sizeof(ESFS_BACKUP_DIRECTORY));
+
+    // delete the files in backup dir
+    pal_result = pal_fsRmFiles(dir_path);
+    // the use case is that esfs folder may not exist
+    if ((pal_result != PAL_SUCCESS) && (pal_result != PAL_ERR_FS_NO_FILE) && (pal_result != PAL_ERR_FS_NO_PATH))
+    {
+        tr_err("esfs_reset() - pal_fsRmFiles(ESFS_BACKUP_DIRECTORY) failed with pal_status = 0x%x", (unsigned int)pal_result);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    pal_result = pal_fsRmDir(dir_path);
+    if (pal_result != PAL_SUCCESS)
+    {
+        // Any error apart from dir not exist returns error.
+        if ((pal_result != PAL_ERR_FS_NO_FILE) && (pal_result != PAL_ERR_FS_NO_PATH))
+        {
+            tr_err("esfs_reset() - pal_fsRmDir(ESFS_BACKUP_DIRECTORY) failed with pal_status = 0x%x", (unsigned int)pal_result);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+    }
+
+    if (esfs_finalize() != ESFS_SUCCESS)
+    {
+        tr_err("esfs_reset() - esfs_finalize() failed");
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    if (esfs_init() != ESFS_SUCCESS)
+    {
+        tr_err("esfs_reset() - esfs_init() failed");
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    return ESFS_SUCCESS;
+
+errorExit:
+    return result;
+}
+
+
+esfs_result_e esfs_factory_reset(void) {
+    palStatus_t   pal_result = PAL_SUCCESS;
+    esfs_result_e result = ESFS_SUCCESS;
+    esfs_file_t file_handle = { 0 };
+    char working_dir_path[MAX_FULL_PATH_SIZE] = { 0 };
+    char full_path_backup_dir[MAX_FULL_PATH_SIZE] = { 0 };
+	bool is_single_partition = true;
+	
+    tr_info("esfs_factory_reset - enter");
+    pal_result = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, full_path_backup_dir);
+    if (pal_result != PAL_SUCCESS)
+    {
+        tr_err("esfs_factory_reset() - pal_fsGetMountPoint() for backup directory failed with pal_status = 0x%x", (unsigned int)pal_result);
+        return ESFS_ERROR;
+    }
+
+    strncat(full_path_backup_dir, "/" ESFS_BACKUP_DIRECTORY "/" FACTORY_RESET_DIR, sizeof(ESFS_BACKUP_DIRECTORY) + sizeof(FACTORY_RESET_DIR));
+    // Create the factory reset subfolder - FR
+    pal_result = pal_fsMkDir(full_path_backup_dir);
+    if (pal_result != PAL_SUCCESS)
+    {
+        // Any error apart from file exist returns error.
+        if (pal_result != PAL_ERR_FS_NAME_ALREADY_EXIST)
+        {
+            tr_err("esfs_factory_reset() - pal_fsMkDir(ESFS_BACKUP_DIRECTORY/FACTORY_RESET_DIR) failed with pal_status = 0x%x", (unsigned int)pal_result);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+    }
+
+    strncat(full_path_backup_dir, "/" FACTORY_RESET_FILE, sizeof(FACTORY_RESET_FILE));
+    // Create the fr_on flag file
+    pal_result = pal_fsFopen(full_path_backup_dir, PAL_FS_FLAG_READWRITEEXCLUSIVE, &(file_handle.file));
+
+    // (res == PAL_SUCCESS) : factory reset is called on the first time
+    // (res == PAL_ERR_FS_NAME_ALREADY_EXIST) : factory reset is called again after it was failed 
+    // on the first time and therefore the file exists
+    if ((pal_result != PAL_SUCCESS) && (pal_result != PAL_ERR_FS_NAME_ALREADY_EXIST))
+    {
+        tr_err("esfs_factory_reset() - unexpected filesystem behavior pal_fsFopen() failed with pal_status = 0x%x", (unsigned int)pal_result);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    // close the file only if we opened it
+    if (pal_result == PAL_SUCCESS)
+    {
+        pal_result = pal_fsFclose(&(file_handle.file));
+        if (pal_result != PAL_SUCCESS)
+        {
+            tr_err("esfs_factory_reset() - unexpected filesystem behavior pal_fsFclose() failed with pal_status = 0x%x", (unsigned int)pal_result);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+    }
+
+    pal_result = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, working_dir_path);
+    if (pal_result != PAL_SUCCESS)
+    {
+        tr_err("esfs_factory_reset() - pal_fsGetMountPoint() for working directory failed with pal_status = 0x%x", (unsigned int)pal_result);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    // Check if there is a single partition by comparing the primary and secondary mount points.
+    // This is the only reliable way to do it, since the logic that determines the number of partitions is
+    // hidden behind the PAL API.
+    pal_result = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, full_path_backup_dir);
+    if (pal_result != PAL_SUCCESS)
+    {
+        tr_err("esfs_factory_reset() - pal_fsGetMountPoint() for backup directory failed with pal_status = 0x%x", (unsigned int)pal_result);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+    is_single_partition = (strcmp(working_dir_path,full_path_backup_dir) == 0);
+
+    strncat(working_dir_path, "/" ESFS_WORKING_DIRECTORY, sizeof(ESFS_WORKING_DIRECTORY));
+
+    // We can only format the working folder if it is dedicated for exclusive use of esfs and
+    // it is not the only partition that exists. The assumption here is that if it is the only partition,
+    // then the backup folder is also on that partition. In that case, formatting would remove the backup partition,
+    // which we do not want to do!
+    if (pal_fsIsPrivatePartition(PAL_FS_PARTITION_PRIMARY) && !is_single_partition)
+    {
+        pal_result = pal_fsFormat(PAL_FS_PARTITION_PRIMARY);
+        if (pal_result != PAL_SUCCESS)
+        {
+            tr_err("esfs_factory_reset() - pal_fsFormat() for working directory failed with pal_status = 0x%x", (unsigned int)pal_result);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+        pal_result = pal_fsMkDir(working_dir_path);
+        if (pal_result != PAL_SUCCESS)
+        {
+            tr_err("esfs_factory_reset() - pal_fsMkDir(ESFS_WORKING_DIRECTORY) failed with pal_status = 0x%x", (unsigned int)pal_result);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+    }
+    else
+    {
+        // delete the files in working dir
+        pal_result = pal_fsRmFiles(working_dir_path);
+        // the use case is that esfs folder may not exist
+        if ((pal_result != PAL_SUCCESS) && (pal_result != PAL_ERR_FS_NO_FILE) && (pal_result != PAL_ERR_FS_NO_PATH))
+        {
+            tr_err("esfs_factory_reset() - pal_fsRmFiles(ESFS_WORKING_DIRECTORY) failed with pal_status = 0x%x", (unsigned int)pal_result);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+    }
+
+    pal_result = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, full_path_backup_dir);
+    if (pal_result != PAL_SUCCESS)
+    {
+        tr_err("esfs_factory_reset() - pal_fsGetMountPoint() for backup directory failed with pal_status = 0x%x", (unsigned int)pal_result);
+        return ESFS_ERROR;
+    }
+    strncat(full_path_backup_dir, "/" ESFS_BACKUP_DIRECTORY, sizeof(ESFS_BACKUP_DIRECTORY));
+
+    pal_result = pal_fsCpFolder(full_path_backup_dir, working_dir_path);
+
+    if ((pal_result != PAL_SUCCESS) && (pal_result != PAL_ERR_FS_NO_FILE))
+    {
+        tr_err("esfs_factory_reset() - pal_fsCpFolder() from backup to working failed with pal_status = 0x%x", (unsigned int)pal_result);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    strncat(full_path_backup_dir, "/" FACTORY_RESET_DIR "/" FACTORY_RESET_FILE, sizeof(FACTORY_RESET_DIR) + sizeof(FACTORY_RESET_FILE));
+    // delete the flag file because factory reset flow ended successfully 
+    pal_result = pal_fsUnlink(full_path_backup_dir);
+    if (pal_result != PAL_SUCCESS)
+    {
+        tr_err("esfs_factory_reset() - pal_fsUnlink(ESFS_BACKUP_DIRECTORY/FACTORY_RESET_DIR/FACTORY_RESET_FILE) failed with pal_status = 0x%x", (unsigned int)pal_result);
+        result = ESFS_ERROR;
+        goto errorExit;
+     }
+
+    return ESFS_SUCCESS;
+
+errorExit:
+    return result;
+}
+
+// Internal function to read header information and check its' validity.
+// Checks the name given against the name written in the file.
+// Checks the version.
+// Initializes some fields of file_handle: blob_name_length, esf_mode
+// Assumes that the read position is at the start of the file.
+// CMAC is calculated.
+// Parameters :
+// name         [IN]  A pointer to an array of binary data that uniquely identifies the file.
+// name_length  [IN]  size in bytes of the name. The minimum is 1 and the maximum is ESFS_MAX_NAME_LENGTH.
+// file_handle  [IN]  A pointer to a file handle on which we calculate the position.
+// return esf_success - name matches;
+//                        ESFS_HASH_CONFLICT - name does not match
+//                        ESFS_WRONG_FILE_VERSION - version does not match
+//                        ESFS_ERROR - other problem
+// On ESFS_SUCCESS or ESFS_HASH_CONFLICT the read position is set after the name.
+// On failure the position is undefined.
+static esfs_result_e esfs_check_file_validity(const uint8_t* name, size_t name_length, esfs_file_t *file_handle)
+{
+    esfs_result_e result = ESFS_ERROR;
+
+    // Read the version
+    uint16_t version;
+    size_t num_bytes;
+    result  = esfs_cmac_read(file_handle, &version , sizeof(version), &num_bytes);
+    if (result != ESFS_SUCCESS || num_bytes != sizeof(version))
+    {
+        tr_err("esfs_check_file_validity() - esfs_cmac_read() failed with ESFS result = 0x%x and num_bytes bytes = %zu",
+            (unsigned int)result, num_bytes);
+        goto errorExit;
+    }
+    // Check that the files version is the same as the source code version.
+    if(version != ESFS_FILE_FORMAT_VERSION)
+    {
+        tr_err("esfs_check_file_validity() - invalid version: failed with version = %u instead of %u", (unsigned int)version, (unsigned int)ESFS_FILE_FORMAT_VERSION);
+        result = ESFS_INVALID_FILE_VERSION;
+        goto errorExit;
+    }
+
+    // Read the mode
+    result = esfs_cmac_read(file_handle, (void *)( &file_handle->esfs_mode ), sizeof(file_handle->esfs_mode), &num_bytes);
+    if (result != ESFS_SUCCESS || num_bytes != sizeof(file_handle->esfs_mode))
+    {
+        tr_err("esfs_check_file_validity() mode -  failed num_bytes bytes = %zu", num_bytes);
+        goto errorExit;
+    }
+    // The mode is not used further in the opening process, so no further checks need be performed as cmac check will detect any
+    // tampering.
+
+    // Read the name length
+    result = esfs_cmac_read(file_handle, (void *)( &file_handle->blob_name_length ), sizeof(file_handle->blob_name_length), &num_bytes);
+    if (result != ESFS_SUCCESS || num_bytes != sizeof(file_handle->blob_name_length))
+    {
+        tr_err("esfs_check_file_validity() name length- esfs_cmac_read() failed with  result = 0x%x and num_bytes bytes = %zu",
+            (unsigned int)result, num_bytes);
+        goto errorExit;
+    }
+    // Check that the name in the file is the same length as the one given. It cannot be greater than ESFS_MAX_NAME_LENGTH
+    // because that is checked on entry to the function.
+    if (name_length != file_handle->blob_name_length)
+    {
+        tr_err("esfs_check_file_validity() - name length conflict");
+        // The hash of the name conflicts with the hash of another name.
+        result = ESFS_HASH_CONFLICT;
+        goto errorExit;
+    }
+    // Check the name chunk by chunk
+    for (int i = name_length; i > 0; i -= ESFS_READ_CHUNK_SIZE_IN_BYTES)
+    {
+        // Read a chunk
+        char buffer[ESFS_READ_CHUNK_SIZE_IN_BYTES];
+        result = esfs_cmac_read(file_handle, (void *)buffer, PAL_MIN(i, ESFS_READ_CHUNK_SIZE_IN_BYTES), &num_bytes);
+        if (result != ESFS_SUCCESS || num_bytes == 0)
+        {
+            tr_err("esfs_check_file_validity() - read name failed with ESFS result = 0x%x and num_bytes bytes = %zu",
+                (unsigned int)result, num_bytes);
+            goto errorExit;
+        }
+        // Check that the chunk matches
+        //tr_info("Comparing %s (%d bytes) name_length=%d", name, (int )num_bytes,(int )name_length);
+        if (memcmp(buffer, name, num_bytes) != 0)
+        {
+            tr_err("esfs_check_file_validity() - esfs hash conflict : The hash of the name conflicts with the hash of another name");
+            // The hash of the name conflicts with the hash of another name.
+            result = ESFS_HASH_CONFLICT;
+            goto errorExit;
+        }
+        // Advance past what we just checked.
+        name += num_bytes;
+    }
+    return ESFS_SUCCESS;
+errorExit:
+    return result;
+}
+
+// Internal function to check the name against the name written in the file.
+// Assume that the read position is set to before the name length.
+// Parameters :
+//             fd -      [IN]  A pointer to a file descriptor.
+//             file_size [OUT] A pointer to a value into which the file size is returned.
+// return esf_success - name matches;
+//                        ESFS_HASH_CONFLICT - name does not match ;
+//                        ESFS_ERROR - other problem
+// On ESFS_SUCCESS or ESFS_HASH_CONFLICT the read position is set after the name.
+// On failure the position is undefined.
+
+// Helper function
+// Restores current position unless it fails.
+// On failure the position is undefined.
+static palStatus_t esfs_get_physical_file_size(palFileDescriptor_t* fd, int32_t *file_size)
+{
+    palStatus_t res;
+
+    // Get current position
+    int32_t current_pos;
+    res = pal_fsFtell(fd, &current_pos);
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_get_physical_file_size() - pal_fsFtell() failed with pal_status = 0x%x", (unsigned int)res);
+        goto errorExit;
+    }
+    // Seek to end of file
+    res = pal_fsFseek(fd, 0, PAL_FS_OFFSET_SEEKEND);
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_get_physical_file_size() - pal_fsFseek() failed with pal_status = 0x%x", (unsigned int)res);
+        goto errorExit;
+    }
+    // Get new position
+    res = pal_fsFtell(fd, file_size);
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_get_physical_file_size() - pal_fsFtell() failed with pal_status = 0x%x", (unsigned int)res);
+        goto errorExit;
+    }
+    // Restore old position
+    res = pal_fsFseek(fd, current_pos, PAL_FS_OFFSET_SEEKSET);
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_get_physical_file_size() - pal_fsFseek() failed with pal_status = 0x%x", (unsigned int)res);
+        goto errorExit;
+    }
+
+errorExit:
+    return res;
+}
+
+// Copy one file to another.
+// Parameters :
+//             src_file  - [IN] A pointer to a string containing the source file name.
+//             src_file  - [IN] A pointer to a string containing the destination file name.
+// Return     : ESFS_SUCCESS on success. Error code otherwise
+static esfs_result_e esfs_copy_file(const char *src_file, const char *dst_file)
+{
+    bool is_src_file_opened = false;
+    bool is_dst_file_opened = false;
+    esfs_file_t file_handle = { 0 };
+    esfs_file_t file_handle_copy = { 0 };
+    esfs_result_e result = ESFS_ERROR;
+    palStatus_t res = PAL_SUCCESS;
+    size_t bytes_to_read = ESFS_FILE_COPY_CHUNK_SIZE;
+    size_t num_bytes_read = 0;
+    size_t num_bytes_write = 0;
+    uint8_t buffer[ESFS_FILE_COPY_CHUNK_SIZE] = {0};
+    int32_t file_size = 0;
+    int32_t copied_bytes = 0;
+    // Open src file read only mode
+    res = pal_fsFopen(src_file, PAL_FS_FLAG_READONLY, &(file_handle.file));
+    if (res != PAL_SUCCESS)
+    {
+        // File cannot be opened so return an error
+        tr_err("esfs_copy_file() - pal_fsFopen() src file failed with pal_status = 0x%x", (unsigned int)res);
+        result = ESFS_NOT_EXISTS;
+        goto errorExit;
+    }
+    is_src_file_opened = true;
+    // Open for reading and writing exclusively, If the file already exists, trunced file
+    res = pal_fsFopen(dst_file, PAL_FS_FLAG_READWRITETRUNC, &(file_handle_copy.file));
+    if (res != PAL_SUCCESS)
+    {
+        // File cannot be opened so return an error
+        tr_err("esfs_copy_file() - pal_fsFopen() dst file failed with pal_status = 0x%x", (unsigned int)res);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+    is_dst_file_opened = true;
+
+    res = esfs_get_physical_file_size(&(file_handle.file), &file_size);
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_copy_file() - esfs_get_physical_file_size() failed with pal_status = 0x%x", (unsigned int)res);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+    while (copied_bytes < file_size)
+    {
+        if (copied_bytes + (int32_t)bytes_to_read > file_size)
+        {
+            bytes_to_read = file_size - copied_bytes;
+        }
+        res = pal_fsFread(&(file_handle.file), buffer, bytes_to_read, &num_bytes_read);
+        if (res != PAL_SUCCESS)
+        {
+            tr_err("esfs_copy_file() - pal_fsFread() failed with pal_status = 0x%x", (unsigned int)res);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+
+        res = pal_fsFwrite(&(file_handle_copy.file), buffer, bytes_to_read, &num_bytes_write);
+        if ((res != PAL_SUCCESS) || (num_bytes_write != bytes_to_read))
+        {
+            tr_err("esfs_copy_file() - pal_fsFwrite() failed with pal result = 0x%x and num_bytes_write bytes = %zu",
+                (unsigned int)res, num_bytes_write);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+
+        copied_bytes += bytes_to_read;
+            
+    }
+
+
+    res = pal_fsFclose(&(file_handle.file));
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_copy_file() - pal_fsFclose() for src file failed with pal_status = 0x%x", (unsigned int)res);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+    res = pal_fsFclose(&(file_handle_copy.file));
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_copy_file() - pal_fsFclose() for dst file failed with pal_status = 0x%x", (unsigned int)res);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+    return ESFS_SUCCESS;
+
+errorExit:
+    if (is_src_file_opened)
+    {
+        // we will not delete the src file
+        pal_fsFclose(&(file_handle.file));
+    }
+
+    if (is_dst_file_opened)
+    {
+        pal_fsFclose(&(file_handle_copy.file));
+        // Clean up if possible. Ignore return value.
+        (void)pal_fsUnlink(dst_file);
+    }
+    return result;
+}
+
+
+
+
+// Internal function to create a new file and open it for writing.
+// Does not return error if file exists.
+// Keep all the conditions that allow the file creation in a single function, esfs_create, while the
+// esfs_create_internal will concentrate on file creation mechanics.
+// Parameters:
+// name          - [IN]    A pointer to an array of binary data that uniquely identifies the file.
+// name_length   - [IN]    size in bytes of the name. The minimum is 1 and the maximum is ESFS_MAX_NAME_LENGTH.
+// meta_data     - [IN]    A pointer to an array of TLVs structures with meta_data_qty members
+// meta_data_qty - [IN]    number of tlvs in the array pointed by meta_data parameter. Minimum is 0 maximum is ESFS_MAX_TYPE_LENGTH_VALUES
+// esfs_mode     - [IN]    a bit map combination of values from enum EsfsMode.
+// file_handle   - [IN/OUT]  Pointer to the handle data structure into which to write the new handle.
+// returns ESFS_SUCCESS The file handle can be used in other esfs functions. It must be closed to release it.
+//          ESFS_ERROR - other problem
+static esfs_result_e esfs_create_internal( const uint8_t *name,
+                                           size_t name_length,
+                                           const esfs_tlv_item_t *meta_data,
+                                           size_t meta_data_qty,
+                                           uint16_t esfs_mode,
+                                           esfs_file_t *file_handle,
+                                           const char* full_path_to_create
+                                        )
+{
+    esfs_result_e result = ESFS_ERROR;
+
+    int32_t position = 0;
+    size_t i;
+    uint16_t file_created = 0;
+    uint16_t cmac_created = 0;
+	uint16_t u16 = ESFS_FILE_FORMAT_VERSION;
+
+
+    // Create the file.
+    // Note that we always overwrite any previous file.
+    palStatus_t res = pal_fsFopen(full_path_to_create, PAL_FS_FLAG_READWRITETRUNC, &file_handle->file);
+    if(res != PAL_SUCCESS)
+    {
+        // more informative message will be written after hash conflict will be implemented
+        tr_err("esfs_create_internal() - pal_fsFopen() failed with status 0x%x", (unsigned int)res);
+        goto errorExit;
+    }
+    file_created = 1;
+
+    if(esfs_cmac_start(file_handle) != ESFS_SUCCESS)
+    {
+        goto errorExit;
+    }
+    cmac_created = 1;
+
+    // Write the version
+    if(esfs_fwrite_and_calc_cmac(&u16, sizeof(u16), file_handle) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_create_internal() - esfs_fwrite_and_calc_cmac() for esfs version failed");
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    // Write the mode
+    if(esfs_fwrite_and_calc_cmac(&esfs_mode, sizeof(esfs_mode), file_handle) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_create_internal() - esfs_fwrite_and_calc_cmac() for esfs_mode failed");
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    // Header
+    // Write the name length
+    u16 = (uint16_t)name_length;
+    if(esfs_fwrite_and_calc_cmac(&u16, sizeof(u16), file_handle) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_create_internal() - esfs_fwrite_and_calc_cmac() for name_length failed");
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    // Write the name
+    if(esfs_fwrite_and_calc_cmac(name, name_length, file_handle) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_create_internal() - esfs_fwrite_and_calc_cmac() for name failed.");
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    // Write the AES nonce, whether the file is encrypted or not. This ensures that the file format is the same
+    // whether encrypted or not.
+    if ((file_handle->esfs_mode & ESFS_ENCRYPTED) != 0)
+    {
+        if(esfs_fwrite_and_calc_cmac((void *)(file_handle->nonce), ESFS_AES_NONCE_SIZE_BYTES, file_handle) != ESFS_SUCCESS)
+        {
+            tr_err("esfs_create_internal() - esfs_fwrite_and_calc_cmac() for AES nonce failed");
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+    }
+
+    // Write the Metadata header
+    // Write the number of items of meta data
+    u16 = (uint16_t)meta_data_qty;
+    if(esfs_fwrite_and_calc_cmac(&u16,sizeof(u16), file_handle) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_create_internal() - esfs_fwrite_and_calc_cmac() for number of items of meta data failed");
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    // If there is meta data
+    if(meta_data_qty != 0)
+    {
+        res = pal_fsFtell(&file_handle->file, &position);
+        if(res != PAL_SUCCESS)
+        {
+            tr_err("esfs_create_internal() - pal_fsFtell() failed with pal_status = 0x%x", (unsigned int)res);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+        position += (sizeof(file_handle->tlv_properties.tlv_items[0]) * meta_data_qty);
+        for(i = 0; i < meta_data_qty; i++ )
+        {
+            file_handle->tlv_properties.tlv_items[i].type = meta_data[i].type;
+            file_handle->tlv_properties.tlv_items[i].length_in_bytes = meta_data[i].length_in_bytes;
+            file_handle->tlv_properties.tlv_items[i].position = (uint16_t)position;
+            // Increment position for next iteration
+            position += meta_data[i].length_in_bytes;
+        }
+
+        // Write the metadata items
+        result = esfs_fwrite_and_calc_cmac(&file_handle->tlv_properties.tlv_items[0], sizeof(file_handle->tlv_properties.tlv_items[0])*meta_data_qty, file_handle);
+        if(result != ESFS_SUCCESS)
+        {
+            tr_err("esfs_create_internal() - esfs_fwrite_and_calc_cmac() for meta data items failed with esfs result = 0x%x", result);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+
+        // Set the number_of_items field here since it is in use later in this function
+        // when we calculate the file header size
+        file_handle->tlv_properties.number_of_items = meta_data_qty;
+
+        // Write the Metadata data values
+        // If encrypted esfs is requested (by the esfs_mode argument), then this part should be encrypted
+        for(i = 0; i < meta_data_qty; i++ )
+        {
+            if((file_handle->esfs_mode & ESFS_ENCRYPTED) != 0)
+            {
+                result = esfs_encrypt_fwrite_and_calc_cmac(meta_data[i].value, meta_data[i].length_in_bytes, file_handle);
+            }
+            else
+            {
+                result = esfs_fwrite_and_calc_cmac(meta_data[i].value, meta_data[i].length_in_bytes, file_handle);
+            }
+
+            if(result != ESFS_SUCCESS)
+            {
+                tr_err("esfs_create_internal() - esfs_fwrite_and_calc_cmac() for meta data item values failed with esfs result = 0x%x", result);
+                result = ESFS_ERROR;
+                goto errorExit;
+            }
+        }
+    }
+
+    file_handle->file_flag = ESFS_WRITE;
+
+    return ESFS_SUCCESS;
+
+errorExit:
+
+    if(file_created)
+    {
+        pal_fsFclose(&file_handle->file);
+        // Clean up if possible. Ignore return value.
+        (void)pal_fsUnlink(full_path_to_create);
+    }
+    if(cmac_created)
+    {
+        uint8_t key[ESFS_CMAC_SIZE_IN_BYTES];
+        // Clean up cmac. Ignore error.
+        (void)esfs_cmac_finish(file_handle, &key[0]);
+    }
+
+    return result;
+}
+
+//      ---------------------------------------------------------------
+//                              API Functions
+//      ---------------------------------------------------------------
+
+
+esfs_result_e esfs_create(const uint8_t *name, size_t name_length, const esfs_tlv_item_t *meta_data, size_t meta_data_qty, uint16_t esfs_mode, esfs_file_t *file_handle)
+{
+
+    palStatus_t   res    = PAL_SUCCESS;
+    esfs_result_e result = ESFS_ERROR;
+
+    bool is_aes_ctx_created = false;
+
+
+    // Verify that the structure is always packed to six bytes, since we read and write it as a whole.
+    PAL_ASSERT_STATIC(sizeof(esfs_tlvItem_t) == 6);
+
+    // Verify that the array is always packed without padding, since we read and write it as a whole.
+    PAL_ASSERT_STATIC(sizeof(esfs_tlvItem_t[ESFS_MAX_TYPE_LENGTH_VALUES]) == ESFS_MAX_TYPE_LENGTH_VALUES * sizeof(esfs_tlvItem_t));
+
+    tr_info("esfs_create - enter");
+
+    // Check parameters
+    if (!file_handle || !name || name_length == 0 || name_length > ESFS_MAX_NAME_LENGTH || meta_data_qty > ESFS_MAX_TYPE_LENGTH_VALUES)
+    {
+        tr_err("esfs_create() failed with bad parameters");
+        result = ESFS_INVALID_PARAMETER;
+        goto errorExit;
+    }
+
+    // Check the metadata parameter
+    for(size_t meta_data_index = 0; meta_data_index < meta_data_qty; meta_data_index++ )
+    {
+        if ((!meta_data[meta_data_index].value) || (meta_data[meta_data_index].length_in_bytes == 0))
+        {
+            tr_err("esfs_create() failed with bad parameters for metadata");
+            result = ESFS_INVALID_PARAMETER;
+            goto errorExit;
+        }
+    }
+
+    // If esfs is in encryption mode, make the required initializations
+    if((esfs_mode & ESFS_ENCRYPTED) != 0)
+    {
+        // ** Create AES context for AES encryption
+        res = pal_initAes( &(file_handle->aes_ctx) );
+
+        if(res != PAL_SUCCESS)
+        {
+            tr_err("esfs_create() - pal_initAes() failed with pal status 0x%x", (unsigned int)res);
+            result = ESFS_ERROR ;
+            goto errorExit;
+        }
+
+        is_aes_ctx_created = true;
+
+        // ** Get AES key from PAL
+        // Note: On each call, PAL should return the same 128 bits key
+        uint8_t aes_key[ESFS_AES_KEY_SIZE_BYTES]; // For AES encryption
+        res = pal_osGetDeviceKey(palOsStorageEncryptionKey128Bit, aes_key, ESFS_AES_KEY_SIZE_BYTES);
+
+        if(res != PAL_SUCCESS)
+        {
+            tr_err("esfs_create() - pal_osGetDeviceKey() failed with pal status 0x%x", (unsigned int)res);
+            result = ESFS_ERROR ;
+            goto errorExit;
+        }
+
+        // ** Assign generated AES key to AES context
+        res = pal_setAesKey( file_handle->aes_ctx,
+                             aes_key,
+                             ESFS_AES_KEY_SIZE_BITS,
+                             PAL_KEY_TARGET_ENCRYPTION
+                           );
+
+        if(res != PAL_SUCCESS)
+        {
+            tr_err("esfs_create() - pal_setAesKey() failed with pal status 0x%x", (unsigned int)res);
+            result = ESFS_ERROR ;
+            goto errorExit;
+        }
+
+        // ** Generate the AES nonce for AES usage
+        res = pal_osRandomBuffer(file_handle->nonce, ESFS_AES_NONCE_SIZE_BYTES);
+
+        if(res != PAL_SUCCESS)
+        {
+            tr_err("esfs_create() - pal_osRandomBuffer() failed with pal status 0x%x", (unsigned int)res);
+            result = ESFS_ERROR ;
+            goto errorExit;
+        }
+    }
+
+    // We set the blob_name_length field here because it is in use later in this function when we calculate the file header size.
+    // Since this field is also used to check the file handle validity [ esfs_validate() ] we set it to zero on an error exit.
+    file_handle->blob_name_length = name_length;
+
+    file_handle->esfs_mode = esfs_mode;
+
+    file_handle->file_invalid = 0;
+
+    file_handle->tlv_properties.number_of_items = 0;
+
+    // Indicate that there is not a signature context yet.
+    file_handle->signature_ctx = 0;
+
+    file_handle->data_size = 0;
+
+    if (esfs_get_name_from_blob(name, name_length, file_handle->short_file_name, ESFS_FILE_NAME_LENGTH) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_create() - esfs_get_name_from_blob() failed");
+        goto errorExit;
+    }
+
+    // Put working file name in file_full_path
+    char file_full_path[MAX_FULL_PATH_SIZE];
+    res = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, file_full_path);
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_create() - pal_fsGetMountPoint() for working directory failed with pal_status = 0x%x", (unsigned int)res);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+    strncat(file_full_path, "/" ESFS_WORKING_DIRECTORY "/", sizeof(ESFS_WORKING_DIRECTORY) + 1);
+    strncat(file_full_path, file_handle->short_file_name, ESFS_QUALIFIED_FILE_NAME_LENGTH - 1);
+
+
+    // Check if the file exists in the working directory (not acceptable)
+    // Note that this is just a check. We will only actually open the file later (in esfs_create_internal()).
+    res = pal_fsFopen(file_full_path, PAL_FS_FLAG_READONLY, &file_handle->file);
+    if (res == PAL_SUCCESS)
+    {
+        result = ESFS_EXISTS;
+        file_handle->esfs_mode = 0;
+        // result can be ESFS_HASH_CONFLICT or ESFS_WRONG_FILE_VERSION
+        // Check if there is a different name in the file
+        // Check that the name written inside the file is the same as that given. If not
+        // you should choose a different name.
+        esfs_result_e check_result = esfs_check_file_validity(name, name_length, file_handle);
+        if (check_result == ESFS_HASH_CONFLICT || check_result == ESFS_INVALID_FILE_VERSION)
+        {
+            result = check_result;
+        }
+        pal_fsFclose(&file_handle->file);
+        tr_err("esfs_create() - pal_fsFopen() for working dir file failed");
+        goto errorExit;
+    }
+
+    // If factory reset file then we make some checks
+    if (esfs_mode & (uint16_t)ESFS_FACTORY_VAL)
+    {
+        // Put backup folder name in file_full_path
+        res = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, file_full_path);
+        if (res != PAL_SUCCESS)
+        {
+            tr_err("esfs_create() - pal_fsGetMountPoint() for backup directory failed with pal_status = 0x%x", (unsigned int)res);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+        strncat(file_full_path, "/" ESFS_BACKUP_DIRECTORY, sizeof(ESFS_BACKUP_DIRECTORY));
+
+        // Create the esfs subfolder for backup
+        res = pal_fsMkDir(file_full_path);
+        if (res != PAL_SUCCESS)
+        {
+            // Any error apart from file exist returns error.
+            if (res != PAL_ERR_FS_NAME_ALREADY_EXIST)
+            {
+                tr_err("esfs_create() - pal_fsMkDir() for backup dir failed with pal status 0x%x", (unsigned int)res);
+                goto errorExit;
+            }
+        }
+
+        // Put backup file name in file_full_path
+        strcat(file_full_path, "/");
+        strncat(file_full_path, file_handle->short_file_name, ESFS_QUALIFIED_FILE_NAME_LENGTH - 1);
+
+        // Check if the file exists in esfs backup directory (acceptable unless there is a hash conflict for the name)
+        res = pal_fsFopen(file_full_path, PAL_FS_FLAG_READONLY, &file_handle->file);
+        if (res == PAL_SUCCESS)
+        {
+            file_handle->esfs_mode = 0;
+            // result can be ESFS_HASH_CONFLICT or ESFS_WRONG_FILE_VERSION
+            // Check if there is a different name in the file
+            // Check that the name written inside the file is the same as that given. If not
+            // you should choose a different name.
+            esfs_result_e check_result = esfs_check_file_validity(name, name_length, file_handle);
+
+            // Close the file.
+            pal_fsFclose(&file_handle->file);
+
+            if (check_result == ESFS_HASH_CONFLICT || check_result == ESFS_INVALID_FILE_VERSION)
+            {
+                tr_err("esfs_create() - esfs_check_file_validity() failed with status 0x%x", check_result);
+                result = check_result;
+                goto errorExit;
+            }
+            // It is OK for it to exist, so continue.
+        }
+    }
+
+    // Now we actually create the new file.
+    // file_full_path contains the correct location (working/backup)
+    result = esfs_create_internal(
+                                    name,
+                                    name_length,
+                                    meta_data,
+                                    meta_data_qty,
+                                    esfs_mode,
+                                    file_handle,
+                                    // Working or backup
+                                    file_full_path
+                                );
+    if(result != ESFS_SUCCESS)
+    {
+        goto errorExit;
+    }
+
+    return ESFS_SUCCESS;
+
+errorExit:
+
+    // Invalidate blob_name_length filed since it is used to check the file handle validity  [ esfs_validate() ]
+    if(file_handle != NULL)
+    {
+        file_handle->blob_name_length = 0;
+    }
+
+    if(is_aes_ctx_created)
+    {
+        pal_freeAes( &(file_handle->aes_ctx) );
+    }
+    return result;
+}
+
+esfs_result_e esfs_open(const uint8_t *name, size_t name_length, uint16_t *esfs_mode, esfs_file_t *file_handle)
+{
+    esfs_result_e result = ESFS_ERROR;
+    uint16_t file_opened = 0;
+    uint16_t cmac_created = 0;
+    bool is_aes_ctx_created = false;
+	palStatus_t res = PAL_SUCCESS;
+
+    tr_info("esfs_open - enter");
+    // Check parameters
+    if(!file_handle || !name || name_length == 0 || name_length > ESFS_MAX_NAME_LENGTH)
+    {
+        tr_err("esfs_open() failed with bad parameters");
+        result = ESFS_INVALID_PARAMETER;
+        goto errorExit;
+    }
+
+    char working_dir_path[MAX_FULL_PATH_SIZE];
+    res = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, working_dir_path);
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_open() - pal_fsGetMountPoint() for working directory failed with pal_status = 0x%x", (unsigned int)res);
+        return ESFS_ERROR;
+    }
+
+    strncat(working_dir_path, "/" ESFS_WORKING_DIRECTORY "/", sizeof(ESFS_WORKING_DIRECTORY) + 1);
+
+    // This is used to esfs_validate the file handle so we set it to zero here and only when open
+    // succeeds to the real value.
+    file_handle->blob_name_length = 0;
+
+    file_handle->file_invalid = 0;
+
+    memset(&file_handle->cmac[0], 0, sizeof(file_handle->cmac));
+
+    if(esfs_get_name_from_blob(name, name_length, file_handle->short_file_name, ESFS_FILE_NAME_LENGTH) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_open() - esfs_get_name_from_blob() failed");
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    strncat(working_dir_path, file_handle->short_file_name, ESFS_QUALIFIED_FILE_NAME_LENGTH - 1);
+
+   // Open the file read only
+    res = pal_fsFopen(working_dir_path, PAL_FS_FLAG_READONLY, &file_handle->file);
+    if(res != PAL_SUCCESS)
+    {
+        // tr_err("esfs_open() - pal_fsFopen() for working dir file failed with pal_status = 0x%x", (unsigned int)res);
+        // File cannot be opened so return an error
+        result = ESFS_NOT_EXISTS;
+        goto errorExit;
+    }
+
+     file_opened = 1;
+
+     if(esfs_cmac_start(file_handle) != ESFS_SUCCESS)
+     {
+         goto errorExit;
+     }
+     cmac_created = 1;
+
+    // Check that the name written inside the file is the same as that given
+    // Note: After this call, the read position will be set to the point after the "Name Blob"
+    result = esfs_check_file_validity(name, name_length, file_handle);
+    if(result != ESFS_SUCCESS)
+    {
+        // the requested file not exists, but exists file with the same short name
+        if (result == ESFS_HASH_CONFLICT)
+        {
+             result = ESFS_NOT_EXISTS;  		
+        }					    
+        tr_err("esfs_open() - esfs_check_file_validity() failed with status = 0x%x", result);
+        // File cannot be opened so return an error
+        goto errorExit;
+    }
+
+    if (esfs_mode)
+    {
+        *esfs_mode = file_handle->esfs_mode;    // file_handle->esfs_mode was set by esfs_check_file_validity()
+    }
+
+    // If esfs is in encryption mode, make the required initializations
+    if((file_handle->esfs_mode & ESFS_ENCRYPTED) != 0)
+    {
+        // ** Create AES context for AES decryption
+        res = pal_initAes( &(file_handle->aes_ctx) );
+
+        if(res != PAL_SUCCESS)
+        {
+            tr_err("esfs_open() - pal_initAes() failed with status 0x%x", (unsigned int)res);
+            result = ESFS_ERROR ;
+            goto errorExit;
+        }
+
+        is_aes_ctx_created = true;
+
+        // ** Get AES key from PAL
+        // Note: On each call, PAL should return the same 128 bits key
+        uint8_t aes_key[ESFS_AES_KEY_SIZE_BYTES];
+        res = pal_osGetDeviceKey(palOsStorageEncryptionKey128Bit, aes_key, ESFS_AES_KEY_SIZE_BYTES);
+
+        if(res != PAL_SUCCESS)
+        {
+            tr_err("esfs_open() - pal_osGetDeviceKey() failed with status 0x%x", (unsigned int)res);
+            result = ESFS_ERROR ;
+            goto errorExit;
+        }
+
+        // ** Assign generated AES key to AES context
+        res = pal_setAesKey( file_handle->aes_ctx,
+                             aes_key,
+                             ESFS_AES_KEY_SIZE_BITS,
+                             PAL_KEY_TARGET_ENCRYPTION
+                           );
+
+        if(res != PAL_SUCCESS)
+        {
+            tr_err("esfs_open() - pal_setAesKey() failed with status 0x%x", (unsigned int)res);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+
+    }
+
+    size_t num_bytes;
+
+    // ** Read the AES nonce into file_handle->nonce
+    if ((file_handle->esfs_mode & ESFS_ENCRYPTED) != 0)
+    {
+        result = esfs_cmac_read(file_handle, &file_handle->nonce[0], ESFS_AES_NONCE_SIZE_BYTES, &num_bytes);
+        if((result != ESFS_SUCCESS) || (num_bytes != ESFS_AES_NONCE_SIZE_BYTES))
+        {
+            tr_err("esfs_open() - esfs_cmac_read() (AES nonce) failed with ESFS result = 0x%x and num_bytes bytes = %zu",
+                (unsigned int)result, num_bytes);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+    }
+
+    file_handle->tlv_properties.number_of_items = 0;
+
+    // Read the number of items of meta data
+    uint16_t meta_data_qty;
+    result = esfs_cmac_read(file_handle, (void *)( &meta_data_qty ), sizeof(meta_data_qty), &num_bytes);
+    if(result != ESFS_SUCCESS || num_bytes != sizeof(meta_data_qty) || meta_data_qty > ESFS_MAX_TYPE_LENGTH_VALUES)
+    {
+        tr_err("esfs_open() - esfs_cmac_read() (number of items of meta data) failed with ESFS result = 0x%x and num_bytes bytes = %zu",
+            (unsigned int)result, num_bytes);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    // Read the metadata properties if there are any
+    if(meta_data_qty != 0)
+    {
+        result = esfs_cmac_read( file_handle,
+                           (void *) ( &(file_handle->tlv_properties.tlv_items[0]) ),
+                           (sizeof(file_handle->tlv_properties.tlv_items[0]) * meta_data_qty),
+                           &num_bytes
+                         );
+
+        if(result != ESFS_SUCCESS || num_bytes != sizeof(file_handle->tlv_properties.tlv_items[0])*meta_data_qty)
+        {
+            tr_err("esfs_open() - esfs_cmac_read() (metadata properties) failed with ESFS result = 0x%x and num_bytes bytes = %zu",
+                (unsigned int)result, num_bytes);
+            goto errorExit;
+        }
+
+        // Skip to the start of the data by calculating the last metadata position plus its length
+        esfs_tlvItem_t *ptypeLengthValueItem = &file_handle->tlv_properties.tlv_items[meta_data_qty - 1];
+
+        if(esfs_cmac_skip_to(file_handle, ptypeLengthValueItem->position + ptypeLengthValueItem->length_in_bytes) != ESFS_SUCCESS)
+        {
+            tr_err("esfs_open() - esfs_cmac_skip_to() failed.");
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+    }
+
+    file_handle->tlv_properties.number_of_items = meta_data_qty;
+
+    // We are at the start of the data section
+    file_handle->current_read_pos = 0;
+
+    // Get current position
+    int32_t current_pos;
+    res = pal_fsFtell(&file_handle->file, &current_pos);
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_open() - pal_fsFtell() failed with pal_status = 0x%x", (unsigned int)res);
+        goto errorExit;
+    }
+
+    // get the whole file size and store it in the handle
+    res = esfs_get_physical_file_size(&file_handle->file, &file_handle->file_size);
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_open() - esfs_open() failed with status 0x%x", (unsigned int)res);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    // Skip to the end of the file while calculating the cmac
+    if(esfs_cmac_skip_to(file_handle, file_handle->file_size - ESFS_CMAC_SIZE_IN_BYTES) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_open() - esfs_cmac_skip_to() failed.");
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    // Terminate cmac calculation and get it.
+    unsigned char cmac[ESFS_CMAC_SIZE_IN_BYTES];
+    if(esfs_cmac_finish(file_handle, &cmac[0]) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_open() - esfs_finish_cmac() failed");
+        goto errorExit;
+    }
+    cmac_created = 0;
+
+    // save the CMAC in the file descriptor. We will use this to check that the file has not
+    // changed when esfs_read() or read_meta_data() is called.
+    memcpy(&file_handle->cmac[0],&cmac[0],sizeof(file_handle->cmac));
+
+    // Check the cmac and set the file position to the start of the data
+    if(esfs_cmac_check_and_restore(file_handle, &cmac[0], current_pos) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_open() - cmac that we read from the file does not match the one that we calculated");
+        result = ESFS_CMAC_DOES_NOT_MATCH;
+        goto errorExit;
+    }
+
+    // Calculate the size of the data only, by getting the file size and deducting the header and cmac
+    file_handle->data_size =  file_handle->file_size - esfs_file_header_size(file_handle);
+
+    // We deduct the cmac bytes at the end of the file since they are not part of the data
+    file_handle->data_size -= ESFS_CMAC_SIZE_IN_BYTES;
+
+    file_handle->file_flag = ESFS_READ;
+    file_handle->blob_name_length = name_length;
+
+    return ESFS_SUCCESS;
+
+errorExit:
+    if(file_opened)
+    {
+        pal_fsFclose(&file_handle->file);
+    }
+    if(is_aes_ctx_created)
+    {
+        pal_freeAes( &(file_handle->aes_ctx) );
+    }
+    if(cmac_created)
+    {
+        // Clean up cmac. Ignore error.
+        (void)esfs_cmac_finish(file_handle, &cmac[0]);
+    }
+
+    return result;
+}
+
+esfs_result_e esfs_write(esfs_file_t *file_handle, const void *buffer, size_t bytes_to_write)
+{
+    esfs_result_e result = ESFS_ERROR;
+
+    tr_info("esfs_write - enter");
+    if((esfs_validate(file_handle) != ESFS_SUCCESS) || (!buffer) || (bytes_to_write == 0))
+    {
+        tr_err("esfs_write() failed with bad parameters");
+        return ESFS_INVALID_PARAMETER;
+    }
+
+    if(file_handle->file_flag == ESFS_READ)
+    {
+        tr_err("esfs_write() write failed - file is opened for read only");
+        result = ESFS_FILE_OPEN_FOR_READ;
+        goto errorExit;
+    }
+    else
+    {
+        // Write data
+        // If encrypted esfs is requested (file_handle->esfs_mode), then this part should be encrypted
+
+        // The data should be encrypted if the encrypted esfs is requested by the esfs_mode argument
+        if((file_handle->esfs_mode & ESFS_ENCRYPTED) != 0)
+        {
+            result = esfs_encrypt_fwrite_and_calc_cmac(buffer, bytes_to_write, file_handle);
+        }
+        else
+        {
+            result = esfs_fwrite_and_calc_cmac(buffer, bytes_to_write, file_handle);
+        }
+
+        if(result != ESFS_SUCCESS)
+        {
+            tr_err("esfs_write() - esfs_fwrite_and_calc_cmac()/esfs_encrypt_fwrite_and_calc_cmac() for data failed with esfs result = 0x%x", result);
+            // Since the write failed, we cannot be sure of the state of the file, so we mark it as invalid.
+            file_handle->file_invalid = 1;
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+    }
+
+    file_handle->data_size += bytes_to_write;
+
+    return ESFS_SUCCESS;
+
+errorExit:
+    return result;
+}
+
+esfs_result_e esfs_read(esfs_file_t *file_handle, void *buffer, size_t bytes_to_read, size_t *read_bytes)
+{
+    esfs_result_e result = ESFS_ERROR;
+    uint16_t cmac_created = 0;
+	size_t remaining_bytes = 0;
+	palStatus_t res = PAL_SUCCESS;
+
+    tr_info("esfs_read - enter");
+    if(esfs_validate(file_handle) != ESFS_SUCCESS || read_bytes == NULL || !buffer)
+    {
+        result = ESFS_INVALID_PARAMETER;
+        goto errorExit;
+    }
+
+    if(file_handle->file_flag != ESFS_READ)
+    {
+        result = ESFS_FILE_OPEN_FOR_WRITE;
+        goto errorExit;
+    }
+    // Save file position
+    int32_t position;
+    res = pal_fsFtell(&file_handle->file, &position);
+    if(res != PAL_SUCCESS)
+    {
+        tr_err("esfs_read() - pal_fsFtell() failed with pal status 0x%x", (unsigned int)res);
+        goto errorExit;
+    }
+
+    // Limit how many bytes we can actually read depending on the size of the data section.
+    remaining_bytes = file_handle->data_size - file_handle->current_read_pos;
+    bytes_to_read = PAL_MIN(remaining_bytes, bytes_to_read);
+
+    if(esfs_cmac_start(file_handle) != ESFS_SUCCESS)
+    {
+        goto errorExit;
+    }
+    cmac_created = 1;
+
+    if(esfs_cmac_skip_to(file_handle, position) != ESFS_SUCCESS)
+    {
+        goto errorExit;
+    }
+
+    // Read data
+    // If required according to esfs_mode, the read data will be decrypted
+    size_t num_bytes;
+    if((file_handle->esfs_mode & ESFS_ENCRYPTED) != 0)
+    {
+        if(esfs_read_and_decrypt(file_handle, buffer, bytes_to_read, &num_bytes) != ESFS_SUCCESS)
+        {
+            goto errorExit;
+        }
+    }
+    else
+    {
+        if(esfs_cmac_read(file_handle, buffer, bytes_to_read, &num_bytes ) != ESFS_SUCCESS)
+        {
+            goto errorExit;
+        }
+    }
+
+    *read_bytes = num_bytes;
+
+    if(esfs_cmac_skip_to(file_handle ,file_handle->file_size - ESFS_CMAC_SIZE_IN_BYTES) != ESFS_SUCCESS)
+    {
+        goto errorExit;
+    }
+
+    unsigned char cmac[ESFS_CMAC_SIZE_IN_BYTES];
+    if(esfs_cmac_finish(file_handle, &cmac[0]) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_read() - esfs_finish_cmac() failed");
+        goto errorExit;
+    }
+    cmac_created = 0;
+
+    // Check the cmac and set to the byte after the end of the data being read.
+    if(esfs_cmac_check_and_restore(file_handle, &cmac[0], position + num_bytes) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_read() - cmac that we read from the file does not match the one that we calculated");
+        result = ESFS_CMAC_DOES_NOT_MATCH;
+        goto errorExit;
+    }
+
+    // Update the current position
+    file_handle->current_read_pos += num_bytes;
+
+    return ESFS_SUCCESS;
+
+errorExit:
+    tr_err("esfs_read errorExit result=0x%x", result);
+    if(cmac_created)
+    {
+        // Clean up cmac. Ignore error and resulting cmac.
+        (void)esfs_cmac_finish(file_handle, &cmac[0]);
+    }
+
+    return result;
+}
+
+esfs_result_e esfs_seek(esfs_file_t *file_handle, int32_t offset, esfs_seek_origin_e whence, uint32_t *position)
+{
+    esfs_result_e result = ESFS_ERROR;
+	palStatus_t res = PAL_SUCCESS;
+    tr_info("esfs_seek - enter");
+    if(esfs_validate(file_handle) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_seek() failed with bad parameters");
+        return ESFS_INVALID_PARAMETER;
+    }
+
+    if(file_handle->file_flag != ESFS_READ)
+    {
+        tr_err("esfs_seek() seek failed - file is opened for write only");
+        result = ESFS_FILE_OPEN_FOR_WRITE;
+        goto errorExit;
+    }
+    pal_fsOffset_t pal_whence;
+    // ESFS whence enum values are in sync with those of pal
+    if(whence == ESFS_SEEK_SET)
+    {
+        if(offset > (int32_t)file_handle->data_size || offset < 0)
+        {
+            tr_err("esfs_seek() failed with bad parameters in offset calculation : ESFS_SEEK_SET");
+            result = ESFS_INVALID_PARAMETER;
+            goto errorExit;
+        }
+        // Add the offset to the start of the data
+        offset += esfs_file_header_size(file_handle);
+        pal_whence = PAL_FS_OFFSET_SEEKSET;
+    }
+    else if(whence == ESFS_SEEK_END)
+    {
+        if(offset < -(int32_t)file_handle->data_size || offset > 0)
+        {
+            tr_err("esfs_seek() failed with bad parameters in offset calculation : ESFS_SEEK_END");
+            result = ESFS_INVALID_PARAMETER;
+            goto errorExit;
+        }
+        // Deduct the cmac size from the offset because it is located after the data section.
+        offset -= ESFS_CMAC_SIZE_IN_BYTES;
+        pal_whence = PAL_FS_OFFSET_SEEKEND;
+    }
+    else if(whence == ESFS_SEEK_CUR)
+    {
+        if(offset + file_handle->current_read_pos > (int32_t)file_handle->data_size || offset + (int32_t)file_handle->current_read_pos < 0)
+        {
+            tr_err("esfs_seek() failed with bad parameters in offset calculation : ESFS_SEEK_CUR");
+            result = ESFS_INVALID_PARAMETER;
+            goto errorExit;
+        }
+        pal_whence = PAL_FS_OFFSET_SEEKCUR;
+    }
+    else
+    {
+        tr_err("esfs_seek() failed with bad parameters - wrong whence");
+        result = ESFS_INVALID_PARAMETER;
+        goto errorExit;
+    }
+    res = pal_fsFseek(&file_handle->file, offset, pal_whence);
+    if(res != PAL_SUCCESS)
+    {
+        tr_err("esfs_seek() - pal_fsFseek() failed with pal status 0x%x", (unsigned int)res);
+        goto errorExit;
+    }
+    // Get current position if position is not NULL
+    if(position)
+    {
+        res = pal_fsFtell(&file_handle->file, (int32_t *)position);
+        if(res != PAL_SUCCESS)
+        {
+            tr_err("esfs_seek() - pal_fsFtell() failed with pal status 0x%x", (unsigned int)res);
+            goto errorExit;
+        }
+
+        // Ignore the file header data
+        *position -= esfs_file_header_size(file_handle);
+
+        // Update the current position
+        file_handle->current_read_pos = *position;
+    }
+
+    return ESFS_SUCCESS;
+
+errorExit:
+    return result;
+}
+
+
+esfs_result_e esfs_file_size(esfs_file_t *file_handle, size_t *size_in_bytes)
+{
+    esfs_result_e result = ESFS_ERROR;
+
+    tr_info("esfs_file_size - enter");
+    if((esfs_validate(file_handle) != ESFS_SUCCESS) || (!size_in_bytes))
+    {
+        tr_err("esfs_file_size() failed with bad parameters");
+        result = ESFS_INVALID_PARAMETER;
+        goto errorExit;
+    }
+
+    *size_in_bytes = file_handle->data_size;
+
+    return ESFS_SUCCESS;
+
+errorExit:
+    return result;
+}
+
+esfs_result_e esfs_close(esfs_file_t *file_handle)
+{
+    uint16_t failed_to_write_CMAC = 0;
+    uint16_t file_esfs_mode = 0;
+    esfs_file_flag_e esfs_file_flag;
+    char esfs_short_file_name[ESFS_QUALIFIED_FILE_NAME_LENGTH] = {0};
+    esfs_result_e result = ESFS_ERROR;
+    char full_path_working_dir[MAX_FULL_PATH_SIZE];
+	palStatus_t res = PAL_SUCCESS;
+
+    tr_info("esfs_close - enter");
+    if(esfs_validate(file_handle) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_close() failed with bad parameters");
+        result = ESFS_INVALID_PARAMETER;
+        goto errorExit;
+    }
+
+    res = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, full_path_working_dir);
+    if (res != PAL_SUCCESS)
+    {
+        tr_err("esfs_close() - pal_fsGetMountPoint() for working directory failed with pal_status = 0x%x", (unsigned int)res);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    strncat(full_path_working_dir, "/" ESFS_WORKING_DIRECTORY "/", sizeof(ESFS_WORKING_DIRECTORY) + 1);
+
+
+    // Close AES context if needed
+    if((file_handle->esfs_mode & ESFS_ENCRYPTED) != 0)
+    {
+        pal_freeAes( &(file_handle->aes_ctx) );
+    }
+ 
+    esfs_file_flag = file_handle->file_flag;
+    file_esfs_mode = file_handle->esfs_mode;
+    strncpy(esfs_short_file_name, file_handle->short_file_name, ESFS_QUALIFIED_FILE_NAME_LENGTH - 1);
+
+    if(file_handle->file_flag == ESFS_WRITE)
+    {
+        unsigned char cmac[ESFS_CMAC_SIZE_IN_BYTES];
+        // Finish signature calculation
+        if(esfs_cmac_finish(file_handle, &cmac[0]) != ESFS_SUCCESS)
+        {
+            tr_err("esfs_close() - esfs_cmac_finish() failed");
+            goto errorExit;
+        }
+        // Write signature
+        size_t bytes_written;
+        res = pal_fsFwrite(&file_handle->file, &cmac[0], sizeof(cmac), &bytes_written);
+        if(res != PAL_SUCCESS || sizeof(cmac) != bytes_written)
+        {
+            tr_err("esfs_close() - pal_fsFwrite() (signature) failed with pal result = 0x%x and bytes_written bytes = %zu",
+                (unsigned int)res, bytes_written);
+            // mark the file invalid on a failed write
+            file_handle->file_invalid = 1;
+            // Continue so that we delete the file, but we should return failure later
+            failed_to_write_CMAC = 1;
+        }
+    }
+
+    res = pal_fsFclose(&file_handle->file);
+    if(res == PAL_SUCCESS)
+    {
+        // Remove a file that is invalid. It may have become invalid due to a failed write.
+        if(file_handle->file_invalid)
+        {
+            strncat(full_path_working_dir,file_handle->short_file_name, ESFS_QUALIFIED_FILE_NAME_LENGTH - 1);
+
+            res = pal_fsUnlink(full_path_working_dir);
+            if(res != PAL_SUCCESS)
+            {
+                tr_err("esfs_close() - pal_fsUnlink() failed with pal status 0x%x", (unsigned int)res);
+                goto errorExit;
+            }
+        }
+    }
+    else
+    {
+        tr_err("esfs_close() - pal_fsFclose() failed with pal status 0x%x", (unsigned int)res);
+        goto errorExit;
+    }
+
+    if(failed_to_write_CMAC)
+    {
+        goto errorExit;
+    }
+
+
+    if ((file_esfs_mode & ESFS_FACTORY_VAL) && (esfs_file_flag == ESFS_WRITE) && !(file_handle->file_invalid))
+    {
+        char full_path_backup_dir[MAX_FULL_PATH_SIZE] = { 0 };
+
+        res = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, full_path_backup_dir);
+        if (res != PAL_SUCCESS)
+        {
+            tr_err("esfs_close() - pal_fsGetMountPoint() for backup directory failed with pal_status = 0x%x", (unsigned int)res);
+            result = ESFS_ERROR;
+            goto errorExit;
+        }
+
+        strncat(full_path_backup_dir, "/" ESFS_BACKUP_DIRECTORY "/", sizeof(ESFS_BACKUP_DIRECTORY) + 1);
+
+        strncat(full_path_working_dir, esfs_short_file_name, ESFS_QUALIFIED_FILE_NAME_LENGTH -1);
+        strncat(full_path_backup_dir, esfs_short_file_name, ESFS_QUALIFIED_FILE_NAME_LENGTH - 1);
+
+        if (esfs_copy_file(full_path_backup_dir, full_path_working_dir) != ESFS_SUCCESS)
+        {
+            tr_err("esfs_close() - esfs_copy_file() failed");
+            goto errorExit;
+        }
+    }
+
+    return ESFS_SUCCESS;
+errorExit:
+    return result;
+}
+
+esfs_result_e esfs_delete(const uint8_t *name, size_t name_length)
+{
+
+    palStatus_t pal_result = PAL_SUCCESS;
+    char working_dir_path[MAX_FULL_PATH_SIZE] = { 0 };
+    char short_file_name[ESFS_QUALIFIED_FILE_NAME_LENGTH];
+    esfs_result_e result = ESFS_ERROR;
+
+    tr_info("esfs_delete - enter");
+    // Check parameters
+    if(!name || name_length == 0)
+    {
+        tr_err("esfs_delete() failed with bad parameters");
+        result = ESFS_INVALID_PARAMETER;
+        goto errorExit;
+    }
+    if(esfs_get_name_from_blob(name, name_length, short_file_name, ESFS_FILE_NAME_LENGTH ) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_delete() - esfs_get_name_from_blob() failed");
+        goto errorExit;
+    }
+    tr_info("esfs_delete %s", short_file_name);
+
+    pal_result = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FOLDER_DEPTH_CHAR + 1, working_dir_path);
+    if (pal_result != PAL_SUCCESS)
+    {
+        tr_err("esfs_delete() - pal_fsGetMountPoint() for working directory failed with pal_status = 0x%x", (unsigned int)pal_result);
+        result = ESFS_ERROR;
+        goto errorExit;
+    }
+
+    strncat(working_dir_path, "/" ESFS_WORKING_DIRECTORY "/", sizeof(ESFS_WORKING_DIRECTORY) + 1);
+
+    // We do not verify that name is the actual name in the file because currently we do not allow the situation of hash
+    // clash to arise.
+
+    strncat(working_dir_path,short_file_name, ESFS_QUALIFIED_FILE_NAME_LENGTH - 1);
+
+    tr_info("esfs_delete %s", working_dir_path);
+    pal_result = pal_fsUnlink(working_dir_path);
+
+    if ((pal_result == PAL_ERR_FS_NO_FILE) || (pal_result == PAL_ERR_FS_NO_PATH))
+    {
+        tr_err("esfs_delete() - pal_fsUnlink() failed with pal status 0x%x", (unsigned int)pal_result);
+        result = ESFS_NOT_EXISTS;
+        goto errorExit;
+    }
+    else if (pal_result != PAL_SUCCESS)
+    {
+        tr_err("esfs_delete() - pal_fsUnlink() failed with pal status 0x%x", (unsigned int)pal_result);
+        goto errorExit;
+    }
+
+    return ESFS_SUCCESS;
+errorExit:
+    return result;
+}
+
+esfs_result_e esfs_get_meta_data_properties(esfs_file_t *file_handle, esfs_tlv_properties_t **meta_data_properties)
+{
+    esfs_result_e result = ESFS_ERROR;
+    tr_info("esfs_get_meta_data_properties - enter");
+    if((esfs_validate(file_handle) != ESFS_SUCCESS) || (!meta_data_properties))
+    {
+        tr_err("esfs_get_meta_data_properties() failed with bad parameters");
+        result = ESFS_INVALID_PARAMETER;
+        goto errorExit;
+    }
+
+    if (file_handle->file_flag != ESFS_READ)
+    {
+        tr_err("esfs_get_meta_data_properties() failed - file is opened for write only");
+        result = ESFS_FILE_OPEN_FOR_WRITE;
+        goto errorExit;
+    }
+
+    *meta_data_properties = &file_handle->tlv_properties;
+    return ESFS_SUCCESS;
+errorExit:
+    return result;
+}
+
+
+esfs_result_e esfs_read_meta_data(esfs_file_t *file_handle, uint32_t index, esfs_tlv_item_t *meta_data)
+{
+    esfs_result_e result = ESFS_ERROR;
+    bool is_read_error = false;
+    uint16_t cmac_created = 0;
+	int32_t offset_to_restore = 0;
+	palStatus_t res = PAL_SUCCESS;
+
+    tr_info("esfs_read_meta_data - enter");
+    if(esfs_validate(file_handle) != ESFS_SUCCESS || index >= ESFS_MAX_TYPE_LENGTH_VALUES || !meta_data || (file_handle->tlv_properties.tlv_items[index].length_in_bytes == 0))
+    {
+        tr_err("esfs_read_meta_data() failed with bad parameters");
+        result = ESFS_INVALID_PARAMETER;
+        goto errorExit;
+    }
+
+    if(file_handle->file_flag != ESFS_READ)
+    {
+        tr_err("esfs_read_meta_data() failed - file is opened for write only");
+        result = ESFS_FILE_OPEN_FOR_WRITE;
+        goto errorExit;
+    }
+    // Get current file position
+    int32_t current_pos;
+    res = pal_fsFtell(&file_handle->file, &current_pos);
+    if(res != PAL_SUCCESS)
+    {
+        tr_err("esfs_read_meta_data() - pal_fsFtell() failed with pal status 0x%x", (unsigned int)res);
+        goto errorExit;
+    }
+
+    // Start the cmac calculation and position to the start of the file
+    if(esfs_cmac_start(file_handle) != ESFS_SUCCESS)
+    {
+        goto errorExit;
+    }
+    cmac_created = 1;
+
+    // Skip to the meta-data position while calculating the cmac
+    if(esfs_cmac_skip_to(file_handle, file_handle->tlv_properties.tlv_items[index].position) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_read_meta_data() - pal_fsFseek() failed with pal status 0x%x", (unsigned int)res);
+        goto errorExit;
+    }
+
+    // Read data
+    // If required according to esfs_mode, the read data will be decrypted
+    size_t num_bytes;
+    if((file_handle->esfs_mode & ESFS_ENCRYPTED) != 0)
+    {
+        if(esfs_read_and_decrypt( file_handle,
+                                  meta_data->value,
+                                  file_handle->tlv_properties.tlv_items[index].length_in_bytes,
+                                  &num_bytes
+                                ) != ESFS_SUCCESS)
+        {
+            is_read_error = true;
+        }
+    }
+    else
+    {
+        if(esfs_cmac_read(file_handle, meta_data->value, file_handle->tlv_properties.tlv_items[index].length_in_bytes, &num_bytes ) != ESFS_SUCCESS)
+        {
+            is_read_error = true;
+        }
+    }
+
+    if(is_read_error || (num_bytes != file_handle->tlv_properties.tlv_items[index].length_in_bytes))
+    {
+        tr_err("esfs_read_meta_data() - read data failed is_read_error = %s and num_bytes  = %zu",
+            is_read_error ? "true" : "false", num_bytes);
+        goto errorExit;
+    }
+
+    // Skip to the end of the data section of the file.
+    if(esfs_cmac_skip_to(file_handle ,file_handle->file_size - ESFS_CMAC_SIZE_IN_BYTES) != ESFS_SUCCESS)
+    {
+        goto errorExit;
+    }
+
+    // Return the cmac
+    unsigned char cmac[ESFS_CMAC_SIZE_IN_BYTES];
+    if(esfs_cmac_finish(file_handle, &cmac[0]) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_read() - esfs_finish_cmac() failed");
+        goto errorExit;
+    }
+    cmac_created = 0;
+
+    // Before restoring old position, make sure offset_to_restore is not a negative number
+    offset_to_restore = current_pos;
+    if(offset_to_restore < 0)
+    {
+        tr_err("esfs_read_meta_data() failed - current_pos is negative");
+        goto errorExit;
+    }
+
+    // Check the cmac and restore the file position to the saved position
+    if(esfs_cmac_check_and_restore(file_handle, &cmac[0], offset_to_restore) != ESFS_SUCCESS)
+    {
+        tr_err("esfs_read_meta_data() - cmac that we read from the file does not match the one that we calculated");
+        result = ESFS_CMAC_DOES_NOT_MATCH;
+        goto errorExit;
+    }
+
+    // Update meta_data fields
+    meta_data->type = file_handle->tlv_properties.tlv_items[index].type;
+    meta_data->length_in_bytes = file_handle->tlv_properties.tlv_items[index].length_in_bytes;
+
+    return ESFS_SUCCESS;
+
+errorExit:
+    if(cmac_created)
+    {
+        // Clean up cmac. Ignore error.
+        (void)esfs_cmac_finish(file_handle, &cmac[0]);
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/esfs_file_name.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,98 @@
+/*
+* Copyright (c) 2017 ARM Limited. All rights reserved.
+* SPDX-License-Identifier: Apache-2.0
+* 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.
+*/
+
+#include "pal.h"
+#include "pal_Crypto.h"
+#include <string.h>
+#include "esfs.h"
+
+
+static char IntToBase64Char(uint8_t intVal)
+{
+    const char* base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#_";
+    return base64Digits[intVal & 0x3F];
+}
+esfs_result_e esfs_EncodeBase64(const void* buffer, uint32_t bufferSize, char* string, uint32_t stringSize)
+{
+    uint32_t bitOffset = 0;
+
+    const uint8_t* readPtr = (const uint8_t*)buffer;
+    const uint8_t* bufferEnd = (const uint8_t*)buffer + bufferSize;
+
+    char* writePtr = string;
+    char* stringEnd = string + stringSize - 1;
+
+    if ((NULL == string) || (NULL == buffer) || (stringSize == 0))
+        return ESFS_INVALID_PARAMETER;
+
+    stringSize--;
+    while(readPtr < bufferEnd && writePtr < stringEnd)
+    {
+        uint8_t tempVal = 0;
+        switch (bitOffset)
+        {
+            case 0:
+                *writePtr++ = IntToBase64Char(*readPtr >> 2);                 // take upper 6 bits
+                break;
+            case 6:
+                tempVal = *readPtr++ << 4;
+                if (readPtr < bufferEnd)
+                    tempVal |= *readPtr >> 4;
+                *writePtr++ = IntToBase64Char(tempVal);
+                break;
+            case 4:
+                tempVal = *readPtr++ << 2;
+                if (readPtr < bufferEnd)
+                    tempVal |= *readPtr >> 6;
+                *writePtr++ = IntToBase64Char(tempVal);
+                break;
+            case 2:
+                *writePtr++ = IntToBase64Char(*readPtr++);
+                break;
+            default:
+                return ESFS_INTERNAL_ERROR; // we should never reach this code.
+        }
+        bitOffset = (bitOffset + 6) & 0x7;
+    }
+    while (bitOffset > 0 && writePtr < stringEnd)
+    {
+        *writePtr++ = '!';
+        bitOffset = (bitOffset + 6) & 0x7;
+    }
+    *writePtr = 0;
+
+    if ((readPtr < bufferEnd) || (bitOffset != 0))
+        return (ESFS_BUFFER_TOO_SMALL);
+
+    return(ESFS_SUCCESS);
+}
+
+/* size_of_file_name should should include the null at the end of the string. In our case 9*/
+esfs_result_e esfs_get_name_from_blob(const uint8_t *blob, uint32_t blob_length,char *file_name, uint32_t size_of_file_name)
+{
+unsigned char output[32] = {0};
+    palStatus_t pal_result;
+    esfs_result_e esfs_result;
+    pal_result = pal_sha256(blob, blob_length, output);
+    if (PAL_SUCCESS != pal_result)
+        return ESFS_INTERNAL_ERROR;
+    esfs_result = esfs_EncodeBase64(output, (size_of_file_name - 1)*6/8, file_name, size_of_file_name);
+    return (esfs_result);
+
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/esfs_performance.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "esfs_performance.h"
+
+#ifdef  ESFS_PERFOMANCE_TEST // Allow disabling calls to performance
+
+#include "mbed-trace/mbed_trace.h"
+
+#define TRACE_GROUP         "esfs"  // Maximum 4 characters
+#define TICKS_PER_MICROSEC  120 // FIXME Replace with pal_osKernelSysMilliSecTick when it will work
+
+static performance_record_t performance_array[PERFORMANCE_ARRAY_SIZE]={{{0}, 0}};
+static unsigned long performance_index = 0;
+
+void print_performance()
+{
+unsigned long i;
+char type_title[10];
+    for (i=0;i<performance_index;i++)
+    {
+        if (performance_array[i].type == ESFS_PERFORMANCE_END)
+        {
+            strcpy(type_title,"end  ");
+            tr_cmdline("\nPerformance %s %s %lu %lu",
+                performance_array[i].title,
+                type_title,
+                performance_array[i].mark,
+                performance_array[i].total);
+        }
+        else
+        {
+            strcpy(type_title,"start  ");
+            tr_cmdline("\nPerformance %s %s %lu",
+                performance_array[i].title,
+                type_title,
+                performance_array[i].total);
+        }
+    }
+    performance_index = 0;
+    tr_cmdline("\nIndex=%lu",performance_index);
+
+}
+void add_performance_mark(const char * title, esfs_performance_type_e type)
+{
+    unsigned long mark  = (unsigned long)(pal_osKernelSysTick()/TICKS_PER_MICROSEC);
+    performance_array[performance_index].mark = mark;
+    strncpy(performance_array[performance_index].title, title, TITLE_MAX);
+    performance_array[performance_index].total=0;
+    performance_array[performance_index].type=type;
+    if (type == ESFS_PERFORMANCE_END)
+    {
+        // find the start mark
+        for (unsigned long j=performance_index-1;j>=0;j--)
+        {
+            if (!strncmp(performance_array[j].title,title,TITLE_MAX))
+            {
+                performance_array[performance_index].total = mark - performance_array[j].mark;
+                break;
+            }
+        }
+    }
+
+    if (performance_index++ >= (PERFORMANCE_ARRAY_SIZE-1))
+    {
+        print_performance();
+    }
+}
+
+
+#endif  // ESFS_PERFOMANCE_TEST
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/include/esfs.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef __ESFS_H
+#define __ESFS_H
+
+#include <stdint.h>
+#include "pal_types.h"
+#include "pal_errors.h"
+#include "pal_macros.h"
+#include "pal_fileSystem.h"
+#include "pal_Crypto.h"
+
+
+
+#define ESFS_AES_NONCE_SIZE_BYTES   (8)
+
+// This value can be reduced to 0 to save stack space, if no metadata is required.
+// Beware that changing the values affects the format of the file.
+#define ESFS_MAX_TYPE_LENGTH_VALUES (3)
+
+#define ESFS_FILE_NAME_LENGTH       (9)
+
+// The maximum length of the name in bytes.
+#define ESFS_MAX_NAME_LENGTH            (1024)
+
+// ESFS_FILE_NAME_LENGTH + dot + extension (for example:  123456789.txt)
+#define ESFS_QUALIFIED_FILE_NAME_LENGTH       (ESFS_FILE_NAME_LENGTH + 4)
+
+#define ESFS_CMAC_SIZE_IN_BYTES         (16)
+
+typedef enum {
+    ESFS_SUCCESS = 0,
+    ESFS_INVALID_PARAMETER = 1,
+    ESFS_INTERNAL_ERROR = 2,
+    ESFS_BUFFER_TOO_SMALL = 3,
+    ESFS_ERROR = 4 ,
+    ESFS_EXISTS = 5,
+    ESFS_NOT_EXISTS = 6,
+    ESFS_HASH_CONFLICT = 7,
+    ESFS_FILE_OPEN_FOR_READ = 8,
+    ESFS_FILE_OPEN_FOR_WRITE = 9,
+    ESFS_INVALID_FILE_VERSION = 10,
+    ESFS_CMAC_DOES_NOT_MATCH = 11,
+    ESFS_ERROR_MAXVAL = 0xFFFF
+}esfs_result_e;
+
+typedef enum {
+    ESFS_USER_READ = 0x0001,
+    ESFS_USER_WRITE = 0x0002,
+    ESFS_USER_DELETE = 0x0004,
+    ESFS_USER_EXECUTE = 0x0008,
+    ESFS_OTHER_READ = 0x0010,
+    ESFS_OTHER_WRITE = 0x0020,
+    ESFS_OTHER_DELETE = 0x0040,
+    ESFS_OTHER_EXECUTE = 0x0080,
+    ESFS_ENCRYPTED = 0x0100,
+    ESFS_FACTORY_VAL = 0x0200,
+    ESFS_EXTENDED_ACL = 0x0400,
+    ESFS_MAXVAL = 0xFFFF
+}esfs_mode_e;
+
+typedef enum {
+    ESFS_READ = 1,    // This is the same as the standard "O_RDONLY"
+    ESFS_WRITE = 2    // This is the same as the standard "O_WRONLY & O_APPEND"
+}esfs_file_flag_e;
+
+typedef struct {
+    uint16_t type;
+    uint16_t length_in_bytes;
+    void *value;
+} esfs_tlv_item_t;
+
+typedef struct {
+    uint16_t type;
+    uint16_t length_in_bytes;
+    // Position in bytes from the beginning of the of file.
+    uint16_t position;
+} esfs_tlvItem_t;
+
+typedef struct {
+    uint16_t number_of_items;
+    esfs_tlvItem_t tlv_items[ESFS_MAX_TYPE_LENGTH_VALUES];
+}esfs_tlv_properties_t;
+
+
+typedef struct {
+    palFileDescriptor_t file;
+    esfs_file_flag_e file_flag;
+    palAesHandle_t aes_ctx;
+    palCMACHandle_t signature_ctx;  // NULL indicates no context.
+    uint8_t nonce[ESFS_AES_NONCE_SIZE_BYTES];
+    uint8_t cmac[ESFS_CMAC_SIZE_IN_BYTES]; // Saved on open/create; compared with on read
+    uint16_t esfs_mode;
+    uint16_t blob_name_length;
+    char short_file_name[ESFS_QUALIFIED_FILE_NAME_LENGTH];
+    esfs_tlv_properties_t tlv_properties;
+    uint8_t file_invalid; // The file handle is invalid.
+    // These are valid for files that are opened, not created.
+    long current_read_pos;   // The byte position from the beginning of the data.
+    size_t data_size;   // The size of the data only in bytes.
+    int32_t file_size;  // Cache the physical file size on open.
+}esfs_file_t;
+
+// ESFS from which the enum values are in sync with those of PAL.
+typedef enum {
+    ESFS_SEEK_SET = PAL_FS_OFFSET_SEEKSET,    // Offset will be relative to the beginning of the file.
+    ESFS_SEEK_CUR = PAL_FS_OFFSET_SEEKCUR,    // Ofset will be relative to the last position read.
+    ESFS_SEEK_END = PAL_FS_OFFSET_SEEKEND     // Offset will be relative to the end of the file and must be zero or a negative number.
+}esfs_seek_origin_e;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** 
+* @brief esfs_init Must be called once after boot.
+*  Initializes the file system so that it can be used.
+*  It creates the working and backup folders if they do not exist.
+*  If the factory_reset operation was not completed, esfs_init continues the operation.
+*
+* @returns ESFS_SUCCESS or an error code.
+*
+*/
+esfs_result_e esfs_init(void);
+
+
+/** 
+* @brief esfs_finalize needs to be called before calling esfs_init again.
+* @returns ESFS_SUCCESS.
+*
+*/
+esfs_result_e esfs_finalize(void);
+
+
+/**
+* @brief esfs_factory_reset removes the files from the working folder
+*  and creates a copy of the files that were created with ESFS_FACTORY_VAL set in the esfs_mode parameter in the working folder.
+*  If the device is rebooted during the factory reset operation, ESFS resumes the operation when calling esfs_init after the reboot.
+*
+* @returns ESFS_SUCCESS or ESFS_ERROR.
+*
+*/
+esfs_result_e esfs_factory_reset(void);
+
+
+/** 
+ * @brief esfs_reset resets ESFS to an empty state.
+                Initializes the file system and formats the SD card if required. Also initializes the internal structures.
+ *
+ * @returns ESFS_SUCCESS or an error code.
+ *
+ */
+esfs_result_e esfs_reset(void);
+
+/**
+ * @brief Creates a new file and opens it for writing. Returns an error if a file exists.
+ *
+ *
+ * @param [in] name
+ *               A binary blob that uniquely identifies the file.
+ *
+ * @param [in] name_length
+ *               The size of the name in bytes. The minimum is 1 and the maximum is ESFS_MAX_NAME_LENGTH.
+ *
+ * @param  [in] meta_data
+ *                A pointer to an array of TLVs structures with meta_data_qty members.
+ *
+ * @param  [in] meta_data_qty
+ *                The number of TLVs in the array pointed by the meta_data parameter. The minimum is 0 and the maximum is ESFS_MAX_TYPE_LENGTH_VALUES.
+ *
+ * @param  [in] esfs_mode
+ *      A bitmap combination of values from the enum EsfsMode.
+ *
+ * @param [out] esfs_file_t file_handle A handle to the created file open for write.
+ *
+ * @returns ESFS_SUCCESS The file handle can be used in other ESFS functions. It must be closed to release it.
+ *          ESFS_INVALID_PARAMETER if the name, name_length, file_handle or meta_data_qty is not valid.
+ *          ESFS_EXISTS if a file with the same blob is found in the file system.
+ *          ESFS_HASH_CONFLICT if two different blobs result in the same short name.
+ *
+ *
+ */
+esfs_result_e esfs_create(const uint8_t * name, size_t name_length, const esfs_tlv_item_t *meta_data, size_t meta_data_qty, uint16_t esfs_mode, esfs_file_t *file_handle);
+
+/**
+ * @brief Opens a file for read.
+ *
+ *
+ * @param [in] name
+ *               A binary blob that uniquely identifies the file.
+ *
+ * @param [in] name_length
+ *               The size of the name in bytes.
+ *
+ * @param  [out] esfs_mode
+ *                A pointer to get the actual mode bits passed on file creation (see EfsFlags for bit values).
+ *
+ *
+ * @param [out] file_handle A handle to the file for future use.
+ *
+ * @returns ESFS_SUCCESS or an error code.
+ * ESFS_INVALID_PARAMETER if the name, name_length or file_handle is not valid.
+ * ESFS_HASH_CONFLICT - A file with the same file name but a different name is found.
+ * ESFS_CMAC_DOES_NOT_MATCH - The CMAC does not match. The file has possibly been tampered with.
+ * ESFS_INVALID_FILE_VERSION  - The format is invalid. This may indicate that the file is corrupt or the firmware supports
+ * a different file version from the one opened.
+ * ESFS_NOT_EXISTS if the file does not exist.
+ * If successful, the file handle can be used in other ESFS functions. It must be closed to release it.
+ *
+ *
+ */
+esfs_result_e esfs_open(const uint8_t * name, size_t name_length, uint16_t * esfs_mode, esfs_file_t *file_handle);
+
+/**
+ * @brief Close the file and invalidate the file handle.
+ *
+ * @param [in] file_handle The handle.
+ *
+ * @returns ESFS_SUCCESS or an error code.
+ * ESFS_INVALID_PARAMETER if the file_handle is not correct.
+ * ESFS_HASH_CONFLICT - Trying to open a file with the same file name but a different name.
+ */
+esfs_result_e esfs_close(esfs_file_t *file_handle);
+
+/**
+ * @brief Reads data from a previously opened file with parameter esfs_mode=EfsRead. Decrypt if required.
+ *
+ *
+ * @param [in] file_handle
+ *               The handle obtained from a call to esfs_open.
+ *
+ *
+ * @param  [in] buffer
+ *                A pointer to the memory buffer where the data read from the file is stored.
+ *
+ * @param  [in] bytes_to_read
+ *                The number of bytes to be read. The buffer must be big enough to contain this size.
+ *
+ *
+ * @param [out] read_bytes
+ *                The pointer to return the number of bytes actually read. Will be equal or smaller than bytes_to_read.
+ *
+ * @returns ESFS_SUCCESS 
+ *          ESFS_INVALID_PARAMETER if the file_handle is not correct, buffer is null or read_bytes is null.
+ *          ESFS_FILE_OPEN_FOR_WRITE if the file is after esfs_create and before esfs_close.
+ *
+ */
+esfs_result_e esfs_read(esfs_file_t *file_handle, void *buffer, size_t bytes_to_read, size_t *read_bytes);
+
+/**
+ * @brief Returns the metadata properties (TLVs) associated with the file.
+ *
+ * @param [in] file_handle
+ *               The handle obtained from a call to esfs_open.
+ *
+ * @param [out] meta_data_properties
+ *              A pointer to return the metadata properties.
+ *
+ * @returns ESFS_SUCCESS 
+ *         ESFS_INVALID_PARAMETER if file_handle is not valid or meta_data_properties is null.
+ *         ESFS_FILE_OPEN_FOR_WRITE if the file is after esfs_create and before esfs_close.
+ *
+ */
+esfs_result_e esfs_get_meta_data_properties(esfs_file_t *file_handle, esfs_tlv_properties_t **meta_data_properties);
+/**
+ * @brief Reads a single metadata entry into a TLV.
+ *
+ * @param [in] file_handle
+ *               The handle obtained from a call to esfs_open.
+ *
+ * @param [in] index
+ *                The index of the metadata if more than one meta data entry with the same type is present. 0 is the first one. 
+ *                The index refers to an imaginary array that holds metadata entries of the same type only.
+ *
+ * @param [in,out] meta_data
+ *                A pointer to an esfs_tlv_item_t structure with a valid *value pointing to a buffer aligned and big enough to hold the metadata.
+ *                The type and length_in_bytes fields of the TLV should be filled before calling the function with the right values for the required metadata.
+ *                The function will check the correctness of the fields.
+ *                (See esfs_get_meta_data_buffer_size to calculate the required size.)
+ *
+ *
+ *@returns ESFS_SUCCESS 
+ *         ESFS_INVALID_PARAMETER if file_handle or meta_data is not valid or the index is out of bounds.
+ *         ESFS_FILE_OPEN_FOR_WRITE if the file is after esfs_create and before esfs_close.
+ *
+ */
+esfs_result_e esfs_read_meta_data(esfs_file_t *file_handle, uint32_t index, esfs_tlv_item_t *meta_data);
+
+/**
+ * @brief Change the current position for read. This function will return an error if used on a file open with EfsWrite mode
+ * or the resulting position is out of the data range of the file.
+ *
+ *@param [in] file_handle
+ *               The handle obtained from a call to esfs_open.
+ *
+ *
+ * @param  [in] offset
+ *                The number of bytes to move the read position. It can be negative but must be in range of the data.
+ *
+ * @param  [in] whence
+ *                The position to relate the calculation of the new position for read. Use EfsSEEK_SET to seek the read position offset bytes from the beginning of the file and
+ *                EfsSEEK_CUR to change the read position offset bytes from the last read. The last read is in the beginning of the file after open.
+ *
+ * @param  [out] position
+ *                  A pointer to an integer that will hold the read position after the seek. The pointer may be NULL if the position is not the desired one.
+ *
+ *@returns ESFS_SUCCESS
+ *         ESFS_INVALID_PARAMETER if file_handle is not valid or the offset is out of bounds.
+ *         ESFS_FILE_OPEN_FOR_WRITE if the file is after esfs_create and before esfs_close.
+ *
+ *
+ */
+esfs_result_e esfs_seek(esfs_file_t *file_handle, int32_t offset, esfs_seek_origin_e whence, uint32_t *position);
+
+/**
+ * @brief Removes the file from the file system.
+ *
+ *
+ *@param [in] name
+ *               A binary blob that uniquely identifies the file.
+ *
+ * @param [in] name_length
+ *               The size of the name in bytes.
+ * @returns ESFS_SUCCESS
+ *          ESFS_NOT_EXISTS if the file does not exist.
+ *          ESFS_INVALID_PARAMETER if name, name_length or file_handle is not valid.
+ */
+esfs_result_e esfs_delete(const uint8_t * name, size_t name_length);
+
+/**
+ * @brief Write data to the file. Encrypt if required.
+ * This may leave the file in an unpredictable state on failure. If that happens, the file
+ * will be deleted by efs_close. The data is only guaranteed to be flushed to the media on efs_close.
+ *
+ *
+ * @param    [in] file_handle
+ *               The handle obtained from a call to esfs_open.
+ *
+ * @param    [in] buffer
+ *               A pointer to memory buffer with the data to write.
+ *
+ * @param    [in] bytes_to_write
+ *               The number of bytes to write from the buffer.
+ *
+ * @returns ESFS_SUCCESS
+ *          ESFS_FILE_OPEN_FOR_READ if called after esfs_open (file opened for read).
+ *          ESFS_INVALID_PARAMETER if file_handle is not correct, buffer is null or bytes_to_write == 0.
+ *
+ *
+ */
+esfs_result_e esfs_write(esfs_file_t *file_handle, const void *buffer, size_t bytes_to_write);
+
+/**
+ * @brief Returns the size of the data in the file.
+ *
+ * @param    [in] file_handle
+ *               The handle obtained from a call to esfs_open.
+ *
+ * @param    [out] size_in_bytes
+ *               A pointer to hold the size of the data in the file.
+ *
+ *
+ * @returns ESFS_SUCCESS
+ *          ESFS_INVALID_PARAMETER if file_handle is not valid.
+ *
+ *
+ */
+esfs_result_e esfs_file_size(esfs_file_t *file_handle, size_t *size_in_bytes);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/include/esfs_file_name.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef __ESFS_FILE_NAME_H
+#define __ESFS_FILE_NAME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+esfs_result_e esfs_get_name_from_blob(const uint8_t *blob, uint32_t blob_length,char *file_name, uint32_t size_of_file_name);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/include/esfs_performance.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifndef ESFS_SOURCE_INCLUDE_ESFS_PERFORMANCE_H_
+#define ESFS_SOURCE_INCLUDE_ESFS_PERFORMANCE_H_
+
+#include <stdint.h>
+
+//#define ESFS_PERFOMANCE_TEST   // Allow enabling and disabling calls to performance. Define it on compilation
+
+#define TITLE_MAX   30
+#define PERFORMANCE_ARRAY_SIZE  100
+typedef enum esfs_performance_type
+{
+        ESFS_PERFORMANCE_START,
+        ESFS_PERFORMANCE_END
+}esfs_performance_type_e;
+
+typedef struct performance_record
+{
+    char title[TITLE_MAX+1];
+    unsigned long mark;
+    unsigned long total;
+    esfs_performance_type_e type;
+}performance_record_t;
+
+
+#ifdef  ESFS_PERFOMANCE_TEST  // If not defined ESFS_PERFOMANCE_TEST functions will be removed
+
+void print_performance();
+void add_performance_mark(const char * title, esfs_performance_type_e type);
+
+
+
+#else
+
+#define print_performance()
+#define add_performance_mark(title, type)
+
+#endif
+
+#endif /* ESFS_SOURCE_INCLUDE_ESFS_PERFORMANCE_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/include/sotp.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifndef __SOTP_H
+#define __SOTP_H
+
+#include <stdint.h>
+#include "pal.h"
+
+#define SYS_CONF_SOTP_DISABLED 0
+#define SYS_CONF_SOTP_ENABLED  1
+#define SYS_CONF_SOTP_LIMITED  2
+
+#if PAL_USE_INTERNAL_FLASH
+    #ifndef SYS_CONF_SOTP
+        #define SYS_CONF_SOTP   SYS_CONF_SOTP_ENABLED
+    #endif
+#else
+    #ifndef SYS_CONF_SOTP
+        #define SYS_CONF_SOTP   SYS_CONF_SOTP_LIMITED
+    #endif
+#endif
+
+#ifdef SOTP_TESTING
+#undef SOTP_PROBE_ONLY
+#endif
+
+typedef enum {
+    SOTP_SUCCESS                = 0,
+    SOTP_READ_ERROR             = 1,
+    SOTP_WRITE_ERROR            = 2,
+    SOTP_NOT_FOUND              = 3,
+    SOTP_DATA_CORRUPT           = 4,
+    SOTP_BAD_VALUE              = 5,
+    SOTP_BUFF_TOO_SMALL         = 6,
+    SOTP_FLASH_AREA_TOO_SMALL   = 7,
+    SOTP_OS_ERROR               = 8,
+    SOTP_BUFF_NOT_ALIGNED       = 9,
+    SOTP_ALREADY_EXISTS         = 10,
+    SOTP_ERROR_MAXVAL           = 0xFFFF
+} sotp_result_e;
+
+#define SOTP_NUM_AREAS PAL_INT_FLASH_NUM_SECTIONS
+
+// Each type can be either OTP (One Time programmed) or RBP (RollBack protected)
+typedef enum {
+    SOTP_TYPE_FACTORY_DONE = 0,
+    SOTP_TYPE_RANDOM_SEED,
+    SOTP_TYPE_SAVED_TIME,
+    SOTP_TYPE_LAST_TIME_BACK,
+    SOTP_TYPE_ROT,
+    SOTP_TYPE_TRUSTED_TIME_SRV_ID,
+    SOTP_TYPE_EXECUTION_MODE,
+    SOTP_TYPE_OEM_TRANSFER_MODE_ENABLED,
+    SOTP_TYPE_MIN_FW_VERSION,
+
+    SOTP_LAST_TYPE = 15, // Keep as long as we have less than this
+    SOTP_MAX_TYPES
+} sotp_type_e;
+
+#define SOTP_BLANK_FLASH_VAL PAL_INT_FLASH_BLANK_VAL
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Check whether a type is an OTP type.
+/**
+ * @brief Check whether a type is an OTP type (can be written once) or RBP (more than once).
+ *
+ * @param [in] type
+ *               Given type.
+ *
+ * @returns false                   Type is RBP (can be written more than once).
+ *          true                    Type is OTP (can be written only once).
+ */
+bool sotp_is_otp_type(uint32_t type);
+
+/**
+ * @brief Returns one item of data programmed on Flash, given type.
+ *
+ * @param [in] type
+ *               Type of stored item (must be between 0-15).
+ *
+ * @param [in] buf_len_bytes
+ *               Length of input buffer in bytes.
+ *
+ * @param [in] buf
+ *               Buffer to store data on (must be aligned to a 32 bit boundary).
+ *
+ * @param [out] actual_len_bytes.
+ *               Actual length of returned data
+ *
+ * @returns SOTP_SUCCESS           Value was found on Flash.
+ *          SOTP_NOT_FOUND         Value was not found on Flash.
+ *          SOTP_READ_ERROR        Physical error reading data.
+ *          SOTP_DATA_CORRUPT      Data on Flash is corrupt.
+ *          SOTP_BAD_VALUE         Bad value in any of the parameters.
+ *          SOTP_BUFF_TOO_SMALL    Not enough memory in user buffer.
+ *          SOTP_BUFF_NOT_ALIGNED  Buffer not aligned to 32 bits.
+ */
+sotp_result_e sotp_get(uint32_t type, uint16_t buf_len_bytes, uint32_t *buf, uint16_t *actual_len_bytes);
+
+/**
+ * @brief Returns one item of data programmed on Flash, given type.
+ *
+ * @param [in] type
+ *               Type of stored item.
+ *
+ * @param [out] actual_len_bytes.
+ *               Actual length of item
+ *
+ * @returns SOTP_SUCCESS           Value was found on Flash.
+ *          SOTP_NOT_FOUND         Value was not found on Flash.
+ *          SOTP_READ_ERROR        Physical error reading data.
+ *          SOTP_DATA_CORRUPT      Data on Flash is corrupt.
+ *          SOTP_BAD_VALUE         Bad value in any of the parameters.
+ */
+sotp_result_e sotp_get_item_size(uint32_t type, uint16_t *actual_len_bytes);
+
+
+/**
+ * @brief Programs one item of data on Flash, given type.
+ *
+ * @param [in] type
+ *               Type of stored item (must be between 0-15).
+ *
+ * @param [in] buf_len_bytes
+ *               Item length in bytes.
+ *
+ * @param [in] buf
+ *               Buffer containing data  (must be aligned to a 32 bit boundary).
+ *
+ * @returns SOTP_SUCCESS           Value was successfully written on Flash.
+ *          SOTP_WRITE_ERROR       Physical error writing data.
+ *          SOTP_BAD_VALUE         Bad value in any of the parameters.
+ *          SOTP_FLASH_AREA_TOO_SMALL
+ *                                 Not enough space in Flash area.
+ *          SOTP_BUFF_NOT_ALIGNED  Buffer not aligned to 32 bits.
+ *          SOTP_ALREADY_EXISTS    Item (OTP type) already exists.
+ *
+ */
+sotp_result_e sotp_set(uint32_t type, uint16_t buf_len_bytes, const uint32_t *buf);
+
+#ifdef SOTP_TESTING
+/**
+ * @brief Delete an item from flash.
+ *
+ * @param [in] type
+ *               Type of stored item (must be between 0-15).
+ *
+ * @param [in] buf_len_bytes
+ *               Item length in bytes.
+ *
+ * @param [in] buf
+ *               Buffer containing data  (must be aligned to a 32 bit boundary).
+ *
+ * @returns SOTP_SUCCESS           Value was successfully written on Flash.
+ *          SOTP_WRITE_ERROR       Physical error writing data.
+ *          SOTP_BAD_VALUE         Bad value in any of the parameters.
+ *          SOTP_FLASH_AREA_TOO_SMALL
+ *                                 Not enough space in Flash area.
+ *          SOTP_BUFF_NOT_ALIGNED  Buffer not aligned to 32 bits.
+ *
+ */
+sotp_result_e sotp_delete(uint32_t type);
+
+/**
+ * @brief Programs one item of data on Flash, given type. No OTP existing check.
+ *
+ * @param [in] type
+ *               Type of stored item (must be between 0-15).
+ *
+ * @param [in] buf_len_bytes
+ *               Item length in bytes.
+ *
+ * @param [in] buf
+ *               Buffer containing data  (must be aligned to a 32 bit boundary).
+ *
+ * @returns SOTP_SUCCESS           Value was successfully written on Flash.
+ *          SOTP_WRITE_ERROR       Physical error writing data.
+ *          SOTP_BAD_VALUE         Bad value in any of the parameters.
+ *          SOTP_FLASH_AREA_TOO_SMALL
+ *                                 Not enough space in Flash area.
+ *          SOTP_BUFF_NOT_ALIGNED  Buffer not aligned to 32 bits.
+ *
+ */
+sotp_result_e sotp_set_for_testing(uint32_t type, uint16_t buf_len_bytes, const uint32_t *buf);
+#endif
+
+/**
+ * @brief Initializes SOTP component.
+ *
+ * @returns SOTP_SUCCESS       Initialization completed successfully.
+ *          SOTP_READ_ERROR    Physical error reading data.
+ *          SOTP_WRITE_ERROR   Physical error writing data (on recovery).
+ *          SOTP_FLASH_AREA_TOO_SMALL
+ *                             Not enough space in Flash area.
+ */
+sotp_result_e sotp_init(void);
+
+/**
+ * @brief Deinitializes SOTP component.
+ *        Warning: This function is not thread safe and should not be called
+ *        concurrently with other SOTP functions.
+ *
+ * @returns SOTP_SUCCESS       Deinitialization completed successfully.
+ */
+sotp_result_e sotp_deinit(void);
+
+/**
+ * @brief Reset Flash SOTP areas.
+ *        Warning: This function is not thread safe and should not be called
+ *        concurrently with other SOTP functions.
+ *
+ * @returns SOTP_SUCCESS       Reset completed successfully.
+ *          SOTP_READ_ERROR    Physical error reading data.
+ *          SOTP_WRITE_ERROR   Physical error writing data.
+ */
+sotp_result_e sotp_reset(void);
+
+#ifdef SOTP_TESTING
+
+/**
+ * @brief Initiate a forced garbage collection.
+ *
+ * @returns SOTP_SUCCESS       GC completed successfully.
+ *          SOTP_READ_ERROR    Physical error reading data.
+ *          SOTP_WRITE_ERROR   Physical error writing data.
+ *          SOTP_FLASH_AREA_TOO_SMALL
+ *                             Not enough space in Flash area.
+ */
+sotp_result_e sotp_force_garbage_collection(void);
+#endif
+
+/**
+ * @brief Returns one item of data programmed on Flash, given type.
+ *        This is the "initless" version of the function, traversing the flash if triggered.
+ *
+ * @param [in] type
+ *               Type of stored item (must be between 0-15).
+ *
+ * @param [in] buf_len_bytes
+ *               Length of input buffer in bytes.
+ *
+ * @param [in] buf
+ *               Buffer to store data on (must be aligned to a 32 bit boundary).
+ *
+ * @param [out] actual_len_bytes.
+ *               Actual length of returned data
+ *
+ * @returns SOTP_SUCCESS           Value was found on Flash.
+ *          SOTP_NOT_FOUND         Value was not found on Flash.
+ *          SOTP_READ_ERROR        Physical error reading data.
+ *          SOTP_DATA_CORRUPT      Data on Flash is corrupt.
+ *          SOTP_BAD_VALUE         Bad value in any of the parameters.
+ *          SOTP_BUFF_TOO_SMALL    Not enough memory in user buffer.
+ *          SOTP_BUFF_NOT_ALIGNED  Buffer not aligned to 32 bits.
+ */
+sotp_result_e sotp_probe(uint32_t type, uint16_t buf_len_bytes, uint32_t *buf, uint16_t *actual_len_bytes);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1095 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+// ----------------------------------------------------------- Includes -----------------------------------------------------------
+
+#include "sotp.h"
+
+#if (SYS_CONF_SOTP == SYS_CONF_SOTP_ENABLED)
+
+#include "sotp_shared_lock.h"
+#include "pal.h"
+#include <string.h>
+#include <stdio.h>
+#include "sotp_int.h"
+#include "sotp_log.h"
+
+// --------------------------------------------------------- Definitions ----------------------------------------------------------
+
+#define SOTP_FORMAT_REV 0
+
+#define MEDITATE_TIME_MS 100
+
+#define NUM_WRITE_RETRIES 100
+
+typedef enum {
+    AREA_STATE_NONE = 0,
+    AREA_STATE_EMPTY,
+    AREA_STATE_VALID,
+} area_state_e;
+
+#define INITIAL_CRC 0xFFFFFFFF
+
+#ifndef SOTP_PROBE_ONLY
+STATIC bool init_done = false;
+#ifdef SOTP_THREAD_SAFE
+STATIC int32_t init_attempts = 0;
+#endif
+STATIC uint8_t active_area;
+STATIC uint16_t active_area_version;
+// Must be aligned to the size of native integer, otherwise atomic add may not work
+STATIC uint32_t free_space_offset __attribute__((aligned(8)));
+STATIC uint32_t offset_by_type[SOTP_MAX_TYPES];
+STATIC sotp_shared_lock_t write_lock;
+
+
+// Currently disable OTP feature
+#if 0
+static const sotp_type_e otp_types[] =
+                        {SOTP_TYPE_FACTORY_DONE,
+                         SOTP_TYPE_ROT,
+                         SOTP_TYPE_TRUSTED_TIME_SRV_ID,
+                         SOTP_TYPE_EXECUTION_MODE};
+#endif
+#endif
+
+STATIC palSotpAreaData_t flash_area_params[SOTP_NUM_AREAS];
+
+// -------------------------------------------------- Local Functions Declaration ----------------------------------------------------
+
+// -------------------------------------------------- Functions Implementation ----------------------------------------------------
+
+sotp_result_e sotp_garbage_collection(uint16_t type, uint16_t buf_len_bytes, const uint32_t *buf);
+
+// Safely increment an integer (depending on if we're thread safe or not)
+// Parameters :
+// value         - [IN]   Pointer to variable.
+// size          - [IN]   Increment.
+// Return        : Value after increment.
+int32_t safe_increment(int32_t* value, int32_t increment)
+{
+#ifdef SOTP_THREAD_SAFE
+    return pal_osAtomicIncrement(value, increment);
+#else
+    *value += increment;
+    return *value;
+#endif
+}
+
+// Check whether a buffer is aligned.
+// Parameters :
+// buf           - [IN]   Data buffer.
+// size          - [IN]   Alignment size.
+// Return        : Boolean result.
+static inline bool is_buf_aligned(const void *buf, uint32_t size)
+{
+    return (((size_t) buf / size * size) == (size_t) buf);
+}
+
+// Pad an address to a specified size.
+// Parameters :
+// address       - [IN]   Address.
+// size          - [IN]   Size.
+// Return        : Padded address.
+static inline uint32_t pad_addr(uint32_t address, uint32_t size)
+{
+    return (((address-1) / size) + 1) * size;
+}
+
+// Flash access helper functions, using area and offset notations
+
+// Read from flash, given area and offset.
+// Parameters :
+// area          - [IN]   Flash area.
+// offset        - [IN]   Offset in area.
+// len_bytes     - [IN]   Length in bytes.
+// buf           - [IN]   Data buffer.
+// Return        : PAL_SUCCESS on success. Error code otherwise.
+palStatus_t sotp_flash_read_area(uint8_t area, uint32_t offset, uint32_t len_bytes, uint32_t *buf)
+{
+    return pal_internalFlashRead(len_bytes, flash_area_params[area].address + offset, buf);
+}
+
+#ifndef SOTP_PROBE_ONLY
+// Write to flash, given area and offset.
+// Parameters :
+// area          - [IN]   Flash area.
+// offset        - [IN]   Offset in area.
+// len_bytes     - [IN]   Length in bytes.
+// buf           - [IN]   Data buffer.
+// Return        : PAL_SUCCESS on success. Error code otherwise.
+palStatus_t sotp_flash_write_area(uint8_t area, uint32_t offset, uint32_t len_bytes, const uint32_t *buf)
+{
+    palStatus_t ret;
+    int i;
+    // On some boards, write action can fail due to HW limitations (like critical actions
+    // that disable all other actions). Just retry until success.
+    for (i = 0; i < NUM_WRITE_RETRIES; i++) {
+        ret = pal_internalFlashWrite(len_bytes, flash_area_params[area].address + offset, buf);
+        if (!ret) {
+            return ret;
+        }
+        pal_osDelay(1);
+    }
+    return ret;
+}
+
+// Erase a flash area, given area.
+// Parameters :
+// area          - [IN]   Flash area.
+// Return        : PAL_SUCCESS on success. Error code otherwise.
+palStatus_t sotp_flash_erase_area(uint8_t area)
+{
+    palStatus_t ret;
+    int i;
+    // On some boards, write action can fail due to HW limitations (like critical actions
+    // that disable all other actions). Just retry until success.
+    for (i = 0; i < NUM_WRITE_RETRIES; i++) {
+        ret = pal_internalFlashErase(flash_area_params[area].address, flash_area_params[area].size);
+        if (!ret) {
+            return ret;
+        }
+        pal_osDelay(1);
+    }
+    return ret;
+}
+#endif
+
+// CRC32 calculation. Supports "rolling" calculation (using the initial value).
+// Parameters :
+// init_crc      - [IN]   Initial CRC.
+// data_len      - [IN]   Buffer's data length.
+// data_buf      - [IN]   Data buffer.
+// Return        : CRC.
+STATIC uint32_t crc32(uint32_t init_crc, uint32_t data_len, uint8_t *data_buf)
+{
+    uint32_t i, j;
+    uint32_t crc, mask;
+
+    crc = init_crc;
+    for (i = 0; i < data_len; i++) {
+       crc = crc ^ (uint32_t) (data_buf[i]);
+       for (j = 0; j < 8; j++) {
+          mask = -(crc & 1);
+          crc = (crc >> 1) ^ (0xEDB88320 & mask);
+       }
+    }
+    return crc;
+}
+
+// Scan start of latest continuous empty area in flash area.
+// Parameters :
+// area          - [IN]   Flash area.
+// offset        - [OUT]  Blank chunk offset.
+// Return        : PAL_SUCCESS on success. Error code otherwise.
+STATIC palStatus_t calc_empty_space(uint8_t area, uint32_t *offset)
+{
+    uint32_t buf[32];
+    uint8_t *chbuf;
+    uint32_t i, j;
+    palStatus_t ret;
+
+    *offset = flash_area_params[area].size;
+    for (i = 0; i < flash_area_params[area].size / sizeof(buf); i++) {
+        *offset -= sizeof(buf);
+        ret = sotp_flash_read_area(area, *offset, sizeof(buf), buf);
+        if (ret != PAL_SUCCESS)
+            return ret;
+        chbuf = (uint8_t *) buf;
+        for (j = sizeof(buf); j > 0; j--) {
+            if (chbuf[j-1] != SOTP_BLANK_FLASH_VAL) {
+                *offset += j;
+                return PAL_SUCCESS;
+            }
+        }
+    }
+    return PAL_SUCCESS;
+}
+
+// Read a record from a given area and offset.
+// Parameters :
+// area          - [IN]   Flash area.
+// offset        - [IN]   Record offset.
+// buf_len_bytes - [IN]   Length of user buffer in byte.
+// buf           - [IN]   User buffer.
+// actual_len_bytes
+//               - [Out]  Actual length of returned data.
+// validate_only - [IN]   Just validate (don't return user data).
+// valid         - [Out]  Is record valid.
+// type          - [Out]  Record type.
+// flags         - [Out]  Record flags.
+// next_offset   - [Out]  If valid, offset of next record.
+// Return        : PAL_SUCCESS on success. Error code otherwise.
+STATIC sotp_result_e read_record(uint8_t area, uint32_t offset, uint16_t buf_len_bytes, uint32_t *buf,
+                                 uint16_t *actual_len_bytes, bool validate_only, bool *valid,
+                                 uint16_t *type, uint16_t *flags, uint32_t *next_offset)
+{
+    uint32_t int_buf[32];
+    uint32_t *buf_ptr;
+    uint32_t data_len, chunk_len;
+    palStatus_t pal_ret;
+    record_header_t header;
+    uint32_t crc = INITIAL_CRC;
+
+    SOTP_LOG_APPEND("read_record area:%d offs:%d len:%d. ", area, offset, buf_len_bytes);
+
+    *valid = true;
+
+    pal_ret = sotp_flash_read_area(area, offset, sizeof(header), (uint32_t *) &header);
+    if (pal_ret != PAL_SUCCESS) {
+        PR_ERR("read_record: sotp_flash_read_area failed with ret 0x%lx\n", pal_ret);
+        return SOTP_READ_ERROR;
+    }
+
+    crc = crc32(crc, sizeof(header) - sizeof(header.mac), (uint8_t *) &header);
+
+    *actual_len_bytes = 0;
+    *type = header.type_and_flags & ~HEADER_FLAG_MASK;
+    *flags = header.type_and_flags & HEADER_FLAG_MASK;
+
+    if ((*type >= SOTP_MAX_TYPES) && (*type != SOTP_MASTER_RECORD_TYPE)) {
+        *valid = false;
+        return SOTP_SUCCESS;
+    }
+
+    data_len = header.length;
+    offset += sizeof(header);
+
+    // In case of validate only enabled, we use our internal buffer for data reading,
+    // instead of the user one. This allows us to use a smaller buffer, on which CRC
+    // is continuously calculated.
+    if (validate_only) {
+        buf_ptr = int_buf;
+        buf_len_bytes = sizeof(int_buf);
+    }
+    else {
+        if (data_len > buf_len_bytes) {
+            offset += data_len;
+            *actual_len_bytes = data_len;
+            *next_offset = pad_addr(offset, FLASH_MINIMAL_PROG_UNIT);
+            return SOTP_BUFF_TOO_SMALL;
+        }
+        buf_ptr = buf;
+    }
+
+    while (data_len) {
+        chunk_len = PAL_MIN(data_len, buf_len_bytes);
+        pal_ret = sotp_flash_read_area(area, offset, chunk_len, buf_ptr);
+        if (pal_ret != PAL_SUCCESS) {
+            PR_ERR("read_record: sotp_flash_read_area failed with ret 0x%lx\n", pal_ret);
+            return SOTP_READ_ERROR;
+        }
+        crc = crc32(crc, chunk_len, (uint8_t *) buf_ptr);
+        data_len -= chunk_len;
+        offset += chunk_len;
+    }
+
+    if (header.mac != crc) {
+        *valid = false;
+        return SOTP_SUCCESS;
+    }
+
+    *actual_len_bytes = header.length;
+    *next_offset = pad_addr(offset, FLASH_MINIMAL_PROG_UNIT);
+
+    return SOTP_SUCCESS;
+}
+
+#ifndef SOTP_PROBE_ONLY
+// Write a record in a given area and offset.
+// Parameters :
+// area          - [IN]   Flash area.
+// offset        - [IN]   Record offset.
+// type          - [IN]   Record type.
+// flags         - [IN]   Record flags
+// data_len      - [IN]   Record's data length.
+// data_buf      - [IN]   Record's data buffer.
+// next_offset   - [Out]  offset of next record.
+// Return        : SOTP_SUCCESS on success. Error code otherwise.
+STATIC sotp_result_e write_record(uint8_t area, uint32_t offset, uint16_t type, uint16_t flags,
+                                  uint32_t data_len, const uint32_t *data_buf, uint32_t *next_offset)
+{
+    record_header_t header;
+    uint32_t crc = INITIAL_CRC;
+    palStatus_t pal_ret;
+    uint32_t write_len;
+    SOTP_LOG_APPEND("write_record area:%d offs:%d len:%d type:%d. ", area, offset, data_len, type);
+
+    header.type_and_flags = type | flags;
+    header.length = data_len;
+    header.mac = 0; // Satisfy compiler
+    crc = crc32(crc, sizeof(header) - sizeof(header.mac), (uint8_t *) &header);
+    if (data_len)
+        crc = crc32(crc, data_len, (uint8_t *) data_buf);
+    header.mac = crc;
+
+    pal_ret = sotp_flash_write_area(area, offset, sizeof(header), (uint32_t *)&header);
+    if (pal_ret != PAL_SUCCESS) {
+        return SOTP_WRITE_ERROR;
+    }
+
+    if (data_len) {
+        offset += sizeof(header);
+        write_len = data_len;
+        pal_ret = sotp_flash_write_area(area, offset, write_len, data_buf);
+        if (pal_ret != PAL_SUCCESS) {
+            return SOTP_WRITE_ERROR;
+        }
+        offset += data_len;
+    }
+
+    *next_offset = pad_addr(offset, FLASH_MINIMAL_PROG_UNIT);
+    return SOTP_SUCCESS;
+}
+
+// Write a master record in a given area.
+// Parameters :
+// area          - [IN]   Flash area.
+// version       - [IN]   Version.
+// next_offset   - [Out]  offset of next record.
+// Return        : SOTP_SUCCESS on success. Error code otherwise.
+STATIC sotp_result_e write_master_record(uint8_t area, uint16_t version, uint32_t *next_offset)
+{
+    master_record_data_t master_rec;
+
+    master_rec.version = version;
+    master_rec.format_rev = SOTP_FORMAT_REV;
+    master_rec.reserved = 0;
+    return write_record(area, 0, SOTP_MASTER_RECORD_TYPE, 0, sizeof(master_rec),
+                        (uint32_t*) &master_rec, next_offset);
+}
+
+// Copy a record from a given area and offset to another offset in the other area.
+// Parameters :
+// from_area     - [IN]   Flash area to copy from.
+// from_offset   - [IN]   Record offset in current area.
+// to_offset     - [IN]   Record offset in new area.
+// next_offset   - [Out]  Offset of next record in the new area.
+// Return        : PAL_SUCCESS on success. Error code otherwise.
+STATIC sotp_result_e copy_record(uint8_t from_area, uint32_t from_offset, uint32_t to_offset,
+                                 uint32_t *next_offset)
+{
+    uint32_t int_buf[32];
+    uint32_t data_len, chunk_len;
+    palStatus_t pal_ret;
+    record_header_t header;
+    SOTP_LOG_APPEND("copy_record f_area:%d f_offs:%d t_offs:%d ",
+                    from_area, from_offset, to_offset);
+
+    // This function assumes that the source record is valid, so no need to recalculate CRC.
+
+    pal_ret = sotp_flash_read_area(from_area, from_offset, sizeof(header), (uint32_t *) &header);
+    if (pal_ret != PAL_SUCCESS) {
+        return SOTP_READ_ERROR;
+    }
+
+    SOTP_LOG_APPEND("type %d. ", header.type);
+
+    data_len = header.length;
+
+    // No need to copy records whose flags indicate deletion
+    if (header.type_and_flags & DELETE_ITEM_FLAG) {
+        *next_offset = pad_addr(to_offset, FLASH_MINIMAL_PROG_UNIT);
+        return SOTP_SUCCESS;
+    }
+
+    // no need to align record size here, as it won't change the outcome of this condition
+    if (to_offset + sizeof(header) + data_len >= flash_area_params[1-from_area].size) {
+        return SOTP_FLASH_AREA_TOO_SMALL;
+    }
+
+    pal_ret = sotp_flash_write_area(1-from_area, to_offset, sizeof(header), (uint32_t *)&header);
+    if (pal_ret != PAL_SUCCESS) {
+        return SOTP_WRITE_ERROR;
+    }
+
+    from_offset += sizeof(header);
+    to_offset += sizeof(header);
+
+    while (data_len) {
+        chunk_len = PAL_MIN(data_len, sizeof(int_buf));
+        pal_ret = sotp_flash_read_area(from_area, from_offset, chunk_len, int_buf);
+        if (pal_ret != PAL_SUCCESS) {
+            return SOTP_READ_ERROR;
+        }
+        pal_ret = sotp_flash_write_area(1-from_area, to_offset, chunk_len, int_buf);
+        if (pal_ret != PAL_SUCCESS) {
+            return SOTP_WRITE_ERROR;
+        }
+
+        data_len -= chunk_len;
+        from_offset += chunk_len;
+        to_offset += chunk_len;
+    }
+
+    *next_offset = pad_addr(to_offset, FLASH_MINIMAL_PROG_UNIT);
+    return SOTP_SUCCESS;
+}
+
+// Perform the garbage collection process.
+// Parameters :
+// type          - [IN]   Item's type.
+// buf_len_bytes - [IN]   Item length in bytes.
+// buf           - [IN]   Pointer to user buffer.
+// Return      : SOTP_SUCCESS on success. Error code otherwise.
+sotp_result_e sotp_garbage_collection(uint16_t type, uint16_t buf_len_bytes, const uint32_t *buf)
+{
+    uint32_t curr_offset, new_area_offset, next_offset;
+    uint8_t curr_area;
+    sotp_result_e ret;
+
+    SOTP_LOG_CREATE("GC. ");
+
+    new_area_offset = sizeof(record_header_t) + sizeof(master_record_data_t);
+
+    // If GC is triggered by a set item request, we need to first write that item in the new location,
+    // otherwise we may either write it twice (if already included), or lose it in case we decide
+    // to skip it at garbage collection phase (and the system crashes).
+    if (type != SOTP_NO_TYPE) {
+        ret = write_record(1 - active_area, new_area_offset, type, 0, buf_len_bytes, buf, &next_offset);
+        if (ret != SOTP_SUCCESS) {
+            PR_ERR("sotp_garbage_collection: write_record failed with ret 0x%x\n", ret);
+            SOTP_LOG_FINALIZE();
+            return ret;
+        }
+        offset_by_type[type] = new_area_offset | (1-active_area) << (sizeof(offset_by_type[type])*8 - 1);
+        new_area_offset = next_offset;
+    }
+
+    // Now iterate on all types, and copy the ones who have valid offsets (meaning that they exist)
+    // to the other area.
+    for (type = 0; type < SOTP_MAX_TYPES; type++) {
+        curr_offset = offset_by_type[type];
+        curr_area = (uint8_t) (curr_offset >> (sizeof(curr_offset)*8 - 1));
+        curr_offset &= ~(1UL << (sizeof(curr_offset)*8 - 1));
+        if ((!curr_offset) || (curr_area != active_area))
+            continue;
+        ret = copy_record(curr_area, curr_offset, new_area_offset, &next_offset);
+        if (ret != SOTP_SUCCESS) {
+            PR_ERR("sotp_garbage_collection: copy_record failed with ret 0x%x\n", ret);
+            SOTP_LOG_FINALIZE();
+            return ret;
+        }
+        offset_by_type[type] = new_area_offset | (1-curr_area) << (sizeof(offset_by_type[type])*8 - 1);
+        new_area_offset = next_offset;
+    }
+
+    // Now write master record, with version incremented by 1.
+    active_area_version++;
+    ret = write_master_record(1 - active_area, active_area_version, &next_offset);
+    if (ret != SOTP_SUCCESS) {
+        PR_ERR("sotp_garbage_collection: write_master_record failed with ret 0x%x\n", ret);
+        SOTP_LOG_FINALIZE();
+        return ret;
+    }
+
+    free_space_offset = new_area_offset;
+
+    // Only now we can switch to the new active area
+    active_area = 1 - active_area;
+
+    // The older area doesn't concern us now. Erase it now.
+    if (sotp_flash_erase_area(1 - active_area) != PAL_SUCCESS) {
+        ret = SOTP_WRITE_ERROR;
+    }
+
+    SOTP_LOG_FINALIZE();
+    return ret;
+}
+
+
+// Get API logics helper function. Serves both Get & Get item size APIs.
+// Parameters :
+// type             - [IN]   Item's type.
+// buf_len_bytes    - [IN]   Item length in bytes.
+// buf              - [IN]   Pointer to user buffer.
+// actual_len_bytes - [OUT]  Actual length of returned data.
+// validate_only    - [IN]   Just validate (don't return user data).
+// Return      : SOTP_SUCCESS on success. Error code otherwise.
+STATIC sotp_result_e sotp_do_get(uint8_t type, uint16_t buf_len_bytes, uint32_t *buf, uint16_t *actual_len_bytes,
+                          bool validate_only)
+{
+    sotp_result_e ret = SOTP_SUCCESS;
+    uint32_t record_offset, next_offset;
+    uint8_t area;
+    uint16_t read_type, flags;
+    bool valid;
+
+    SOTP_LOG_CREATE("get type:%d len:%d. ", type, buf_len_bytes);
+
+    if (!init_done) {
+        ret = sotp_init();
+        if (ret != SOTP_SUCCESS) {
+            SOTP_LOG_FINALIZE();
+            return ret;
+        }
+    }
+
+    if (type >= SOTP_MAX_TYPES) {
+        SOTP_LOG_FINALIZE();
+        return SOTP_BAD_VALUE;
+    }
+
+
+    if (!buf)
+        buf_len_bytes = 0;
+
+    if (buf_len_bytes && !is_buf_aligned(buf, sizeof(uint32_t))) {
+        SOTP_LOG_FINALIZE();
+        return SOTP_BUFF_NOT_ALIGNED;
+    }
+
+    // This loop is required for the case we try to perform reading while GC is in progress.
+    // If so, we have the following cases:
+    // 1. Record is still in the older area. It will be successfully read.
+    // 2. Record was already copied to the new area. Now the offset_by_type indicates it.
+    // So we have two cases here:
+    // a. Read from new area succeeds. Everything's OK.
+    // b. Read fails (either physically or CRC error). So we know that if the area taken
+    //    from offset_by_type is different from the active area, a GC is in progress, so
+    //    retry the operation.
+    for (;;) {
+        record_offset = offset_by_type[type];
+        if (!record_offset) {
+            SOTP_LOG_FINALIZE();
+            return SOTP_NOT_FOUND;
+        }
+
+        area = (uint8_t) (record_offset >> (sizeof(record_offset)*8 - 1));
+        record_offset &= ~(1UL << (sizeof(record_offset)*8 - 1));
+
+        ret = read_record(area, record_offset, buf_len_bytes, buf,
+                          actual_len_bytes, validate_only, &valid,
+                          &read_type, &flags, &next_offset);
+        if ((ret == SOTP_SUCCESS) && valid)
+            break;
+        // In case area is the same as expected, GC is not in progress and we have a genuine error.
+        if (area == active_area) {
+            if (ret == SOTP_SUCCESS) {
+                ret = SOTP_DATA_CORRUPT;
+            }
+            PR_ERR("sotp_do_get: read_record failed with ret 0x%x\n", ret);
+            SOTP_LOG_FINALIZE();
+            return ret;
+        }
+    }
+
+    SOTP_LOG_FINALIZE();
+    return SOTP_SUCCESS;
+}
+
+// Start of API functions
+
+bool sotp_is_otp_type(uint32_t type)
+{
+// Currently disable OTP feature
+#if 0
+    unsigned int i;
+    for (i = 0; i < sizeof(otp_types) / sizeof(sotp_type_e); i++) {
+        if (otp_types[i] == type) {
+            return true;
+        }
+    }
+#endif
+    return false;
+}
+
+sotp_result_e sotp_get(uint32_t type, uint16_t buf_len_bytes, uint32_t *buf, uint16_t *actual_len_bytes)
+{
+    return sotp_do_get((uint8_t)type, buf_len_bytes, buf, actual_len_bytes, false);
+}
+
+sotp_result_e sotp_get_item_size(uint32_t type, uint16_t *actual_len_bytes)
+{
+    return sotp_do_get((uint8_t)type, 0, NULL, actual_len_bytes, true);
+}
+
+STATIC sotp_result_e sotp_do_set(uint32_t type, uint16_t buf_len_bytes, const uint32_t *buf,
+                          bool ignore_otp, uint16_t flags)
+{
+    sotp_result_e ret = SOTP_SUCCESS;
+    uint32_t record_offset, record_size, new_free_space;
+    uint32_t next_offset;
+    uint8_t save_active_area;
+
+    SOTP_LOG_CREATE("set type:%d len:%d. ", type, buf_len_bytes);
+
+    if (!init_done) {
+        ret = sotp_init();
+        if (ret != SOTP_SUCCESS) {
+            SOTP_LOG_FINALIZE();
+            return ret;
+        }
+    }
+
+    if (type >= SOTP_MAX_TYPES) {
+        SOTP_LOG_FINALIZE();
+        return SOTP_BAD_VALUE;
+    }
+
+    if (!buf)
+        buf_len_bytes = 0;
+
+    if (buf_len_bytes && !is_buf_aligned(buf, sizeof(uint32_t))) {
+        SOTP_LOG_FINALIZE();
+        return SOTP_BUFF_NOT_ALIGNED;
+    }
+
+    if ((flags & DELETE_ITEM_FLAG) && !offset_by_type[type]) {
+        SOTP_LOG_FINALIZE();
+        return SOTP_NOT_FOUND;
+    }
+
+    if (!ignore_otp && sotp_is_otp_type(type) && offset_by_type[(uint8_t)type]) {
+        SOTP_LOG_FINALIZE();
+        return SOTP_ALREADY_EXISTS;
+    }
+
+    // writers do not lock each other exclusively, but can operate in parallel.
+    // Shared lock is in order to prevent GC from operating (which uses exclusive lock).
+    if (sotp_sh_lock_shared_lock(write_lock) != SOTP_SHL_SUCCESS) {
+        PR_ERR("sotp_set: sotp_sh_lock_shared_lock failed\n");
+        SOTP_LOG_FINALIZE();
+        return SOTP_OS_ERROR;
+    }
+
+    save_active_area = active_area;
+    record_size = pad_addr(sizeof(record_header_t) + buf_len_bytes, FLASH_MINIMAL_PROG_UNIT);
+
+    // Parallel operation of writers is allowed due to this atomic operation. This operation
+    // produces an offset on which each writer can work separately, without being interrupted
+    // by the other writer. The only mutual resource here is free_space_offset - which
+    // gets the correct value because of this atomic increment.
+    new_free_space = safe_increment((int32_t *) &free_space_offset, record_size);
+    record_offset = new_free_space - record_size;
+
+    // If we cross the area limit, we need to invoke GC. However, we should consider all the cases
+    // where writers work in parallel, and we only want the FIRST writer to invoke GC.
+    if (new_free_space >= flash_area_params[active_area].size) {
+        // In the case we have crossed the limit, but the initial offset was still before the limit, this
+        // means we are the first writer (common case). Exclusively lock write_lock, and invoke GC.
+        if (record_offset < flash_area_params[active_area].size) {
+            if (sotp_sh_lock_promote(write_lock) != SOTP_SHL_SUCCESS) {
+                SOTP_LOG_FINALIZE();
+                return SOTP_OS_ERROR;
+            }
+            ret = sotp_garbage_collection((uint8_t)type, buf_len_bytes, buf);
+            sotp_sh_lock_exclusive_release(write_lock);
+            SOTP_LOG_FINALIZE();
+            return ret;
+        }
+        else {
+            SOTP_LOG_APPEND("S ");
+            // In the case we have crossed the limit, and the initial offset was also after the limit,
+            // this means we are not first writer (uncommon case). Just wait for GC to complete.
+            // then write record.
+            if (sotp_sh_lock_shared_release(write_lock) != SOTP_SHL_SUCCESS) {
+                PR_ERR("sotp_set: sotp_sh_lock_shared_release failed\n");
+                SOTP_LOG_FINALIZE();
+                return SOTP_OS_ERROR;
+            }
+            for (;;) {
+                if (sotp_sh_lock_shared_lock(write_lock) != SOTP_SHL_SUCCESS) {
+                    PR_ERR("sotp_set: sotp_sh_lock_shared_lock failed\n");
+                    SOTP_LOG_FINALIZE();
+                    return SOTP_OS_ERROR;
+                }
+                if (save_active_area != active_area) {
+                    SOTP_LOG_APPEND("E ");
+                    break;
+                }
+                if (sotp_sh_lock_shared_release(write_lock) != SOTP_SHL_SUCCESS) {
+                    PR_ERR("sotp_set: sotp_sh_lock_shared_lock failed\n");
+                    SOTP_LOG_FINALIZE();
+                    return SOTP_OS_ERROR;
+                }
+            }
+            new_free_space = safe_increment((int32_t *) &free_space_offset, record_size);
+            record_offset = new_free_space - free_space_offset;
+        }
+    }
+
+    // Now write the record
+    ret = write_record(active_area, record_offset, (uint8_t)type, flags, buf_len_bytes, buf, &next_offset);
+    if (ret != SOTP_SUCCESS) {
+        PR_ERR("sotp_set: write_record failed with err code 0x%x\n", ret);
+        sotp_sh_lock_shared_release(write_lock);
+        SOTP_LOG_FINALIZE();
+        return ret;
+    }
+
+    // Update offset_by_type. High bit indicates area.
+    if (flags & DELETE_ITEM_FLAG)
+        offset_by_type[type] = 0;
+    else
+        offset_by_type[type] = record_offset | (active_area << (sizeof(offset_by_type[type])*8 - 1));
+
+    if (sotp_sh_lock_shared_release(write_lock) != SOTP_SHL_SUCCESS) {
+        PR_ERR("sotp_set: sotp_sh_lock_shared_release failed\n");
+        SOTP_LOG_FINALIZE();
+        return SOTP_OS_ERROR;
+    }
+
+    SOTP_LOG_FINALIZE();
+    return SOTP_SUCCESS;
+}
+
+sotp_result_e sotp_set(uint32_t type, uint16_t buf_len_bytes, const uint32_t *buf)
+{
+    return sotp_do_set(type, buf_len_bytes, buf, false, 0);
+}
+
+#ifdef SOTP_TESTING
+
+sotp_result_e sotp_set_for_testing(uint32_t type, uint16_t buf_len_bytes, const uint32_t *buf)
+{
+    return sotp_do_set(type, buf_len_bytes, buf, true, 0);
+}
+
+sotp_result_e sotp_delete(uint32_t type)
+{
+    return sotp_do_set(type, 0, NULL, true, DELETE_ITEM_FLAG);
+}
+#endif
+
+sotp_result_e sotp_init(void)
+{
+    uint8_t area;
+    uint16_t type;
+    uint16_t flags;
+    palStatus_t pal_ret;
+    sotp_result_e ret = SOTP_SUCCESS;
+#ifdef SOTP_THREAD_SAFE
+    int32_t init_attempts_val;
+#endif
+    area_state_e area_state[SOTP_NUM_AREAS] = { AREA_STATE_NONE, AREA_STATE_NONE };
+    uint32_t free_space_offset_of_area[SOTP_NUM_AREAS] = { 0, 0 };
+    uint16_t versions[SOTP_NUM_AREAS] = { 0, 0 };
+    uint32_t next_offset;
+    master_record_data_t master_rec;
+    uint16_t actual_len_bytes;
+    bool valid;
+
+    if (init_done)
+        return SOTP_SUCCESS;
+
+    // This handles the case that init function is called by more than one thread concurrently.
+    // Only the one who gets the value of 1 in init_attempts_val will proceed, while others will
+    // wait until init is finished.
+#ifdef SOTP_THREAD_SAFE
+    init_attempts_val = safe_increment(&init_attempts, 1);
+    if (init_attempts_val != 1) {
+        while(!init_done)
+            pal_osDelay(MEDITATE_TIME_MS);
+        return SOTP_SUCCESS;
+    }
+#endif
+
+    memset(offset_by_type, 0, sizeof(offset_by_type));
+
+    if (sotp_sh_lock_create(&write_lock) != SOTP_SHL_SUCCESS) {
+        PR_ERR("sotp_init: sotp_sh_lock_create failed\n");
+        ret = SOTP_OS_ERROR;
+        goto init_end;
+    }
+
+    for (area = 0; area < SOTP_NUM_AREAS; area++) {
+        pal_ret = pal_internalFlashGetAreaInfo(area, &flash_area_params[area]);
+        if (pal_ret != PAL_SUCCESS) {
+            PR_ERR("sotp_init: pal_internalFlashGetAreaInfo failed with err code 0x%lx\n",
+                    (unsigned long) pal_ret);
+            ret = SOTP_OS_ERROR;
+            goto init_end;
+        }
+
+        // Find start of empty space at the end of the area. This serves for both
+        // knowing whether the area is empty and for the record traversal at the end.
+        pal_ret = calc_empty_space(area, &(free_space_offset_of_area[area]));
+        if (pal_ret != PAL_SUCCESS) {
+            PR_ERR("sotp_init: calc_empty_space failed with err code 0x%lx\n",
+                    (unsigned long) pal_ret);
+            ret = SOTP_READ_ERROR;
+            goto init_end;
+        }
+
+        if (!free_space_offset_of_area[area]) {
+            area_state[area] = AREA_STATE_EMPTY;
+            continue;
+        }
+
+        // Check validity of master record
+        ret = read_record(area, 0, sizeof(master_rec), (uint32_t *) &master_rec,
+                          &actual_len_bytes, false, &valid,
+                          &type, &flags, &next_offset);
+        if (ret != SOTP_SUCCESS) {
+            if (ret == SOTP_BUFF_TOO_SMALL) {
+                // Buf too small error means that we have a corrupt master record -
+                // treat it as such
+                valid = false;
+            }
+            else {
+                PR_ERR("sotp_init: read_record failed with err code 0x%x\n", ret);
+                goto init_end;
+            }
+        }
+
+        // We have a non valid master record, in a non-empty area. Just erase the area.
+        if ((!valid) || (type != SOTP_MASTER_RECORD_TYPE)) {
+            pal_ret = sotp_flash_erase_area(area);
+            if (pal_ret != PAL_SUCCESS) {
+                PR_ERR("sotp_init: sotp_flash_erase_area failed with err code 0x%lx\n",
+                        (unsigned long) pal_ret);
+                ret = SOTP_WRITE_ERROR;
+                goto init_end;
+            }
+            area_state[area] = AREA_STATE_EMPTY;
+            continue;
+        }
+        versions[area] = master_rec.version;
+
+        // Place free_space_offset after the master record (for the traversal,
+        // which takes place after this loop).
+        free_space_offset = next_offset;
+        area_state[area] = AREA_STATE_VALID;
+
+        // Unless both areas are valid (a case handled later), getting here means
+        // that we found our active area.
+        active_area = area;
+        active_area_version = versions[area];
+    }
+
+    // In case we have two empty areas, arbitrarily assign 0 to the active one.
+    if ((area_state[0] == AREA_STATE_EMPTY) && (area_state[1] == AREA_STATE_EMPTY)) {
+        active_area = 0;
+        ret = write_master_record(active_area, 1, &free_space_offset);
+        goto init_end;
+    }
+
+    // In case we have two valid areas, choose the one having the higher version (or 0
+    // in case of wrap around). Erase the other one.
+    if ((area_state[0] == AREA_STATE_VALID) && (area_state[1] == AREA_STATE_VALID)) {
+        if ((versions[0] > versions[1]) || (!versions[0]))
+            active_area = 0;
+        else
+            active_area = 1;
+        active_area_version = versions[active_area];
+        pal_ret = sotp_flash_erase_area(1 - active_area);
+        if (pal_ret != PAL_SUCCESS) {
+            PR_ERR("sotp_init: sotp_flash_erase_area failed with err code 0x%lx\n",
+                    (unsigned long) pal_ret);
+            ret = SOTP_WRITE_ERROR;
+            goto init_end;
+        }
+    }
+
+    // Traverse area until reaching the empty space at the end or until reaching a faulty record
+    while (free_space_offset < free_space_offset_of_area[active_area]) {
+        ret = read_record(active_area, free_space_offset, 0, NULL,
+                          &actual_len_bytes, true, &valid,
+                          &type, &flags, &next_offset);
+        if (ret != SOTP_SUCCESS) {
+            PR_ERR("sotp_init: read_record failed with err code 0x%x\n", ret);
+            goto init_end;
+        }
+        // In case we have a faulty record, this probably means that the system crashed when written.
+        // Perform a garbage collection, to make the the other area valid.
+        if (!valid) {
+            ret = sotp_garbage_collection(SOTP_NO_TYPE, 0, NULL);
+            break;
+        }
+        if (flags & DELETE_ITEM_FLAG)
+            offset_by_type[type] = 0;
+        else
+            offset_by_type[type] = free_space_offset | (active_area << (sizeof(offset_by_type[type])*8 - 1));
+        free_space_offset = next_offset;
+    }
+
+init_end:
+    init_done = true;
+    return ret;
+}
+
+sotp_result_e sotp_deinit(void)
+{
+    if (init_done) {
+        sotp_sh_lock_destroy(write_lock);
+    }
+
+#ifdef SOTP_THREAD_SAFE
+    init_attempts = 0;
+#endif
+    init_done = false;
+
+    return SOTP_SUCCESS;
+}
+
+sotp_result_e sotp_reset(void)
+{
+    uint8_t area;
+    palStatus_t pal_ret;
+
+    // Erase both areas, and reinitialize the module. This is totally not thread safe,
+    // as init doesn't take the case of re-initialization into account. It's OK, as this function
+    // should only be called in pre-production cases.
+    for (area = 0; area < SOTP_NUM_AREAS; area++) {
+        if (!init_done) {
+            pal_ret = pal_internalFlashGetAreaInfo(area, &flash_area_params[area]);
+            if (pal_ret != PAL_SUCCESS)
+                return SOTP_OS_ERROR;
+        }
+        pal_ret = sotp_flash_erase_area(area);
+        if (pal_ret != PAL_SUCCESS)
+            return SOTP_WRITE_ERROR;
+    }
+
+    sotp_deinit();
+    return sotp_init();
+}
+
+#ifdef SOTP_TESTING
+
+sotp_result_e sotp_force_garbage_collection(void)
+{
+    sotp_result_e ret;
+
+    if (!init_done) {
+        ret = sotp_init();
+        if (ret != SOTP_SUCCESS)
+            return ret;
+    }
+
+    if (sotp_sh_lock_exclusive_lock(write_lock) != SOTP_SHL_SUCCESS) {
+        PR_ERR("sotp_force_garbage_collection: sotp_sh_lock_exclusive_lock failed");
+        return SOTP_OS_ERROR;
+    }
+    ret = sotp_garbage_collection(SOTP_NO_TYPE, 0, NULL);
+    sotp_sh_lock_exclusive_release(write_lock);
+    return ret;
+}
+#endif
+
+#endif // SOTP_PROBE_ONLY
+
+#if defined(SOTP_PROBE_ONLY) || defined(SOTP_TESTING)
+sotp_result_e sotp_probe(uint32_t type, uint16_t buf_len_bytes, uint32_t *buf, uint16_t *actual_len_bytes)
+{
+
+    uint8_t area;
+    int sel_area = -1;
+    uint16_t read_type;
+    uint16_t flags;
+    palStatus_t pal_ret;
+    sotp_result_e ret = SOTP_SUCCESS, save_ret = SOTP_SUCCESS;
+    uint32_t free_space_offset_of_area = 0;
+    uint32_t curr_offset = 0, next_offset;
+    master_record_data_t master_rec;
+    uint16_t prev_version = 0;
+    uint16_t tmp_actual_len_bytes;
+    bool valid;
+    bool found = 0;
+
+    for (area = 0; area < SOTP_NUM_AREAS; area++) {
+        pal_ret = pal_internalFlashGetAreaInfo(area, &flash_area_params[area]);
+        if (pal_ret != PAL_SUCCESS) {
+            PR_ERR("sotp_probe: pal_internalFlashGetAreaInfo failed with err code 0x%lx\n",
+                    (unsigned long) pal_ret);
+            return SOTP_OS_ERROR;
+        }
+
+        // Check validity of master record
+        ret = read_record(area, 0, sizeof(master_rec), (uint32_t *) &master_rec,
+                          actual_len_bytes, false, &valid,
+                          &read_type, &flags, &next_offset);
+        if (ret != SOTP_SUCCESS) {
+            if (ret == SOTP_BUFF_TOO_SMALL) {
+                // Buf too small error means that we have a corrupt master record -
+                // treat it as such, move to next area.
+                continue;
+            }
+            else {
+                PR_ERR("sotp_probe_type: read_record failed with err code 0x%x\n", ret);
+                return ret;
+            }
+        }
+
+        // We have a non valid master record, move to next area.
+        if ((!valid) || (read_type != SOTP_MASTER_RECORD_TYPE)) {
+            continue;
+        }
+
+        // Use similar logic of init's way of handling two valid areas (without erasing them of course)
+        if ((area == 1) && (sel_area > 0)) {
+            if ((!prev_version) || (prev_version > master_rec.version)) {
+                // leave selected area as 0
+                break;
+            }
+        }
+
+        prev_version = master_rec.version;
+        curr_offset = next_offset;
+        sel_area = area;
+    }
+
+    if (sel_area < 0) {
+        return SOTP_NOT_FOUND;
+    }
+
+    area = (uint8_t) sel_area;
+    pal_ret = calc_empty_space(area, &free_space_offset_of_area);
+    if (pal_ret != PAL_SUCCESS) {
+        PR_ERR("sotp_probe: calc_empty_space failed with err code 0x%lx\n",
+                (unsigned long) pal_ret);
+        return SOTP_READ_ERROR;
+    }
+
+    // Traverse area until reaching the empty space at the end or until reaching a faulty record
+    found = false;
+    while (curr_offset < free_space_offset_of_area) {
+        // first just verify, then read to user buffer
+        ret = read_record(area, curr_offset, 0, NULL,
+                          &tmp_actual_len_bytes, true, &valid,
+                          &read_type, &flags, &next_offset);
+        if (ret != SOTP_SUCCESS) {
+            PR_ERR("sotp_probe: read_record failed with err code 0x%x\n", ret);
+            return ret;
+        }
+        if (!valid) {
+            break;
+        }
+
+        if (read_type == type) {
+            if (flags & DELETE_ITEM_FLAG) {
+                found = false;
+            }
+            else {
+                save_ret = read_record(area, curr_offset, buf_len_bytes, buf,
+                                  actual_len_bytes, false, &valid,
+                                  &read_type, &flags, &next_offset);
+                found = true;
+            }
+        }
+        curr_offset = next_offset;
+    }
+
+    if (!found) {
+        return SOTP_NOT_FOUND;
+    }
+
+    return save_ret;
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp_int.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+
+#ifndef __SOTP_INT_H
+#define __SOTP_INT_H
+
+#include <stdint.h>
+#include "mbed-trace/mbed_trace.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TRACE_GROUP                     "sotp"
+
+#ifdef ESFS_INTERACTIVE_TEST
+#define STATIC
+#define PR_ERR printf
+#define PR_INFO printf
+#define PR_DEBUG printf
+#else
+#define STATIC static
+#define PR_ERR tr_err
+#define PR_INFO tr_info
+#define PR_DEBUG tr_debug
+#endif
+
+
+typedef struct {
+    uint16_t type_and_flags;
+    uint16_t length;
+    uint32_t mac;
+} record_header_t __attribute__((aligned(4)));
+
+#define FLASH_MINIMAL_PROG_UNIT 8
+
+#define DELETE_ITEM_FLAG        0x8000
+#define HEADER_FLAG_MASK        0xF000
+#define SOTP_MASTER_RECORD_TYPE 0x0FFE
+#define SOTP_NO_TYPE            0x0FFF
+
+#define MASTER_RECORD_BLANK_FIELD_SIZE FLASH_MINIMAL_PROG_UNIT
+
+
+typedef struct {
+    uint16_t version;
+    uint16_t format_rev;
+    uint32_t reserved;
+} master_record_data_t __attribute__((aligned(4)));
+
+#define MASTER_RECORD_SIZE sizeof(master_record_data_t)
+
+palStatus_t sotp_flash_read_area(uint8_t area, uint32_t offset, uint32_t len_bytes, uint32_t *buf);
+palStatus_t sotp_flash_write_area(uint8_t area, uint32_t offset, uint32_t len_bytes, const uint32_t *buf);
+palStatus_t sotp_flash_erase_area(uint8_t area);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp_log.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+// ----------------------------------------------------------- Includes -----------------------------------------------------------
+
+
+#include "pal.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "sotp_log.h"
+
+#if SOTP_LOG
+
+#define LINE_SIZE 1024
+typedef struct {
+    uint64_t start_time;
+    uint64_t end_time;
+    uint32_t action_id;
+    uint32_t dummy;
+    char line[LINE_SIZE];
+} sotp_log_entry_t;
+
+#define MAX_ENTRIES 64
+typedef struct {
+    uint32_t num_entries;
+    uint32_t curr_entry_ind;
+    uint32_t ind_stack_ptr;
+    uint32_t ind_stack[4];
+    sotp_log_entry_t entries[MAX_ENTRIES];
+} sotp_thr_log_t;
+
+// Must be aligned to the size of native integer, otherwise atomic add may not work
+static uint32_t action_id_ctr  __attribute__((aligned(8)));
+#define MAX_NUMBER_OF_THREADS 9
+static sotp_thr_log_t thr_logs[MAX_NUMBER_OF_THREADS];
+
+// Initialize SOTP logs.
+// Parameters :
+// Return   : None.
+void sotp_log_init(void)
+{
+    action_id_ctr = 0;
+    memset(thr_logs, 0, sizeof(thr_logs));
+}
+
+// Create an SOTP log entry.
+// Parameters :
+// args     - [IN]   format (as in printf).
+// args     - [IN]   arg list (as in printf) to log.
+// Return   : None.
+void sotp_log_create(char *fmt, ...)
+{
+    int thr = pal_osThreadGetId();
+    sotp_thr_log_t *thr_log = &thr_logs[thr];
+    sotp_log_entry_t *entry;
+    uint32_t entry_ind;
+    va_list args;
+    uint32_t action_id;
+
+    action_id = pal_osAtomicIncrement((int32_t *) &action_id_ctr, 1);
+
+    if (thr_log->num_entries < MAX_ENTRIES) {
+        thr_log->num_entries++;
+    }
+
+    entry_ind = thr_log->curr_entry_ind;
+    thr_logs->ind_stack[thr_logs->ind_stack_ptr++] = entry_ind;
+    thr_log->curr_entry_ind = (thr_log->curr_entry_ind + 1) % MAX_ENTRIES;
+    entry = &thr_log->entries[entry_ind];
+    entry->start_time = pal_osKernelSysTick();
+    entry->action_id = action_id;
+
+    va_start(args, fmt);
+    vsnprintf(entry->line, LINE_SIZE, fmt, args);
+    va_end(args);
+}
+
+// Append to an SOTP log entry.
+// Parameters :
+// args     - [IN]   format (as in printf).
+// args     - [IN]   arg list (as in printf) to log.
+// Return   : None.
+void sotp_log_append(char *fmt, ...)
+{
+    int thr = pal_osThreadGetId();
+    sotp_thr_log_t *thr_log = &thr_logs[thr];
+    sotp_log_entry_t *entry;
+    uint32_t entry_ind;
+    va_list args;
+
+    if (!thr_logs->ind_stack_ptr) {
+        return;
+    }
+
+    entry_ind = thr_logs->ind_stack[thr_logs->ind_stack_ptr-1];
+    entry = &thr_log->entries[entry_ind];
+    va_start(args, fmt);
+    vsnprintf(entry->line + strlen(entry->line), LINE_SIZE-strlen(entry->line), fmt, args);
+    va_end(args);
+}
+
+// Finalize an SOTP log entry.
+// Parameters :
+// Return   : None.
+void sotp_log_finalize(void)
+{
+    int thr = pal_osThreadGetId();
+    sotp_thr_log_t *thr_log = &thr_logs[thr];
+    sotp_log_entry_t *entry;
+    uint32_t entry_ind;
+
+    if (!thr_logs->ind_stack_ptr) {
+        return;
+    }
+    entry_ind = thr_logs->ind_stack[--thr_logs->ind_stack_ptr];
+    entry = &thr_log->entries[entry_ind];
+    entry->end_time = pal_osKernelSysTick();
+}
+
+// Print SOTP log (sorted by start time).
+// Parameters :
+// Return   : None.
+void sotp_log_print_log(void)
+{
+    int pending_logs;
+    int log_inds[MAX_NUMBER_OF_THREADS];
+    int i, thr;
+    uint64_t earliest;
+    sotp_log_entry_t *curr_entry, *entry_to_print;
+    uint64_t ref_time;
+
+    pending_logs = 0;
+    ref_time = (uint64_t) -1;
+    for (i = 0; i < MAX_NUMBER_OF_THREADS; i++) {
+        if (!thr_logs[i].num_entries) {
+            log_inds[i] = -1;
+            continue;
+        }
+        pending_logs++;
+        if (thr_logs[i].num_entries < MAX_ENTRIES)
+            log_inds[i] = 0;
+        else
+            log_inds[i] = thr_logs[i].curr_entry_ind;
+        curr_entry = &thr_logs[i].entries[log_inds[i]];
+        if (curr_entry->start_time && (curr_entry->start_time < ref_time)) {
+            ref_time = curr_entry->start_time;
+        }
+    }
+
+    while (pending_logs) {
+        earliest = (uint64_t) -1;
+        for (i = 0; i < MAX_NUMBER_OF_THREADS; i++) {
+            if (log_inds[i] < 0)
+                continue;
+            curr_entry = &thr_logs[i].entries[log_inds[i]];
+            if (curr_entry->start_time < earliest) {
+                entry_to_print = curr_entry;
+                earliest = curr_entry->start_time;
+                thr = i;
+            }
+        }
+        printf("%d (+%9ld-%9ld) #%9d %s\n",
+                thr,
+                entry_to_print->start_time - ref_time,
+                entry_to_print->end_time?(entry_to_print->end_time - entry_to_print->start_time) : 0,
+                entry_to_print->action_id,
+                entry_to_print->line);
+        ref_time = entry_to_print->start_time;
+        log_inds[thr] = (log_inds[thr] + 1) % MAX_ENTRIES;
+        if (log_inds[thr] == thr_logs[thr].curr_entry_ind) {
+            log_inds[thr] = -1;
+            pending_logs--;
+        }
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp_log.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+
+#ifndef __SOTP_LOG_H
+#define __SOTP_LOG_H
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if 0
+#if defined(ESFS_INTERACTIVE_TEST) && defined(TARGET_IS_PC_LINUX)
+    #ifndef SOTP_LOG
+        #define SOTP_LOG 1
+    #endif
+#endif
+#endif
+
+#if SOTP_LOG
+void sotp_log_create(char *fmt, ...);
+void sotp_log_append(char *fmt, ...);
+void sotp_log_finalize(void);
+void sotp_log_init(void);
+void sotp_log_print_log(void);
+#define SOTP_LOG_CREATE sotp_log_create
+#define SOTP_LOG_APPEND sotp_log_append
+#define SOTP_LOG_FINALIZE sotp_log_finalize
+#define SOTP_LOG_PRINT_LOG sotp_log_print_log
+#define SOTP_LOG_INIT sotp_log_init
+#else
+#define SOTP_LOG_CREATE(...) ((void)0)
+#define SOTP_LOG_APPEND(...) ((void)0)
+#define SOTP_LOG_FINALIZE(...) ((void)0)
+#define SOTP_LOG_PRINT_LOG(...) ((void)0)
+#define SOTP_LOG_INIT(...) ((void)0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp_no_sotp.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+
+
+// ----------------------------------------------------------- Includes -----------------------------------------------------------
+
+#include "sotp.h"
+
+#if (SYS_CONF_SOTP==SYS_CONF_SOTP_LIMITED)
+
+#include "esfs.h"
+#include "pal.h"
+#include <string.h>
+#include <stdio.h>
+#include "sotp_int.h"
+
+#define FILE_NAME_BASE "sotp_type_"
+#define FILE_NAME_SIZE (sizeof(FILE_NAME_BASE)+4)
+
+STATIC bool init_done = false;
+
+static const sotp_type_e otp_types[] = {SOTP_TYPE_TRUSTED_TIME_SRV_ID};
+
+// --------------------------------------------------------- Definitions ----------------------------------------------------------
+
+
+// -------------------------------------------------- Local Functions Declaration ----------------------------------------------------
+
+// -------------------------------------------------- Functions Implementation ----------------------------------------------------
+
+// Start of API functions
+
+bool sotp_is_otp_type(uint32_t type)
+{
+    unsigned int i;
+    for (i = 0; i < sizeof(otp_types) / sizeof(sotp_type_e); i++) {
+        if (otp_types[i] == type) {
+            return true;
+        }
+    }
+    return false;
+}
+
+sotp_result_e sotp_get(uint32_t type, uint16_t buf_len_bytes, uint32_t *buf, uint16_t *actual_len_bytes)
+{
+    esfs_file_t handle;
+    uint16_t mode;
+    char file_name[FILE_NAME_SIZE];
+    esfs_result_e esfs_ret;
+    size_t act_size;
+    sotp_result_e ret;
+
+    if (!init_done) {
+        ret = sotp_init();
+        if (ret != SOTP_SUCCESS)
+            return ret;
+    }
+
+    if (type > SOTP_MAX_TYPES) {
+        return SOTP_BAD_VALUE;
+    }
+
+    memset(&handle, 0, sizeof(handle));
+    sprintf(file_name, "%s%ld", FILE_NAME_BASE, type);
+
+    esfs_ret = esfs_open((uint8_t *)file_name, strlen(file_name), &mode, &handle);
+    if (esfs_ret == ESFS_NOT_EXISTS) {
+        return SOTP_NOT_FOUND;
+    }
+    else if (esfs_ret != ESFS_SUCCESS) {
+        return SOTP_OS_ERROR;
+    }
+
+    if (!buf) {
+        buf_len_bytes = 0;
+    }
+
+    esfs_ret = esfs_file_size(&handle, &act_size);
+    *actual_len_bytes = (uint16_t) act_size;
+    if (esfs_ret != ESFS_SUCCESS) {
+        esfs_close(&handle);
+        return SOTP_READ_ERROR;
+    }
+
+    if (*actual_len_bytes > buf_len_bytes) {
+        esfs_close(&handle);
+        return SOTP_BUFF_TOO_SMALL;
+    }
+
+    if (*actual_len_bytes) {
+        esfs_ret = esfs_read(&handle, buf, buf_len_bytes, &act_size);
+        if (esfs_ret != ESFS_SUCCESS) {
+            esfs_close(&handle);
+            return SOTP_READ_ERROR;
+        }
+    }
+
+    esfs_ret = esfs_close(&handle);
+    if (esfs_ret != ESFS_SUCCESS) {
+        return SOTP_OS_ERROR;
+    }
+
+    return SOTP_SUCCESS;
+}
+
+sotp_result_e sotp_get_item_size(uint32_t type, uint16_t *actual_len_bytes)
+{
+    esfs_file_t handle;
+    uint16_t mode;
+    char file_name[FILE_NAME_SIZE];
+    esfs_result_e esfs_ret;
+    size_t size_bytes;
+    sotp_result_e ret;
+
+    if (!init_done) {
+        ret = sotp_init();
+        if (ret != SOTP_SUCCESS)
+            return ret;
+    }
+
+    if (type > SOTP_MAX_TYPES) {
+        return SOTP_BAD_VALUE;
+    }
+
+    memset(&handle, 0, sizeof(handle));
+    sprintf(file_name, "%s%ld", FILE_NAME_BASE, type);
+
+    esfs_ret = esfs_open((uint8_t *)file_name, strlen(file_name), &mode, &handle);
+    if (esfs_ret == ESFS_NOT_EXISTS) {
+        return SOTP_NOT_FOUND;
+    }
+    if (esfs_ret != ESFS_SUCCESS) {
+        return SOTP_OS_ERROR;
+    }
+
+    esfs_ret = esfs_file_size(&handle, &size_bytes);
+    if (esfs_ret != ESFS_SUCCESS) {
+        esfs_close(&handle);
+        return SOTP_READ_ERROR;
+    }
+
+    esfs_ret = esfs_close(&handle);
+    if (esfs_ret != ESFS_SUCCESS) {
+        return SOTP_OS_ERROR;
+    }
+
+    *actual_len_bytes = (uint16_t) size_bytes;
+    return SOTP_SUCCESS;
+}
+
+sotp_result_e sotp_set(uint32_t type, uint16_t buf_len_bytes, const uint32_t *buf)
+{
+    esfs_file_t handle;
+    uint16_t mode;
+    char file_name[FILE_NAME_SIZE];
+    esfs_result_e esfs_ret;
+    sotp_result_e ret;
+
+    if (!init_done) {
+        ret = sotp_init();
+        if (ret != SOTP_SUCCESS)
+            return ret;
+    }
+
+    if (type > SOTP_MAX_TYPES) {
+        return SOTP_BAD_VALUE;
+    }
+
+    // Only perform actual setting of values on OTP types. Return success for the rest without
+    // doing anything.
+    if (!sotp_is_otp_type(type)) {
+        return SOTP_SUCCESS;
+    }
+
+    memset(&handle, 0, sizeof(handle));
+    sprintf(file_name, "%s%ld", FILE_NAME_BASE, type);
+
+    esfs_ret = esfs_open((uint8_t *)file_name, strlen(file_name), &mode, &handle);
+    if (esfs_ret == ESFS_SUCCESS) {
+        esfs_close(&handle);
+        return SOTP_ALREADY_EXISTS;
+    }
+    if (esfs_ret != ESFS_NOT_EXISTS) {
+        return SOTP_OS_ERROR;
+    }
+
+    esfs_ret = esfs_create((uint8_t *)file_name, strlen(file_name), NULL, 0, ESFS_FACTORY_VAL, &handle);
+    if (esfs_ret != ESFS_SUCCESS) {
+        return SOTP_OS_ERROR;
+    }
+
+    if (buf && buf_len_bytes) {
+        esfs_ret = esfs_write(&handle, buf, buf_len_bytes);
+        if (esfs_ret != ESFS_SUCCESS) {
+            esfs_close(&handle);
+            return SOTP_WRITE_ERROR;
+        }
+    }
+
+    esfs_ret = esfs_close(&handle);
+    if (esfs_ret != ESFS_SUCCESS) {
+        return SOTP_OS_ERROR;
+    }
+
+    return SOTP_SUCCESS;
+}
+
+#ifdef SOTP_TESTING
+
+sotp_result_e sotp_set_for_testing(uint32_t type, uint16_t buf_len_bytes, const uint32_t *buf)
+{
+    char file_name[FILE_NAME_SIZE];
+    esfs_result_e esfs_ret;
+    sotp_result_e ret;
+
+    if (!init_done) {
+        ret = sotp_init();
+        if (ret != SOTP_SUCCESS)
+            return ret;
+    }
+
+    sprintf(file_name, "%s%ld", FILE_NAME_BASE, type);
+    esfs_ret = esfs_delete((uint8_t *)file_name, strlen(file_name));
+    if ((esfs_ret != ESFS_NOT_EXISTS) && (esfs_ret != ESFS_SUCCESS)) {
+        return SOTP_OS_ERROR;
+    }
+    return sotp_set(type, buf_len_bytes, buf);
+}
+
+sotp_result_e sotp_delete(uint32_t type)
+{
+    char file_name[FILE_NAME_SIZE];
+    esfs_result_e esfs_ret;
+    sotp_result_e ret;
+
+    if (!init_done) {
+        ret = sotp_init();
+        if (ret != SOTP_SUCCESS)
+            return ret;
+    }
+
+    sprintf(file_name, "%s%ld", FILE_NAME_BASE, type);
+    esfs_ret = esfs_delete((uint8_t *)file_name, strlen(file_name));
+    if (esfs_ret == ESFS_SUCCESS)
+        return SOTP_SUCCESS;
+
+    if (esfs_ret == ESFS_NOT_EXISTS)
+        return SOTP_NOT_FOUND;
+
+    return SOTP_OS_ERROR;
+}
+
+#endif
+
+sotp_result_e sotp_init(void)
+{
+    esfs_result_e esfs_ret;
+
+    if (init_done)
+        return SOTP_SUCCESS;
+
+    esfs_ret = esfs_init();
+    if (esfs_ret != ESFS_SUCCESS) {
+        return SOTP_OS_ERROR;
+    }
+
+    return SOTP_SUCCESS;
+}
+
+sotp_result_e sotp_deinit(void)
+{
+    return SOTP_SUCCESS;
+}
+
+sotp_result_e sotp_reset(void)
+{
+    char file_name[FILE_NAME_SIZE];
+    esfs_result_e esfs_ret;
+    uint32_t type;
+    sotp_result_e ret;
+
+    if (!init_done) {
+        ret = sotp_init();
+        if (ret != SOTP_SUCCESS)
+            return ret;
+    }
+
+    for (type = 0; type < SOTP_MAX_TYPES; type++) {
+        sprintf(file_name, "%s%ld", FILE_NAME_BASE, type);
+
+        esfs_ret = esfs_delete((uint8_t *)file_name, strlen(file_name));
+        if ((esfs_ret != ESFS_NOT_EXISTS) && (esfs_ret != ESFS_SUCCESS)) {
+            return SOTP_OS_ERROR;
+        }
+    }
+
+    return SOTP_SUCCESS;
+}
+
+#ifdef SOTP_TESTING
+
+sotp_result_e sotp_force_garbage_collection(void)
+{
+    return SOTP_SUCCESS;
+}
+
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp_shared_lock.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+
+
+// ----------------------------------------------------------- Includes -----------------------------------------------------------
+
+
+#include "sotp_shared_lock.h"
+#include "mbed-trace/mbed_trace.h"
+#include "pal.h"
+#include <string.h>
+#include <stdlib.h>
+
+// --------------------------------------------------------- Definitions ----------------------------------------------------------
+
+#define TRACE_GROUP                     "sotp"
+
+#define PR_ERR tr_err
+#define PR_INFO tr_info
+#define PR_DEBUG tr_debug
+
+#define MEDITATE_TIME_MS 100
+
+#ifdef SOTP_THREAD_SAFE
+typedef struct {
+    int32_t      ctr;
+    // Use semaphore and not mutex, as mutexes don't behave well when trying
+    // to delete them while taken (which may happen in our tests).
+    palSemaphoreID_t sem;
+} shared_lock_priv_t;
+#endif
+// -------------------------------------------------- Local Functions Declaration ----------------------------------------------------
+
+
+// -------------------------------------------------- Functions Implementation ----------------------------------------------------
+// Create a shared lock.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_create(sotp_shared_lock_t *sh_lock)
+{
+#ifdef SOTP_THREAD_SAFE
+    shared_lock_priv_t *lock_priv;
+    lock_priv = (shared_lock_priv_t *) malloc(sizeof(shared_lock_priv_t));
+
+    if (!lock_priv) {
+        PR_ERR("sotp_sh_lock_create: Out of memory\n");
+        return SOTP_SHL_NO_MEM;
+    }
+
+    lock_priv->ctr = 0;
+
+    if (pal_osSemaphoreCreate(1, &(lock_priv->sem)) != PAL_SUCCESS) {
+        PR_ERR("sotp_sh_lock_shared_lock: PAL error\n");
+        free(lock_priv);
+        return SOTP_SHL_PAL_ERR;
+    }
+
+    *sh_lock = (sotp_shared_lock_t) lock_priv;
+#endif
+    return SOTP_SHL_SUCCESS;
+}
+
+// Destroy a shared lock.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_destroy(sotp_shared_lock_t sh_lock)
+{
+#ifdef SOTP_THREAD_SAFE
+    shared_lock_priv_t *lock_priv = (shared_lock_priv_t *) sh_lock;
+
+    if (!sh_lock) {
+        PR_ERR("sotp_sh_lock_destroy: NULL parameter\n");
+        return SOTP_SHL_NULL_PTR;
+    }
+
+    // Semaphore may be taken, so deleting it would fail. Try releasing (without checking return code).
+    pal_osSemaphoreRelease(lock_priv->sem);
+
+    if (pal_osSemaphoreDelete(&(lock_priv->sem)) != PAL_SUCCESS) {
+        PR_ERR("sotp_sh_lock_destroy: PAL error\n");
+        return SOTP_SHL_PAL_ERR;
+    }
+
+    free(lock_priv);
+#endif
+    return SOTP_SHL_SUCCESS;
+}
+
+// Lock a shared-lock in a shared manner.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_shared_lock(sotp_shared_lock_t sh_lock)
+{
+#ifdef SOTP_THREAD_SAFE
+    shared_lock_priv_t *lock_priv = (shared_lock_priv_t *) sh_lock;
+    int32_t ctrs;
+
+    if (!sh_lock)
+        return SOTP_SHL_NULL_PTR;
+
+    if (pal_osSemaphoreWait(lock_priv->sem, PAL_RTOS_WAIT_FOREVER, &ctrs) != PAL_SUCCESS) {
+        PR_ERR("sotp_sh_lock_shared_lock: PAL error\n");
+        return SOTP_SHL_PAL_ERR;
+    }
+
+    pal_osAtomicIncrement(&lock_priv->ctr, 1);
+
+    if (pal_osSemaphoreRelease(lock_priv->sem) != PAL_SUCCESS) {
+        PR_ERR("sotp_sh_lock_shared_lock: PAL error\n");
+        return SOTP_SHL_PAL_ERR;
+    }
+#endif
+    return SOTP_SHL_SUCCESS;
+}
+
+// Release a shared-lock in a shared manner.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_shared_release(sotp_shared_lock_t sh_lock)
+{
+#ifdef SOTP_THREAD_SAFE
+    shared_lock_priv_t *lock_priv = (shared_lock_priv_t *) sh_lock;
+    int32_t val;
+
+    if (!sh_lock) {
+        PR_ERR("sotp_sh_lock_shared_release: NULL parameter\n");
+        return SOTP_SHL_NULL_PTR;
+    }
+
+    val = pal_osAtomicIncrement(&lock_priv->ctr, -1);
+    if (val < 0) {
+        PR_ERR("sotp_sh_lock_shared_release: Misuse (released more than locked)\n");
+        return SOTP_SHL_MISUSE;
+    }
+
+#endif
+    return SOTP_SHL_SUCCESS;
+}
+
+// Lock a shared-lock in an exclusive manner.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_exclusive_lock(sotp_shared_lock_t sh_lock)
+{
+#ifdef SOTP_THREAD_SAFE
+    shared_lock_priv_t *lock_priv = (shared_lock_priv_t *) sh_lock;
+    int32_t ctrs;
+
+    if (!sh_lock) {
+        PR_ERR("sotp_sh_lock_exclusive_lock: NULL parameter\n");
+        return SOTP_SHL_NULL_PTR;
+    }
+
+    if (pal_osSemaphoreWait(lock_priv->sem, PAL_RTOS_WAIT_FOREVER, &ctrs) != PAL_SUCCESS) {
+        PR_ERR("sotp_sh_lock_exclusive_lock: PAL error\n");
+        return SOTP_SHL_PAL_ERR;
+    }
+
+    while(lock_priv->ctr)
+        pal_osDelay(MEDITATE_TIME_MS);
+
+#endif
+    return SOTP_SHL_SUCCESS;
+}
+
+// Release a shared-lock in an exclusive manner.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_exclusive_release(sotp_shared_lock_t sh_lock)
+{
+#ifdef SOTP_THREAD_SAFE
+    shared_lock_priv_t *lock_priv = (shared_lock_priv_t *) sh_lock;
+
+    if (!sh_lock) {
+        PR_ERR("sotp_sh_lock_exclusive_release: NULL parameter\n");
+        return SOTP_SHL_NULL_PTR;
+    }
+
+    if (pal_osSemaphoreRelease(lock_priv->sem) != PAL_SUCCESS) {
+        PR_ERR("sotp_sh_lock_exclusive_release: PAL error\n");
+        return SOTP_SHL_PAL_ERR;
+    }
+
+#endif
+    return SOTP_SHL_SUCCESS;
+}
+
+// Promote a shared-lock from shared mode to exclusive mode.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_promote(sotp_shared_lock_t sh_lock)
+{
+#ifdef SOTP_THREAD_SAFE
+    shared_lock_priv_t *lock_priv = (shared_lock_priv_t *) sh_lock;
+    int32_t ctrs;
+
+    if (!sh_lock) {
+        PR_ERR("sotp_sh_lock_promote: NULL parameter\n");
+        return SOTP_SHL_NULL_PTR;
+    }
+
+    if (pal_osSemaphoreWait(lock_priv->sem, PAL_RTOS_WAIT_FOREVER, &ctrs) != PAL_SUCCESS) {
+        PR_ERR("sotp_sh_lock_promote: PAL error\n");
+        return SOTP_SHL_PAL_ERR;
+    }
+
+    while(lock_priv->ctr > 1)
+        pal_osDelay(MEDITATE_TIME_MS);
+
+    if (lock_priv->ctr != 1) {
+        PR_ERR("sotp_sh_lock_promote: Misuse (promoted when not locked)\n");
+        return SOTP_SHL_MISUSE;
+    }
+
+    pal_osAtomicIncrement(&lock_priv->ctr, -1);
+
+#endif
+    return SOTP_SHL_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-client-esfs/source/sotp/sotp_shared_lock.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+
+
+#ifndef __SOTP_SHARED_LOCK_H
+#define __SOTP_SHARED_LOCK_H
+
+#include <stdint.h>
+#include "pal_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    SOTP_SHL_SUCCESS            = 0,
+    SOTP_SHL_INVALID_ARG        = 1,
+    SOTP_SHL_NULL_PTR           = 2,
+    SOTP_SHL_NO_MEM             = 3,
+    SOTP_SHL_PAL_ERR            = 4,
+    SOTP_SHL_MISUSE             = 5,
+    SOTP_SHL_ERROR_MAXVAL       = 0xFFFF
+} sotp_sh_lock_result_e;
+
+typedef uintptr_t sotp_shared_lock_t;
+
+// Create a shared lock.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_create(sotp_shared_lock_t *sh_lock);
+
+// Destroy a shared lock.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_destroy(sotp_shared_lock_t sh_lock);
+
+// Lock a shared-lock in a shared manner.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_shared_lock(sotp_shared_lock_t sh_lock);
+
+// Release a shared-lock in a shared manner.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_shared_release(sotp_shared_lock_t sh_lock);
+
+// Lock a shared-lock in an exclusive manner.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_exclusive_lock(sotp_shared_lock_t sh_lock);
+
+// Release a shared-lock in an exclusive manner.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_exclusive_release(sotp_shared_lock_t sh_lock);
+
+// Promote a shared-lock from shared mode to exclusive mode.
+// Parameters :
+// sh_lock    - [OUT]  lock handle.
+// Return     : SOTP_SHL_SUCCESS on success. Error code otherwise.
+sotp_sh_lock_result_e sotp_sh_lock_promote(sotp_shared_lock_t sh_lock);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-trace-helper/mbed-trace-helper/mbed-trace-helper.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,66 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+/* Logging macros */
+
+#ifndef __MBED_TRACE_HELPER_H__
+#define __MBED_TRACE_HELPER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdbool.h>
+/**
+* Function used in mbed-trace to set trace print
+*/
+void mbed_trace_helper_print(const char* format);
+/**
+* Function used in mbed-trace to set wait mutex function
+*/
+void mbed_trace_helper_mutex_wait( void );
+/**
+* Function used in mbed-trace to set release mutex function
+*/
+void mbed_trace_helper_mutex_release( void );
+/**
+* This function creates mutex
+*/
+bool mbed_trace_helper_create_mutex( void );
+/**
+* Deletes mutex
+*/
+void mbed_trace_helper_delete_mutex(void);
+/**
+* Check activated trace level according to MBED_TRACE_MAX_LEVEL and used level in mbed_trace_config_set.
+* In case the activated level is higher then MBED_TRACE_MAX_LEVEL, the function prints warning.
+*/
+uint8_t mbed_trace_helper_check_activated_trace_level( void );
+/**
+* The function calls to configuration functions of mbed_trace_helper according to passed parameters and initializes mbed-trace
+*/
+bool mbed_trace_helper_init(uint8_t config, bool is_mutex_used);
+/**
+* The function terminats thred and mbed-trace
+*/
+void mbed_trace_helper_finish( void );
+#ifdef __cplusplus
+}
+#endif
+#endif /*__TRACE_HELPER_H__*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/mbed-trace-helper/source/mbed-trace-helper.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,143 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "pv_log.h"
+#include <stdarg.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include "pal.h"
+#include "pv_error_handling.h"
+#include "mbed-trace/mbed_trace.h"
+/**
+* Mutex for printing logs in a thread safe manner.
+*/
+palMutexID_t g_pv_logger_mutex = NULLPTR;
+
+void mbed_trace_helper_print(const char* format)
+{
+    fprintf(stdout, "%s\n", format);
+}
+
+void mbed_trace_helper_mutex_wait()
+{
+    (void)pal_osMutexWait(g_pv_logger_mutex, PAL_RTOS_WAIT_FOREVER);
+}
+
+void mbed_trace_helper_mutex_release()
+{
+    (void)pal_osMutexRelease(g_pv_logger_mutex);
+}
+/**
+* Creates mutex
+*/
+bool mbed_trace_helper_create_mutex(void)
+{
+    palStatus_t status;
+
+    // g_pv_logger_mutex already created - no need to recreate it.
+    if (g_pv_logger_mutex) {
+        goto exit;
+    }
+
+    status = pal_osMutexCreate(&g_pv_logger_mutex);
+    if (status != PAL_SUCCESS) {
+        SA_PV_LOG_INFO("Error creating g_pv_logger_mutex (pal err = %d)", (int)status);
+        return false;
+    }
+
+exit:
+    return true;
+}
+
+/**
+* Deletes mutex
+*/
+void mbed_trace_helper_delete_mutex(void)
+{
+    // g_pv_logger_mutex already created - no need to recreate it.
+    if (g_pv_logger_mutex == NULLPTR) {
+        return;
+    }
+
+    pal_osMutexDelete(&g_pv_logger_mutex);
+    g_pv_logger_mutex = NULLPTR;
+}
+
+uint8_t mbed_trace_helper_check_activated_trace_level()
+{
+    uint8_t config_active_level = 0;
+    uint8_t activated_level = 0;
+
+    SA_PV_LOG_INFO_FUNC_ENTER("MBED_TRACE_MAX_LEVEL = %d", MBED_TRACE_MAX_LEVEL);
+
+    config_active_level = mbed_trace_config_get() & TRACE_MASK_LEVEL;
+    SA_PV_LOG_INFO("config_active_level is %d", config_active_level);
+    
+    activated_level = config_active_level & MBED_TRACE_MAX_LEVEL;
+    SA_PV_LOG_INFO("activated_level is %d", activated_level);
+
+    if (activated_level == 0) {
+        SA_PV_LOG_CRITICAL("The compiled maximum trace level %d, is higher than activated trace level", MBED_TRACE_MAX_LEVEL);
+        SA_PV_LOG_CRITICAL("If you want to use the requested log level, please change MBED_TRACE_MAX_LEVEL compilation flag and recompile the code");
+    }
+
+    SA_PV_LOG_INFO_FUNC_EXIT_NO_ARGS();
+
+    return activated_level;
+}
+
+bool mbed_trace_helper_init(uint8_t config, bool is_mutex_used)
+{
+    bool success = true;
+    int rc = 0;
+
+    rc = mbed_trace_init();
+
+    if (rc != 0) {
+        return false;
+    }
+
+    if (is_mutex_used) {
+        // Create mutex
+        success = mbed_trace_helper_create_mutex();
+        if (success != true) {
+            mbed_trace_free();
+            return false;
+        }
+    }
+    // Set trace level, TRACE_MODE_PLAIN used to ignore mbed trace print pattern ([trace_level] [trace_group] format)
+    mbed_trace_config_set(config);
+
+    // Set trace print function
+    mbed_trace_print_function_set(mbed_trace_helper_print);
+
+    if (is_mutex_used) {
+        // Set mutex wait function for mbed trace
+        mbed_trace_mutex_wait_function_set(mbed_trace_helper_mutex_wait);
+        // Set mutex release function for mbed trace
+        mbed_trace_mutex_release_function_set(mbed_trace_helper_mutex_release);
+    }
+    return  true;
+}
+
+void mbed_trace_helper_finish()
+{
+    mbed_trace_helper_delete_mutex();
+    mbed_trace_free();
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/CMakeLists.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,18 @@
+
+# includes
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/secsrv-cbor)
+
+FILE(
+	GLOB_RECURSE  
+	cbor
+
+	"${CMAKE_CURRENT_SOURCE_DIR}/secsrv-cbor/*.h"
+	"${CMAKE_CURRENT_SOURCE_DIR}/source/*.c"
+)
+
+message ("*********************************************************************")
+message ("cbor = [[${cbor}]]")
+message ("*********************************************************************")
+
+CREATE_LIBRARY(cn-cbor "${cbor}" "")
+ADDSUBDIRS()
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Carsten Bormann <cabo@tzi.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/ORIGIN.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,7 @@
+Source code is taken from Cborg git - https://github.com/quartzjer/cborg. 
+List of changes:
+* Chagne the tests to fit unit tests format.
+* Changed representation of CN_CBOR_UINT in the union v in struct cn_cbor from unsigned long to uint64_t as fix for platforms where unsigned long is represented in only 32 bits.
+* Same thing done for CN_CBOR_INT changed from long to int64_t.
+* Changed encoding lib function and added a lib function that gets the length of the buffer to encode into. 
+Updated to revision be86408ca8554719ba54f3f6ede0dc98be17d58a (from 19-Nov-2016).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/secsrv-cbor/cbor.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,143 @@
+#ifndef CBOR_PROTOCOL_H__
+#define CBOR_PROTOCOL_H__
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+/* The 8 major types */
+#define MT_UNSIGNED 0
+#define MT_NEGATIVE 1
+#define MT_BYTES    2
+#define MT_TEXT     3
+#define MT_ARRAY    4
+#define MT_MAP      5
+#define MT_TAG      6
+#define MT_PRIM     7
+
+/* The initial bytes resulting from those */
+#define IB_UNSIGNED (MT_UNSIGNED << 5)
+#define IB_NEGATIVE (MT_NEGATIVE << 5)
+#define IB_BYTES    (MT_BYTES << 5)
+#define IB_TEXT     (MT_TEXT << 5)
+#define IB_ARRAY    (MT_ARRAY << 5)
+#define IB_MAP      (MT_MAP << 5)
+#define IB_TAG      (MT_TAG << 5)
+#define IB_PRIM     (MT_PRIM << 5)
+
+#define IB_NEGFLAG (IB_NEGATIVE - IB_UNSIGNED)
+#define IB_NEGFLAG_AS_BIT(ib) ((ib) >> 5)
+#define IB_TEXTFLAG (IB_TEXT - IB_BYTES)
+
+#define IB_AI(ib) ((ib) & 0x1F)
+#define IB_MT(ib) ((ib) >> 5)
+
+/* Tag numbers handled by this implementation */
+#define TAG_TIME_EPOCH 1
+#define TAG_BIGNUM     2
+#define TAG_BIGNUM_NEG 3
+#define TAG_URI        32
+#define TAG_RE         35
+
+/* Initial bytes of those tag numbers */
+#define IB_TIME_EPOCH (IB_TAG | TAG_TIME_EPOCH)
+#define IB_BIGNUM     (IB_TAG | TAG_BIGNUM)
+#define IB_BIGNUM_NEG (IB_TAG | TAG_BIGNUM_NEG)
+/* TAG_URI and TAG_RE are non-immediate tags */
+
+/* Simple values handled by this implementation */
+#define VAL_FALSE 20
+#define VAL_TRUE  21
+#define VAL_NIL   22
+#define VAL_UNDEF 23
+
+/* Initial bytes of those simple values */
+#define IB_FALSE (IB_PRIM | VAL_FALSE)
+#define IB_TRUE  (IB_PRIM | VAL_TRUE)
+#define IB_NIL   (IB_PRIM | VAL_NIL)
+#define IB_UNDEF (IB_PRIM | VAL_UNDEF)
+
+/* AI values with more data in head */
+#define AI_1 24
+#define AI_2 25
+#define AI_4 26
+#define AI_8 27
+#define AI_INDEF 31
+#define IB_BREAK (IB_PRIM | AI_INDEF)
+/* For  */
+#define IB_UNUSED (IB_TAG | AI_INDEF)
+
+/* Floating point initial bytes */
+#define IB_FLOAT2 (IB_PRIM | AI_2)
+#define IB_FLOAT4 (IB_PRIM | AI_4)
+#define IB_FLOAT8 (IB_PRIM | AI_8)
+
+// These definitions are here because they aren't required for the public
+// interface, and they were quite confusing in cn-cbor.h
+
+#ifdef USE_CBOR_CONTEXT
+
+
+/**
+ * Allocate enough space for 1 `cn_cbor` structure.
+ *
+ * @param[in]  ctx  The allocation context, or NULL for calloc.
+ * @return          A pointer to a `cn_cbor` or NULL on failure
+ */
+#define CN_CALLOC(ctx) ((ctx) && (ctx)->calloc_func) ? \
+    (ctx)->calloc_func(1, sizeof(cn_cbor), (ctx)->context) : \
+    calloc(1, sizeof(cn_cbor));
+
+/**
+ * Free a
+ * @param  free_func [description]
+ * @return           [description]
+ */
+#define CN_FREE(ptr, ctx) ((ctx) && (ctx)->free_func) ? \
+    (ctx)->free_func((ptr), (ctx)->context) : \
+    free((ptr));
+
+#define CN_CALLOC_CONTEXT() CN_CALLOC(cbor_context)
+#define CN_CBOR_FREE_CONTEXT(p) CN_FREE(p, cbor_context)
+
+// This is in fact supposed to be sizeof(bitmap[0]). since sizeof is evaluated by the compiler and not the preprocessor, using it here will mess up the BITMAP_ARRAY_SIZE define.
+#define BITMAP_ENTRY_IN_BITS 32 
+
+ // The number of entries in the bitmap array
+#define BITMAP_ARRAY_SIZE (( MAX_SIZE_POOL_IN_CBORS % BITMAP_ENTRY_IN_BITS == 0 ) ?  ( MAX_SIZE_POOL_IN_CBORS / BITMAP_ENTRY_IN_BITS ) : ( ( MAX_SIZE_POOL_IN_CBORS / BITMAP_ENTRY_IN_BITS ) + 1 ))
+
+ /**
+ * The memory pool structure.
+ * The context field of a cn_cbor_context object should point to an object of this type.
+ */
+typedef struct cbor_mem_pool_ {
+    int32_t bitmap[BITMAP_ARRAY_SIZE];
+    uint8_t pool_size_in_cbors;
+    cn_cbor *pool;
+} cbor_mem_pool;
+
+
+#else
+
+#define CN_CALLOC_CONTEXT() CN_CALLOC
+#define CN_CBOR_FREE_CONTEXT(p) CN_FREE(p)
+
+#ifndef CN_CALLOC
+#define CN_CALLOC calloc(1, sizeof(cn_cbor))
+#endif
+
+#ifndef CN_FREE
+#define CN_FREE free
+#endif
+
+#endif // USE_CBOR_CONTEXT
+
+#ifndef UNUSED_PARAM
+#define UNUSED_PARAM(p) ((void)&(p))
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif // CBOR_PROTOCOL_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/secsrv-cbor/cn-cbor.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,536 @@
+/**
+ * \file
+ * \brief
+ * CBOR parsing
+ */
+
+#ifndef CN_CBOR_H
+#define CN_CBOR_H
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+//typedef int ssize_t;
+
+#ifdef EMACS_INDENTATION_HELPER
+} /* Duh. */
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+//typedef ssize_t int;
+//#include <unistd.h>
+
+/**
+ * All of the different kinds of CBOR values.
+ */
+typedef enum cn_cbor_type {
+  /** false */
+  CN_CBOR_FALSE,
+  /** true */
+  CN_CBOR_TRUE,
+  /** null */
+  CN_CBOR_NULL,
+  /** undefined */
+  CN_CBOR_UNDEF,
+  /** Positive integers */
+  CN_CBOR_UINT,
+  /** Negative integers */
+  CN_CBOR_INT,
+  /** Byte string */
+  CN_CBOR_BYTES,
+  /** UTF-8 string */
+  CN_CBOR_TEXT,
+  /** Byte string, in chunks.  Each chunk is a child. */
+  CN_CBOR_BYTES_CHUNKED,
+  /** UTF-8 string, in chunks.  Each chunk is a child */
+  CN_CBOR_TEXT_CHUNKED,
+  /** Array of CBOR values.  Each array element is a child, in order */
+  CN_CBOR_ARRAY,
+  /** Map of key/value pairs.  Each key and value is a child, alternating. */
+  CN_CBOR_MAP,
+  /** Tag describing the next value.  The next value is the single child. */
+  CN_CBOR_TAG,
+  /** Simple value, other than the defined ones */
+  CN_CBOR_SIMPLE,
+  /** Doubles, floats, and half-floats */
+  CN_CBOR_DOUBLE,
+  /** An error has occurred */
+  CN_CBOR_INVALID
+} cn_cbor_type;
+
+/**
+ * Flags used during parsing.  Not useful for consumers of the
+ * `cn_cbor` structure.
+ */
+typedef enum cn_cbor_flags {
+  /** The count field will be used for parsing */
+  CN_CBOR_FL_COUNT = 1,
+  /** An indefinite number of children */
+  CN_CBOR_FL_INDEF = 2,
+  /** Not used yet; the structure must free the v.str pointer when the
+     structure is freed */
+  CN_CBOR_FL_OWNER = 0x80,            /* of str */
+} cn_cbor_flags;
+
+// FIXME: These could be used in the future instead of type and flags in struct cn_cbor (will make the sizeof(cn_cbor) 8 bytes less)
+//#define CN_CBOR_TYPE(pCbor) (pCbor->enums & 0x0f)
+//#define CN_CBOR_FLAGS(pCbor) (pCbor->enums & 0xf0)
+
+/**
+ * A CBOR value
+ */
+
+typedef struct cn_cbor {
+  /** The type of value */
+  cn_cbor_type type;
+  /** Flags used at parse time */
+  cn_cbor_flags flags;
+  /** Data associated with the value; different branches of the union are
+      used depending on the `type` field. */
+  union {
+    /** CN_CBOR_BYTES */
+    const uint8_t* bytes;
+    /** CN_CBOR_TEXT */
+    const char* str;
+    /** CN_CBOR_INT */
+    int64_t sint;
+    /** CN_CBOR_UINT */
+    uint64_t uint;
+    /** CN_CBOR_DOUBLE */
+    double dbl;
+    /** for use during parsing */
+    unsigned long count;
+  } v;                          /* TBD: optimize immediate */
+  /** Number of children.
+    * @note: for maps, this is 2x the number of entries */
+  int length;
+
+  // FIXME: This could be used in the future instead of type and flags in struct cn_cbor (will make the sizeof(cn_cbor) 8 bytes less)
+  //uint8_t enums;
+
+  /** The first child value */
+  struct cn_cbor* first_child;
+  /** The last child value */
+  struct cn_cbor* last_child;
+  /** The sibling after this one, or NULL if this is the last */
+  struct cn_cbor* next;
+  /** The parent of this value, or NULL if this is the root */
+  struct cn_cbor* parent;
+} cn_cbor;
+
+/**
+ * All of the different kinds of errors
+ */
+typedef enum cn_cbor_error {
+  /** No error has occurred */
+  CN_CBOR_NO_ERROR,
+  /** More data was expected while parsing */
+  CN_CBOR_ERR_OUT_OF_DATA,
+  /** Some extra data was left over at the end of parsing */
+  CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED,
+  /** A map should be alternating keys and values.  A break was found
+      when a value was expected */
+  CN_CBOR_ERR_ODD_SIZE_INDEF_MAP,
+  /** A break was found where it wasn't expected */
+  CN_CBOR_ERR_BREAK_OUTSIDE_INDEF,
+  /** Indefinite encoding works for bstrs, strings, arrays, and maps.
+      A different major type tried to use it. */
+  CN_CBOR_ERR_MT_UNDEF_FOR_INDEF,
+  /** Additional Information values 28-30 are reserved */
+  CN_CBOR_ERR_RESERVED_AI,
+  /** A chunked encoding was used for a string or bstr, and one of the elements
+      wasn't the expected (string/bstr) type */
+  CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING,
+  /** An invalid parameter was passed to a function */
+  CN_CBOR_ERR_INVALID_PARAMETER,
+  /** Allocation failed */
+  CN_CBOR_ERR_OUT_OF_MEMORY,
+  /** A float was encountered during parse but the library was built without
+      support for float types. */
+  CN_CBOR_ERR_FLOAT_NOT_SUPPORTED,
+  /** Encoder was unable to encode the cn_cbor object that was provided */
+  CN_CBOR_ERR_ENCODER
+} cn_cbor_error;
+
+/**
+ * Strings matching the `cn_cbor_error` conditions.
+ *
+ * @todo: turn into a function to make the type safety more clear?
+ */
+extern const char *cn_cbor_error_str[];
+
+/**
+ * Errors
+ */
+typedef struct cn_cbor_errback {
+  /** The position in the input where the erorr happened */
+  int pos;
+  /** The error, or CN_CBOR_NO_ERROR if none */
+  cn_cbor_error err;
+} cn_cbor_errback;
+
+#ifdef USE_CBOR_CONTEXT
+
+
+/**
+ * Allocate and zero out memory.  `count` elements of `size` are required,
+ * as for `calloc(3)`.  The `context` is the `cn_cbor_context` passed in
+ * earlier to the CBOR routine.
+ *
+ * @param[in] count   The number of items to allocate
+ * @param[in] size    The size of each item
+ * @param[in] context The allocation context
+ */
+typedef void* (*cn_calloc_func)(size_t count, size_t size, void *context);
+
+/**
+ * Free memory previously allocated with a context.  If using a pool allocator,
+ * this function will often be a no-op, but it must be supplied in order to
+ * prevent the CBOR library from calling `free(3)`.
+ *
+ * @note: it may be that this is never needed; if so, it will be removed for
+ * clarity and speed.
+ *
+ * @param  context [description]
+ * @return         [description]
+ */
+typedef void (*cn_free_func)(void *ptr, void *context);
+
+/**
+ * The allocation context.
+ */
+typedef struct cn_cbor_context {
+    /** The pool `calloc` routine.  Must allocate and zero. */
+    cn_calloc_func calloc_func;
+    /** The pool `free` routine.  Often a no-op, but required. */
+    cn_free_func  free_func;
+    /** Typically, the pool object, to be used when calling `calloc_func`
+      * and `free_func` */
+    void *context;
+} cn_cbor_context;
+
+extern cn_cbor_context *cbor_context;
+
+/** When USE_CBOR_CONTEXT is defined, many functions take an extra `context`
+  * parameter */
+#define CBOR_CONTEXT , cn_cbor_context *cbor_context
+/** When USE_CBOR_CONTEXT is defined, some functions take an extra `context`
+  * parameter at the beginning */
+#define CBOR_CONTEXT_COMMA cn_cbor_context *cbor_context,
+/** When USE_CBOR_CONTEXT is defined, some functions take a `context`
+  * parameter, as the only argument */
+#define CBOR_CONTEXT_NO_COMMA cn_cbor_context *cbor_context
+
+/** The following two defines are used by caller as arguments for the  
+  * function that is being called - to use context*/
+#define CBOR_CONTEXT_PARAM , cbor_context
+#define CBOR_CONTEXT_PARAM_COMMA cbor_context, 
+
+/** The following two defines are used by caller as arguments for the
+  * function that is being called - to force use of LIBC allocation instead of pool*/
+#define CBOR_CONTEXT_NULL , NULL
+#define CBOR_CONTEXT_NULL_COMMA NULL,
+
+
+#else
+
+#define CBOR_CONTEXT
+#define CBOR_CONTEXT_COMMA
+#define CBOR_CONTEXT_NO_COMMA void
+#define CBOR_CONTEXT_PARAM
+#define CBOR_CONTEXT_PARAM_COMMA
+#define CBOR_CONTEXT_NULL
+#define CBOR_CONTEXT_NULL_COMMA
+
+#endif
+
+/**
+ * Decode an array of CBOR bytes into structures.
+ *
+ * @param[in]  buf          The array of bytes to parse
+ * @param[in]  len          The number of bytes in the array
+ * @param[in]  CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
+ * @param[out] errp         Error, if NULL is returned
+ * @return                  The parsed CBOR structure, or NULL on error
+ */
+cn_cbor* cn_cbor_decode(const uint8_t *buf, size_t len CBOR_CONTEXT, cn_cbor_errback *errp);
+
+/**
+ * Get a value from a CBOR map that has the given string as a key.
+ *
+ * @param[in]  cb           The CBOR map
+ * @param[in]  key          The string to look up in the map
+ * @return                  The matching value, or NULL if the key is not found
+ */
+cn_cbor* cn_cbor_mapget_string(const cn_cbor* cb, const char* key);
+
+/**
+ * Get a value from a CBOR map that has the given integer as a key.
+ *
+ * @param[in]  cb           The CBOR map
+ * @param[in]  key          The int to look up in the map
+ * @return                  The matching value, or NULL if the key is not found
+ */
+cn_cbor* cn_cbor_mapget_int(const cn_cbor* cb, int key);
+
+/**
+ * Get the item with the given index from a CBOR array.
+ *
+ * @param[in]  cb           The CBOR map
+ * @param[in]  idx          The array index
+ * @return                  The matching value, or NULL if the index is invalid
+ */
+cn_cbor* cn_cbor_index(const cn_cbor* cb, unsigned int idx);
+
+/**
+ * Free the given CBOR structure.
+ * You MUST NOT try to free a cn_cbor structure with a parent (i.e., one
+ * that is not a root in the tree).
+ *
+ * @param[in]  cb           The CBOR value to free.  May be NULL, or a root object.
+ * @param[in]  CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
+ */
+void cn_cbor_free(cn_cbor* cb CBOR_CONTEXT);
+
+/**
+* Get the size of the buffer that must be provided to cn_cbor_encoder_write().
+* This is the size of the CBOR that will be encoded.
+*
+* @param[in]  cb         Pointer to a cn_cbor structure, which the user wishes to encode.
+* @param[out] err	 Error, if -1 is returned.
+* @return                -1 on fail, or number size of the allocated buffer containing the encoded data.
+*/
+
+int cn_cbor_get_encoded_size(const cn_cbor *cb, cn_cbor_errback *err);
+
+/**
+ * Write a CBOR value and all of the child values.
+ * Allocates a buffer of the correct size and fills it with the encoded CBOR. 
+ * User must free the buffer.
+ *
+ * @param[in]  cb         Pointer to a cn_cbor structure, which the user wishes to encode.
+ * @param[out] bufOut     Pointer a buffer which will be filled with the encoded data.
+ * @param[in]  bufSize	  Size of the provided buffer in bytes.
+ * @param[out] err	  Error, if -1 is returned.
+ * @return                -1 on fail, or number encoded bytes written to the provided buffer.
+ */
+
+int cn_cbor_encoder_write(const cn_cbor *cb, uint8_t *bufOut, int bufSize, cn_cbor_errback *err);
+
+/**
+* Get the size in bytes of the encoding of only cn_cbor container (map or array) discarding its parents and siblings.
+*
+* @param[in]  cb_container         Pointer to a cn_cbor structure of either type CN_CBOR_MAP or CN_CBOR_ARRAY. Mey be part of a bigger cn_cbor structure.
+* @return                          -1 on fail, or number encoded bytes the container will be .
+*/
+int cn_cbor_get_encoded_container_size(const cn_cbor *cb_container);
+
+/**
+ * Create a CBOR map.
+ *
+ * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
+ * @param[out]  errp         Error, if NULL is returned
+ * @return                   The created map, or NULL on error
+ */
+cn_cbor* cn_cbor_map_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp);
+
+/**
+ * Create a CBOR byte string.  The data in the byte string is *not* owned
+ * by the CBOR object, so it is not freed automatically.
+ *
+ * @param[in]   data         The data
+ * @param[in]   len          The number of bytes of data
+ * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
+ * @param[out]  errp         Error, if NULL is returned
+ * @return                   The created object, or NULL on error
+ */
+cn_cbor* cn_cbor_data_create(const uint8_t* data, int len
+                             CBOR_CONTEXT,
+                             cn_cbor_errback *errp);
+
+/**
+ * Create a CBOR UTF-8 string from a buffer. The data is not checked for UTF-8 correctness.
+ * The data being stored in the string is *not* owned the CBOR object, so it is
+ * not freed automatically.
+ *
+ * @param[in]   data         UTF-8 string (does not have to be NULL terminated)
+ * @param[in]   len          The number of bytes of data
+ * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
+ * @param[out]  errp         Error, if NULL is returned
+ * @return                   The created object, or NULL on error
+ */
+cn_cbor* cn_cbor_text_create(const uint8_t* data, int len
+                             CBOR_CONTEXT,
+                             cn_cbor_errback *errp);
+
+/**
+ * Create a CBOR UTF-8 string.  The data is not checked for UTF-8 correctness.
+ * The data being stored in the string is *not* owned the CBOR object, so it is
+ * not freed automatically.
+ *
+ * @note: Do NOT use this function with untrusted data.  It calls strlen, and
+ * relies on proper NULL-termination.
+ *
+ * @param[in]   data         NULL-terminated UTF-8 string
+ * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
+ * @param[out]  errp         Error, if NULL is returned
+ * @return                   The created object, or NULL on error
+ */
+cn_cbor* cn_cbor_string_create(const char* data
+                               CBOR_CONTEXT,
+                               cn_cbor_errback *errp);
+
+/**
+ * Create a CBOR integer (either positive or negative).
+ *
+ * @param[in]   value    the value of the integer
+ * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
+ * @param[out]  errp         Error, if NULL is returned
+ * @return                   The created object, or NULL on error
+ */
+cn_cbor* cn_cbor_int_create(int64_t value
+                            CBOR_CONTEXT,
+                            cn_cbor_errback *errp);
+
+
+/**
+* Create a CBOR unsigned integer ( positive ).
+*
+* @param[in]   value    the value of the  unsigned integer
+* @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
+* @param[out]  errp         Error, if NULL is returned
+* @return                   The created object, or NULL on error
+*/
+cn_cbor* cn_cbor_uint_create(uint64_t value
+    CBOR_CONTEXT,
+    cn_cbor_errback *errp);
+
+/**
+ * Put a CBOR object into a map with a CBOR object key.  Duplicate checks are NOT
+ * currently performed.
+ *
+ * @param[in]   cb_map       The map to insert into
+ * @param[in]   key          The key
+ * @param[in]   cb_value     The value
+ * @param[out]  errp         Error
+ * @return                   True on success
+ */
+bool cn_cbor_map_put(cn_cbor* cb_map,
+                     cn_cbor *cb_key, cn_cbor *cb_value,
+                     cn_cbor_errback *errp);
+
+/**
+ * Put a CBOR object into a map with an integer key.  Duplicate checks are NOT
+ * currently performed.
+ *
+ * @param[in]   cb_map       The map to insert into
+ * @param[in]   key          The integer key
+ * @param[in]   cb_value     The value
+ * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
+ * @param[out]  errp         Error
+ * @return                   True on success
+ */
+bool cn_cbor_mapput_int(cn_cbor* cb_map,
+                        int64_t key, cn_cbor* cb_value
+                        CBOR_CONTEXT,
+                        cn_cbor_errback *errp);
+
+/**
+ * Put a CBOR object into a map with a string key.  Duplicate checks are NOT
+ * currently performed.
+ *
+ * @note: do not call this routine with untrusted string data.  It calls
+ * strlen, and requires a properly NULL-terminated key.
+ *
+ * @param[in]   cb_map       The map to insert into
+ * @param[in]   key          The string key
+ * @param[in]   cb_value     The value
+ * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
+ * @param[out]  errp         Error
+ * @return                   True on success
+ */
+bool cn_cbor_mapput_string(cn_cbor* cb_map,
+                           const char* key, cn_cbor* cb_value
+                           CBOR_CONTEXT,
+                           cn_cbor_errback *errp);
+
+/**
+ * Create a CBOR array
+ *
+ * @param[in]   CBOR_CONTEXT Allocation context (only if USE_CBOR_CONTEXT is defined)
+ * @param[out]  errp         Error, if NULL is returned
+ * @return                   The created object, or NULL on error
+ */
+cn_cbor* cn_cbor_array_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp);
+
+/**
+ * Append an item to the end of a CBOR array.
+ *
+ * @param[in]   cb_array  The array into which to insert
+ * @param[in]   cb_value  The value to insert
+ * @param[out]  errp      Error
+ * @return                True on success
+ */
+bool cn_cbor_array_append(cn_cbor* cb_array,
+                          cn_cbor* cb_value,
+                          cn_cbor_errback *errp);
+
+#ifdef USE_CBOR_CONTEXT
+
+// The maximum number of CBOR objects in an allocated pool.
+#define MAX_SIZE_POOL_IN_CBORS 64
+
+/**
+* Init a new cn_cbor_context.
+* This will dynamically allocate a pool of cn_cbor objects and must be freed by calling cn_cbor_free_context.
+* FIXME: The created context is currently stored as a global in cn-cbor.c for easy access and convenience.
+*        This means only one CBOR context can be used at a time and is prone to errors if we are not careful.
+*        In the future we will probably want to init a context and and pass it on all the way to the cn_cbor functions that need access to it, Instead of using a global.
+*        This will also allow us to use several contexts at a time and run multi-threaded.
+*
+* @param[in]   num_of_cbors_in_pool The number of cn_cbor object in the pool. The size of the dynamically allocated pool will be num_of_cbors_in_pool * sizeof(cn_cbor)
+*
+* @return      A pointer to the created context, or NULL in case of error
+*/
+cn_cbor_context *cn_cbor_init_context(size_t num_of_cbors_in_pool);
+
+/**
+* Release the resources of a cn_cbor_context.
+* Releases the dynamically allocated pool. if either ctx is NULL or the pool is NULL,
+* then the function will do nothing. This should never happen, unless user committed an error.
+* The function does not return anything to conform with standard freeing practices.
+*
+* @param[in]    ctx Pointer to the cn_cbor_context object which points to the memory pool we wish to free
+*
+*/
+void cn_cbor_free_context(cn_cbor_context *ctx);
+
+#ifdef USE_CBOR_CONTEXT_STATS
+
+/**
+* Print stats of the memory allocations of the CBOR library.
+*/
+void cn_cbor_context_print_stats(void);
+
+/**
+* Resets the stats of the memory allocations of the CBOR library.
+*/
+void cn_cbor_context_reset_stats(void);
+
+#else
+#define cn_cbor_context_print_stats()
+#define cn_cbor_context_reset_stats()
+#endif // USE_CBOR_CONTEXT_STATS
+
+#endif // USE_CBOR_CONTEXT
+
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif  /* CN_CBOR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/source/cn-cbor.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,328 @@
+#ifndef CN_CBOR_C
+#define CN_CBOR_C
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+#ifdef EMACS_INDENTATION_HELPER
+} /* Duh. */
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+#ifdef CBOR_CAN_DO_UNALIGNED_READS
+#include <arpa/inet.h> // needed for ntohl (e.g.) on Linux
+#endif
+
+#include "cn-cbor.h"
+#include "cbor.h"
+
+
+#define CN_CBOR_FAIL(code) do { pb->err = code;  goto fail; } while(0)
+
+void cn_cbor_free(cn_cbor* cb CBOR_CONTEXT) {
+  cn_cbor* p = cb;
+  assert(!p || !p->parent);
+  while (p) {
+    cn_cbor* p1;
+    p1 = p->first_child;
+    while ((p1)) { /* go down */
+      p = p1;
+      p1 = p->first_child;
+    }
+    p1 = p->next;
+    if (!(p1)) {   /* go up next */
+      p1 = p->parent;
+      if ((p1))
+        p1->first_child = 0;
+    }
+    CN_CBOR_FREE_CONTEXT(p);
+    p = p1;
+  }
+}
+
+#ifndef CBOR_NO_FLOAT
+static double decode_half(int half) {
+  int exp = (half >> 10) & 0x1f;
+  int mant = half & 0x3ff;
+  double val = 0;
+  if (exp == 0) {
+    val = ldexp(mant, -24);
+  } else if (exp != 31) {
+    val = ldexp(mant + 1024, exp - 25);
+  } else {
+    if (mant == 0) {
+      val = INFINITY;
+    } else {
+      val = NAN;
+    }
+  }
+  return half & 0x8000 ? -val : val;
+}
+#endif /* CBOR_NO_FLOAT */
+
+/* Fix these if you can't do non-aligned reads */
+#define ntoh8p(p) (*(unsigned char*)(p))
+#ifdef CBOR_CAN_DO_UNALIGNED_READS
+#define ntoh16p(p) (ntohs(*(unsigned short*)(p)))
+#define ntoh32p(p) (ntohl(*(unsigned long*)(p)))
+#else
+static uint16_t ntoh16p(unsigned char *p) {
+  uint16_t ret = ntoh8p(p);
+  ret <<= 8;
+  ret += ntoh8p(p+1);
+  return ret;
+}
+static uint32_t ntoh32p(unsigned char *p) {
+  uint64_t ret = ntoh16p(p);
+  ret <<= 16;
+  ret += ntoh16p(p+2);
+  return ret;
+}
+#endif
+static uint64_t ntoh64p(unsigned char *p) {
+  uint64_t ret = ntoh32p(p);
+  ret <<= 32;
+  ret += ntoh32p(p+4);
+  return ret;
+}
+
+static cn_cbor_type mt_trans[] = {
+  CN_CBOR_UINT,    CN_CBOR_INT,
+  CN_CBOR_BYTES,   CN_CBOR_TEXT,
+  CN_CBOR_ARRAY,   CN_CBOR_MAP,
+  CN_CBOR_TAG,     CN_CBOR_SIMPLE,
+};
+
+struct parse_buf {
+  unsigned char *buf;
+  unsigned char *ebuf;
+  cn_cbor_error err;
+};
+
+#define TAKE(pos, ebuf, n, stmt)                \
+  if (n > (size_t)(ebuf - pos))                 \
+    CN_CBOR_FAIL(CN_CBOR_ERR_OUT_OF_DATA);      \
+  stmt;                                         \
+  pos += n;
+
+static cn_cbor *decode_item (struct parse_buf *pb CBOR_CONTEXT, cn_cbor* top_parent) {
+  unsigned char *pos = pb->buf;
+  unsigned char *ebuf = pb->ebuf;
+  cn_cbor* parent = top_parent;
+  int ib;
+  unsigned int mt;
+  int ai;
+  uint64_t val;
+  cn_cbor* cb = NULL;
+#ifndef CBOR_NO_FLOAT
+  union {
+    float f;
+    uint32_t u;
+  } u32;
+  union {
+    double d;
+    uint64_t u;
+  } u64;
+#endif /* CBOR_NO_FLOAT */
+
+again:
+  TAKE(pos, ebuf, 1, ib = ntoh8p(pos) );
+  if (ib == IB_BREAK) {
+    if (!(parent->flags & CN_CBOR_FL_INDEF))
+      CN_CBOR_FAIL(CN_CBOR_ERR_BREAK_OUTSIDE_INDEF);
+    switch (parent->type) {
+    case CN_CBOR_BYTES: case CN_CBOR_TEXT:
+      parent->type += 2;            /* CN_CBOR_* -> CN_CBOR_*_CHUNKED */
+      break;
+    case CN_CBOR_MAP:
+      if (parent->length & 1)
+        CN_CBOR_FAIL(CN_CBOR_ERR_ODD_SIZE_INDEF_MAP);
+    default:;
+    }
+    goto complete;
+  }
+  mt = ib >> 5;
+  ai = ib & 0x1f;
+  val = ai;
+
+  cb = CN_CALLOC_CONTEXT();
+  if (!cb)
+    CN_CBOR_FAIL(CN_CBOR_ERR_OUT_OF_MEMORY);
+
+  cb->type = mt_trans[mt];
+
+  cb->parent = parent;
+  if (parent->last_child) {
+    parent->last_child->next = cb;
+  } else {
+    parent->first_child = cb;
+  }
+  parent->last_child = cb;
+  parent->length++;
+
+  switch (ai) {
+  case AI_1: TAKE(pos, ebuf, 1, val = ntoh8p(pos))  ; cb->length = 1; break;
+  case AI_2: TAKE(pos, ebuf, 2, val = ntoh16p(pos)) ; cb->length = 2; break;
+  case AI_4: TAKE(pos, ebuf, 4, val = ntoh32p(pos)) ; cb->length = 4; break;
+  case AI_8: TAKE(pos, ebuf, 8, val = ntoh64p(pos)) ; cb->length = 8; break;
+
+  case 28: case 29: case 30: CN_CBOR_FAIL(CN_CBOR_ERR_RESERVED_AI);
+  case AI_INDEF:
+    if ((mt - MT_BYTES) <= MT_MAP) {
+      cb->flags |= CN_CBOR_FL_INDEF;
+      goto push;
+    } else {
+      CN_CBOR_FAIL(CN_CBOR_ERR_MT_UNDEF_FOR_INDEF);
+    }
+  }
+  // process content
+  switch (mt) {
+  case MT_UNSIGNED:
+    cb->v.uint = val;           /* to do: Overflow check */
+  	/*
+  	   if the integer itsef is used (ai=0..23), set the length to 4, for compliance   
+  	   with the definition that integer values of mbed.UseBootstrap and mbed.MemoryTotalKB 
+  	   is 4 bytes. 
+  	   This implementation might cause bugs with other parameters that has no such requirement, 
+  	   so the code should be changed in the future
+  	*/
+  	if (cb->length == 0) {
+		cb->length = 4;		
+  	}
+    break;
+  case MT_NEGATIVE:
+    cb->v.sint = ~val;          /* to do: Overflow check */
+  	/*
+	   if the integer itsef is used (ai=0..23), set the length to 4, for compliance   
+	   with the definition that integer values of mbed.UseBootstrap and mbed.MemoryTotalKB 
+	   is 4 bytes. 
+	   This implementation might cause bugs with other parameters that has no such requirement, 
+	   so the code should be changed in the future
+  	*/
+	if (cb->length == 0) {
+		cb->length = 4;		
+  	}
+    break;
+  case MT_BYTES: case MT_TEXT:
+    cb->v.str = (char *) pos;
+    cb->length = val;
+    TAKE(pos, ebuf, val, ;);
+    break;
+  case MT_MAP:
+    val <<= 1;
+    /* fall through */
+  case MT_ARRAY:
+    cb->v.count = val;
+    if ((cb->v.count)) {
+      cb->flags |= CN_CBOR_FL_COUNT;
+      goto push;
+    }
+    break;
+  case MT_TAG:
+    cb->v.uint = val;
+    goto push;
+  case MT_PRIM:
+    switch (ai) {
+    case VAL_FALSE: cb->type = CN_CBOR_FALSE; break;
+    case VAL_TRUE:  cb->type = CN_CBOR_TRUE;  break;
+    case VAL_NIL:   cb->type = CN_CBOR_NULL;  break;
+    case VAL_UNDEF: cb->type = CN_CBOR_UNDEF; break;
+    case AI_2:
+#ifndef CBOR_NO_FLOAT
+      cb->type = CN_CBOR_DOUBLE;
+      cb->v.dbl = decode_half(val);
+#else /*  CBOR_NO_FLOAT */
+      CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED);
+#endif /*  CBOR_NO_FLOAT */
+      break;
+    case AI_4:
+#ifndef CBOR_NO_FLOAT
+      cb->type = CN_CBOR_DOUBLE;
+      u32.u = val;
+      cb->v.dbl = u32.f;
+#else /*  CBOR_NO_FLOAT */
+      CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED);
+#endif /*  CBOR_NO_FLOAT */
+      break;
+    case AI_8:
+#ifndef CBOR_NO_FLOAT
+      cb->type = CN_CBOR_DOUBLE;
+      u64.u = val;
+      cb->v.dbl = u64.d;
+#else /*  CBOR_NO_FLOAT */
+      CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED);
+#endif /*  CBOR_NO_FLOAT */
+      break;
+    default: cb->v.uint = val;
+    }
+  }
+fill:                           /* emulate loops */
+  if (parent->flags & CN_CBOR_FL_INDEF) {
+    if (parent->type == CN_CBOR_BYTES || parent->type == CN_CBOR_TEXT)
+      if (cb->type != parent->type)
+          CN_CBOR_FAIL(CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING);
+    goto again;
+  }
+  if (parent->flags & CN_CBOR_FL_COUNT) {
+    if (--parent->v.count)
+      goto again;
+  }
+  /* so we are done filling parent. */
+complete:                       /* emulate return from call */
+  if (parent == top_parent) {
+    if (pos != ebuf)            /* XXX do this outside */
+      CN_CBOR_FAIL(CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED);
+    pb->buf = pos;
+    return cb;
+  }
+  cb = parent;
+  parent = parent->parent;
+  goto fill;
+push:                           /* emulate recursive call */
+  parent = cb;
+  goto again;
+fail:
+  pb->buf = pos;
+  return 0;
+}
+
+cn_cbor* cn_cbor_decode(const unsigned char* buf, size_t len CBOR_CONTEXT, cn_cbor_errback *errp) {
+  cn_cbor catcher;
+  struct parse_buf pb;
+  cn_cbor* ret;
+  
+  memset(&catcher,0 , sizeof(cn_cbor));
+  catcher.type = CN_CBOR_INVALID;
+  pb.buf  = (unsigned char *)buf;
+  pb.ebuf = (unsigned char *)buf+len;
+  pb.err  = CN_CBOR_NO_ERROR;
+  ret = decode_item(&pb CBOR_CONTEXT_PARAM, &catcher);
+  if (ret != NULL) {
+    /* mark as top node */
+    ret->parent = NULL;
+  } else {
+
+    if (catcher.first_child) {
+      catcher.first_child->parent = 0;
+      cn_cbor_free(catcher.first_child CBOR_CONTEXT_PARAM);
+    }
+//fail:
+    if (errp) {
+      errp->err = pb.err;
+      errp->pos = pb.buf - (unsigned char *)buf;
+    }
+    return NULL;
+  }
+  return ret;
+}
+
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif  /* CN_CBOR_C */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/source/cn-context.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,282 @@
+#ifdef USE_CBOR_CONTEXT
+#include "cn-cbor.h"
+#include "cbor.h"
+#include <stdlib.h>
+#include <string.h>
+
+cn_cbor_context context_obj;
+cn_cbor_context *cbor_context = &context_obj;
+cbor_mem_pool mem_pool_internal;
+
+#ifdef USE_CBOR_CONTEXT_STATS
+uint32_t calloc_heap_cntr = 0;
+uint32_t free_heap_cntr = 0;
+uint32_t calloc_pool_cntr = 0;
+uint32_t free_pool_cntr = 0;
+uint32_t bytes_heap_allocated = 0;
+uint32_t total_bytes_heap_allocated = 0;
+uint32_t max_bytes_heap_allocated = 0;
+uint32_t bytes_pool_allocated = 0;
+uint32_t total_bytes_pool_allocated = 0;
+uint32_t max_bytes_pool_allocated = 0;
+uint32_t number_of_pools_allocated = 0;
+uint32_t total_bytes_allocated_for_pools = 0;
+#endif // USE_CBOR_CONTEXT_STATS
+
+//#include <strings.h>
+
+#define BITMAP_ENTRY_SIZE_IN_BITS ( sizeof(mem_pool->bitmap[0]) * 8 )
+#define BITMAP_FULL (-1)
+
+#ifdef USE_CBOR_CONTEXT_STATS
+#define CBOR_STATS_FREE(mem) do { \
+                                        free_##mem##_cntr++; \
+                                        bytes_##mem##_allocated -= sizeof(cn_cbor); \
+                                      } while(0) 
+
+#define CBOR_STATS_CALLOC(mem, size, count) do { \
+                                        calloc_##mem##_cntr++; \
+                                        bytes_##mem##_allocated += size * count; \
+                                        total_bytes_##mem##_allocated += size * count; \
+                                        if (bytes_##mem##_allocated > max_bytes_##mem##_allocated) { \
+                                            max_bytes_##mem##_allocated = bytes_##mem##_allocated; \
+                                        } \
+                                        } while (0)
+#else
+#define CBOR_STATS_FREE(mem) 
+#define CBOR_STATS_CALLOC(mem, size, count) 
+#endif //USE_CBOR_CONTEXT_STATS
+
+// Count leading zeros in pure C (https://stackoverflow.com/questions/23856596/counting-leading-zeros-in-a-32-bit-unsigned-integer-with-best-algorithm-in-c-pro) 
+static int clz_pure_c(uint32_t a)
+{
+    static const char debruijn32[32] = {
+        0, 31, 9, 30, 3, 8, 13, 29, 2, 5, 7, 21, 12, 24, 28, 19,
+        1, 10, 4, 14, 6, 22, 25, 20, 11, 15, 23, 26, 16, 27, 17, 18
+    };
+
+    // This algorithm does work correctly for input 0, so we handle it independently
+    if (a == 0) {
+        return 32;
+    }
+
+    a |= a >> 1;
+    a |= a >> 2;
+    a |= a >> 4;
+    a |= a >> 8;
+    a |= a >> 16;
+    a++;
+
+    return debruijn32[a * 0x076be629 >> 27];
+}
+
+// Count leading zeros. Use compiler functions that use direct machine instructions if possible
+static int count_leading_zeros(uint32_t a)
+{
+    // If GCC
+#if defined(__GNUC__)
+    return __builtin_clz(a);
+#elif defined(__arm__)
+    return __clz(a);
+
+#else // If not GCC or ARMCC, use pure C implementation
+    return clz_pure_c();
+
+#endif
+}
+
+// Count trailing zeros using using the count leading zeros command (https://community.arm.com/community-help/f/discussions/2114/count-trailing-zeros)
+static int ctz(uint32_t a)
+{
+    int c = count_leading_zeros(a & -a);
+    return a ? 31 - c : c;
+}
+
+// Get the index of the first 0 bit in bitmap_entry
+static int find_first_open_slot(int32_t bitmap_entry)
+{
+    int pos = ctz(~bitmap_entry);
+
+    return (pos < 32) ? pos : -1;
+}
+
+// NOTE: CBOR library uses only calloc(1, sizeof(cn_cbor)). Currently only calloc(1,sizeof(cn_cbor)) is supported by the allocator
+/**
+* Allocate space for count (currently must be 1) CBOR elements.
+*
+* NOTE: CBOR library uses only calloc(1, sizeof(cn_cbor)). Currently only calloc(1,sizeof(cn_cbor)) currently supported by allocator.
+* @param[in] count             Count of number of elements in allocated array. Currently must be 1.
+* @param[in]  size             Size of each element in the allocated array. Must be sizeof(cn_cbor)
+* @param[in]  context          Pointer to the CBOR context.
+* @return                      The address of the allocated memory.
+*/
+void *cbor_calloc(size_t count, size_t size, void *context)
+{
+    void *ret_mem;
+    int bitmap_idx, pos, bit_pos, max_bitmap_idx;
+    cbor_mem_pool *mem_pool = (cbor_mem_pool *)(context);
+
+    // Currently supports only allocations of 1 slot. CBOR lib never allocates more than that.
+    if (count != 1 || size != sizeof(cn_cbor)) {
+        return NULL;
+    }
+
+    // Get the index of the last entry in the bitmap array
+    max_bitmap_idx = mem_pool->pool_size_in_cbors / BITMAP_ENTRY_SIZE_IN_BITS;
+
+    // If number of CBOR objects in pool is not divisible by 8, there is an additional entry to the bitmap for the residue
+    if (mem_pool->pool_size_in_cbors % BITMAP_ENTRY_SIZE_IN_BITS != 0) {
+        max_bitmap_idx++;
+    }
+
+    for (bitmap_idx = 0; bitmap_idx < max_bitmap_idx; bitmap_idx++) {
+        // If bitmap entry is full, try next
+        if (mem_pool->bitmap[bitmap_idx] == BITMAP_FULL) {
+            continue;
+        }
+        // Find first open slot in bitmap[bitmap_idx]
+        bit_pos = find_first_open_slot(mem_pool->bitmap[bitmap_idx]);
+        // If found open slot
+        if (bit_pos >= 0) {
+
+            // Adjust position for CBOR pool
+            pos = bit_pos + (bitmap_idx * BITMAP_ENTRY_SIZE_IN_BITS);
+
+            // If position not in pool (since the size is not divisible by the size of each entry in the bitmap array in bits)
+            if (pos >= mem_pool->pool_size_in_cbors) {
+                break;
+            }
+
+            ret_mem = &(mem_pool->pool[pos]);
+
+            // Zero the returned memory (CBOR lib demands this)
+            memset(ret_mem, 0, sizeof(mem_pool->pool[pos]));
+
+            // Set the bit in index pos
+            mem_pool->bitmap[bitmap_idx] = mem_pool->bitmap[bitmap_idx] | (1ULL << bit_pos);
+
+            CBOR_STATS_CALLOC(pool, size, count);
+            return ret_mem;
+        }
+    }
+
+    // If no space in pool, use LIBC calloc
+    CBOR_STATS_CALLOC(heap, size, count);
+    return calloc(count, size);
+}
+
+// Return whether a given address resides within the allocated CBOR pool
+#define IS_IN_POOL(cbor_ptr, mem_pool) (( (uint8_t*)cbor_ptr >= ((uint8_t*) &(mem_pool->pool[0]))) && ( (uint8_t*)cbor_ptr <= ((uint8_t*) &(mem_pool->pool[mem_pool->pool_size_in_cbors - 1]))))
+
+// Assuming cbor_ptr points to a cn_cbor object in the pool, return its index in the pool. Use this macro ONLY after asserting that cbor_ptr is in pool using IS_IN_POOL().
+#define POS_IN_POOL(cbor_ptr, mem_pool) ( ((uint8_t*)cbor_ptr - ((uint8_t*) &(mem_pool->pool[0]))) / sizeof(mem_pool->pool[0]) )
+
+// Get the index of the bitmap array, in which the bit corresponding to mem_pool->pool[position_in_pool] resides.
+#define INDEX_IN_BITMAP(position_in_pool, mem_pool) ( position_in_pool / (sizeof(mem_pool->bitmap[0]) * 8 ) )
+
+// Get the position of the bit in the bitmap, corresponding to mem_pool->pool[position_in_pool].
+#define POS_IN_INDEX(position_in_pool) ( position_in_pool % (sizeof(mem_pool->bitmap[0]) * 8 ) )
+
+/**
+* Free a cn_cbor object.
+* If the cn_cbor pointed to by ptr is in the pool, simply unset the corresponding bit in the bitmap.
+* If the cn_cbor pointed to by ptr is not in the pool, assume it was allocated with LIBC calloc (since pool was full), and free it using LIBC free.
+*
+* @param[in]  ptr              Pointer to a cn_cbor object we wish to free
+* @param[in]  context          Pointer to the CBOR context.
+* @return                      The address of the allocated memory.
+*/
+
+void cbor_free(void *ptr, void *context)
+{
+    int pos, bitmap_idx;
+    cbor_mem_pool *mem_pool = (cbor_mem_pool *)(context);
+
+    // If ptr is in internal pool simply unset its bit in the bitmap
+    if (IS_IN_POOL(ptr, mem_pool)) {
+        // Get position of the bit
+        pos = POS_IN_POOL(ptr, mem_pool);
+
+        bitmap_idx = INDEX_IN_BITMAP(pos, mem_pool);
+        int pos_in_index = POS_IN_INDEX(pos);
+        // Set the bit in the corresponding offset in the correct index of the bitmap
+        mem_pool->bitmap[bitmap_idx] = mem_pool->bitmap[bitmap_idx] & ~(1ULL << pos_in_index);
+
+        CBOR_STATS_FREE(pool);
+    } else { // If not in pool - allocated with libc calloc(), so we use libc free()
+        free(ptr);
+
+        CBOR_STATS_FREE(heap);
+    }
+}
+
+cn_cbor_context *cn_cbor_init_context(size_t num_of_cbors_in_pool)
+{
+    if (num_of_cbors_in_pool > MAX_SIZE_POOL_IN_CBORS) {
+        return NULL;
+    }
+
+    memset(&mem_pool_internal, 0, sizeof(mem_pool_internal));
+
+    cbor_context->calloc_func = cbor_calloc;
+    cbor_context->free_func = cbor_free;
+
+    mem_pool_internal.pool = calloc(num_of_cbors_in_pool, sizeof(cn_cbor));
+    mem_pool_internal.pool_size_in_cbors = num_of_cbors_in_pool;
+
+    cbor_context->context = &mem_pool_internal;
+
+#ifdef USE_CBOR_CONTEXT_STATS
+    number_of_pools_allocated++;
+    total_bytes_allocated_for_pools += (num_of_cbors_in_pool * sizeof(cn_cbor));
+#endif // USE_CBOR_CONTEXT_STATS
+
+    return cbor_context;
+}
+
+void cn_cbor_free_context(cn_cbor_context *ctx)
+{
+    if (ctx && ctx->context) {
+        free(((cbor_mem_pool *)(ctx->context))->pool);
+    }
+}
+
+#ifdef USE_CBOR_CONTEXT_STATS
+#include <inttypes.h>
+void cn_cbor_context_print_stats()
+{
+    printf("  ***************** CBOR Memory Statistics *****************\n");
+    printf("  * Total bytes allocated on heap:                       %" PRIu32 "\n", total_bytes_heap_allocated);
+    printf("  * Number of heap allocations:                          %" PRIu32 "\n", calloc_heap_cntr);
+    printf("  * Number of heap frees:                                %" PRIu32 "\n", free_heap_cntr);
+    printf("  * Max peak ever allocated (heap):                      %" PRIu32 "\n", max_bytes_heap_allocated);
+    printf("  *\n");
+    printf("  * Total bytes allocated in pool:                       %" PRIu32 "\n", total_bytes_pool_allocated);
+    printf("  * Number of pool allocations:                          %" PRIu32 "\n", calloc_pool_cntr);
+    printf("  * Number of pool frees:                                %" PRIu32 "\n", free_pool_cntr);
+    printf("  * Max peak ever allocated (pool):                      %" PRIu32 "\n", max_bytes_pool_allocated);
+    printf("  *\n");
+    printf("  * Total size of All CBOR pools ever allocated (bytes): %" PRIu32 "\n", total_bytes_allocated_for_pools);
+    printf("  * Number of pools allocated:                           %" PRIu32 "\n", number_of_pools_allocated);
+    printf("  ***********************************************************\n");
+}
+
+void cn_cbor_context_reset_stats()
+{
+    calloc_heap_cntr = 0;
+    free_heap_cntr = 0;
+    calloc_pool_cntr = 0;
+    free_pool_cntr = 0;
+    bytes_heap_allocated = 0;
+    total_bytes_heap_allocated = 0;
+    max_bytes_heap_allocated = 0;
+    bytes_pool_allocated = 0;
+    total_bytes_pool_allocated = 0;
+    max_bytes_pool_allocated = 0;
+    number_of_pools_allocated = 0;
+    total_bytes_allocated_for_pools = 0;
+}
+
+#endif // USE_CBOR_CONTEXT_STATS
+
+#endif // USE_CBOR_CONTEXT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/source/cn-create.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,211 @@
+#ifndef CN_CREATE_C
+#define CN_CREATE_C
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "cn-cbor.h"
+#include "cbor.h"
+
+#define INIT_CB(v) \
+  if (errp) {errp->err = CN_CBOR_NO_ERROR;} \
+  (v) = CN_CALLOC_CONTEXT(); \
+  if (!(v)) { if (errp) {errp->err = CN_CBOR_ERR_OUT_OF_MEMORY;} return NULL; }
+
+cn_cbor* cn_cbor_map_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp)
+{
+  cn_cbor* ret;
+  INIT_CB(ret);
+
+  ret->type = CN_CBOR_MAP;
+  ret->flags |= CN_CBOR_FL_COUNT;
+
+  return ret;
+}
+
+cn_cbor* cn_cbor_data_create(const uint8_t* data, int len
+                             CBOR_CONTEXT,
+                             cn_cbor_errback *errp)
+{
+  cn_cbor* ret;
+  INIT_CB(ret);
+
+  ret->type = CN_CBOR_BYTES;
+  ret->length = len;
+  ret->v.str = (const char*) data; // TODO: add v.ustr to the union?
+
+  return ret;
+}
+
+cn_cbor* cn_cbor_text_create(const uint8_t* data, int len
+                             CBOR_CONTEXT,
+                             cn_cbor_errback *errp)
+{
+    cn_cbor* ret;
+    INIT_CB(ret);
+
+    ret->type = CN_CBOR_TEXT;
+    ret->length = len;
+    ret->v.str = (const char*)data; 
+
+    return ret;
+}
+
+cn_cbor* cn_cbor_string_create(const char* data
+                               CBOR_CONTEXT,
+                               cn_cbor_errback *errp)
+{
+  cn_cbor* ret;
+  INIT_CB(ret);
+
+  ret->type = CN_CBOR_TEXT;
+  ret->length = strlen(data);
+  ret->v.str = data;
+
+  return ret;
+}
+
+cn_cbor* cn_cbor_int_create(int64_t value
+                            CBOR_CONTEXT,
+                            cn_cbor_errback *errp)
+{
+  cn_cbor* ret;
+  INIT_CB(ret);
+
+  if (value<0) {
+    ret->type = CN_CBOR_INT;
+    ret->v.sint = value;
+  } else {
+    ret->type = CN_CBOR_UINT;
+    ret->v.uint = value;
+  }
+
+  return ret;
+}
+
+cn_cbor* cn_cbor_uint_create(uint64_t value
+                             CBOR_CONTEXT,
+                             cn_cbor_errback *errp)
+{
+  cn_cbor* ret;
+  INIT_CB(ret);
+
+  ret->type = CN_CBOR_UINT;
+  ret->v.uint = value;
+
+  return ret;
+}
+
+static bool _append_kv(cn_cbor *cb_map, cn_cbor *key, cn_cbor *val)
+{
+  //Connect key and value and insert them into the map.
+  key->parent = cb_map;
+  key->next = val;
+  val->parent = cb_map;
+  val->next = NULL;
+
+  if(cb_map->last_child) {
+    cb_map->last_child->next = key;
+  } else {
+    cb_map->first_child = key;
+  }
+  cb_map->last_child = val;
+  cb_map->length += 2;
+  return true;
+}
+
+bool cn_cbor_map_put(cn_cbor* cb_map,
+                     cn_cbor *cb_key, cn_cbor *cb_value,
+                     cn_cbor_errback *errp)
+{
+  //Make sure input is a map. Otherwise
+  if(!cb_map || !cb_key || !cb_value || cb_map->type != CN_CBOR_MAP)
+  {
+    if (errp) {errp->err = CN_CBOR_ERR_INVALID_PARAMETER;}
+    return false;
+  }
+
+  return _append_kv(cb_map, cb_key, cb_value);
+}
+
+bool cn_cbor_mapput_int(cn_cbor* cb_map,
+                        int64_t key, cn_cbor* cb_value
+                        CBOR_CONTEXT,
+                        cn_cbor_errback *errp)
+{
+  cn_cbor* cb_key;
+
+  //Make sure input is a map. Otherwise
+  if(!cb_map || !cb_value || cb_map->type != CN_CBOR_MAP)
+  {
+    if (errp) {errp->err = CN_CBOR_ERR_INVALID_PARAMETER;}
+    return false;
+  }
+
+  cb_key = cn_cbor_int_create(key CBOR_CONTEXT_PARAM, errp);
+  if (!cb_key) { return false; }
+  return _append_kv(cb_map, cb_key, cb_value);
+}
+
+bool cn_cbor_mapput_string(cn_cbor* cb_map,
+                           const char* key, cn_cbor* cb_value
+                           CBOR_CONTEXT,
+                           cn_cbor_errback *errp)
+{
+  cn_cbor* cb_key;
+
+  //Make sure input is a map. Otherwise
+  if(!cb_map || !cb_value || cb_map->type != CN_CBOR_MAP)
+  {
+    if (errp) {errp->err = CN_CBOR_ERR_INVALID_PARAMETER;}
+    return false;
+  }
+
+  cb_key = cn_cbor_string_create(key CBOR_CONTEXT_PARAM,  errp);
+  if (!cb_key) { return false; }
+  return _append_kv(cb_map, cb_key, cb_value);
+}
+
+cn_cbor* cn_cbor_array_create(CBOR_CONTEXT_COMMA cn_cbor_errback *errp)
+{
+  cn_cbor* ret;
+  INIT_CB(ret);
+
+  ret->type = CN_CBOR_ARRAY;
+  ret->flags |= CN_CBOR_FL_COUNT;
+
+  return ret;
+}
+
+bool cn_cbor_array_append(cn_cbor* cb_array,
+                          cn_cbor* cb_value,
+                          cn_cbor_errback *errp)
+{
+  //Make sure input is an array.
+  if(!cb_array || !cb_value || cb_array->type != CN_CBOR_ARRAY)
+  {
+    if (errp) {errp->err = CN_CBOR_ERR_INVALID_PARAMETER;}
+    return false;
+  }
+
+  cb_value->parent = cb_array;
+  cb_value->next = NULL;
+  if(cb_array->last_child) {
+    cb_array->last_child->next = cb_value;
+  } else {
+    cb_array->first_child = cb_value;
+  }
+  cb_array->last_child = cb_value;
+  cb_array->length++;
+  return true;
+}
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif  /* CN_CBOR_C */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/source/cn-encoder.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,433 @@
+#ifndef CN_ENCODER_C
+#define CN_ENCODER_C
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+#ifdef EMACS_INDENTATION_HELPER
+} /* Duh. */
+#endif
+
+#include <string.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <limits.h>
+#include <math.h>
+#include "cn-cbor.h"
+#include "cbor.h"
+
+// Provide our own implementation of htons() and htonl() to avoid inclusion of inet.h or arpa/inet,h,
+// which can create unintended depedencies.
+
+static uint16_t htons(const uint16_t host16) {
+  uint16_t be16;
+  uint8_t *be16_ptr = (uint8_t*)&be16;
+
+  be16_ptr[0] = (host16 >> 8) & 0xff;
+  be16_ptr[1] = (host16 >> 0) & 0xff;
+
+  return be16;
+}
+
+static uint32_t htonl(const uint32_t host32) {
+  uint32_t be32;
+  uint8_t *be32_ptr = (uint8_t*)&be32;
+
+  be32_ptr[0] = (host32 >> 24) & 0xff;
+  be32_ptr[1] = (host32 >> 16) & 0xff;
+  be32_ptr[2] = (host32 >> 8)  & 0xff;
+  be32_ptr[3] = (host32 >> 0)  & 0xff;
+
+  return be32;
+}
+
+#define hton8p(p) (*(uint8_t*)(p))
+#define hton16p(p) (htons(*(uint16_t*)(p)))
+#define hton32p(p) (htonl(*(uint32_t*)(p)))
+static uint64_t hton64p(const uint8_t *p) {
+  /* TODO: does this work on both BE and LE systems? */
+  uint64_t ret = hton32p(p);
+  ret <<= 32;
+  ret |= hton32p(p+4);
+  return ret;
+}
+
+typedef struct _write_state
+{
+  uint8_t *buf;
+  int offset;
+  int size;
+} cn_write_state;
+
+#define ensure_writable(sz) if ((ws->offset<0) || (ws->offset + (sz) > ws->size)) { \
+	ws->offset = -1; \
+	return; \
+}
+
+#define write_byte_and_data(b, data, sz) \
+if (ws->buf == NULL) { ws->offset += sz + 1; } \
+else { \
+ws->buf[ws->offset++] = (b); \
+memcpy(ws->buf + ws->offset, (data), (sz)); \
+ws->offset += sz; \
+}
+
+#define write_byte(b) \
+if (ws->buf == NULL) { ws->offset++; } \
+else { ws->buf[ws->offset++] = (b); } \
+
+#define write_byte_ensured(b) \
+ensure_writable(1); \
+write_byte(b); \
+
+static uint8_t _xlate[] = {
+  IB_FALSE,    /* CN_CBOR_FALSE */
+  IB_TRUE,     /* CN_CBOR_TRUE */
+  IB_NIL,      /* CN_CBOR_NULL */
+  IB_UNDEF,    /* CN_CBOR_UNDEF */
+  IB_UNSIGNED, /* CN_CBOR_UINT */
+  IB_NEGATIVE, /* CN_CBOR_INT */
+  IB_BYTES,    /* CN_CBOR_BYTES */
+  IB_TEXT,     /* CN_CBOR_TEXT */
+  IB_BYTES,    /* CN_CBOR_BYTES_CHUNKED */
+  IB_TEXT,     /* CN_CBOR_TEXT_CHUNKED */
+  IB_ARRAY,    /* CN_CBOR_ARRAY */
+  IB_MAP,      /* CN_CBOR_MAP */
+  IB_TAG,      /* CN_CBOR_TAG */
+  IB_PRIM,     /* CN_CBOR_SIMPLE */
+  0xFF,        /* CN_CBOR_DOUBLE */
+  0xFF         /* CN_CBOR_INVALID */
+};
+
+static inline bool is_indefinite(const cn_cbor *cb)
+{
+  return (cb->flags & CN_CBOR_FL_INDEF) != 0;
+}
+
+static void _write_positive(cn_write_state *ws, cn_cbor_type typ, uint64_t val) {
+  uint8_t ib;
+  assert((size_t)typ < sizeof(_xlate));
+
+  ib = _xlate[typ];
+  if (ib == 0xFF) {
+    ws->offset = -1;
+    return;
+  }
+
+  if (val < 24) {
+    ensure_writable(1);
+    write_byte(ib | val);
+  } else if (val < 256) {
+    ensure_writable(2);
+    write_byte(ib | 24);
+    write_byte((uint8_t)val);
+  } else if (val < 65536) {
+    uint16_t be16 = (uint16_t)val;
+    ensure_writable(3);
+    be16 = hton16p(&be16);
+    write_byte_and_data(ib | 25, (const void*)&be16, 2);
+  } else if (val < 0x100000000L) {
+    uint32_t be32 = (uint32_t)val;
+    ensure_writable(5);
+    be32 = hton32p(&be32);
+    write_byte_and_data(ib | 26, (const void*)&be32, 4);
+  } else {
+    uint64_t be64;
+    ensure_writable(9);
+    be64 = hton64p((const uint8_t*)&val);
+    write_byte_and_data(ib | 27, (const void*)&be64, 8);
+  }
+}
+
+#ifndef CBOR_NO_FLOAT
+static void _write_double(cn_write_state *ws, double val)
+{
+  float float_val = val;
+  
+  /* NOTE - the following code block assures portability across
+            different OSs, it is even necessary when running
+	    different OSs under same toolchain. */
+  if (isnan(val)) {
+      float_val = NAN;
+  } else if (isinf(val) && isgreater(val, 0)) {
+      float_val = INFINITY;
+  } else if (isinf(val) && isless(val, 0)) {
+      float_val = -INFINITY;
+  }
+
+  if (((float_val == val) && !isnan(val)) || (isinf(val) && isinf(float_val))) { /* 32 bits is enough and we aren't NaN or INFINITY */
+    uint32_t be32;
+    uint16_t be16, u16;
+    union {
+      float f;
+      uint32_t u;
+    } u32;
+    u32.f = float_val;
+    if ((u32.u & 0x1FFF) == 0) { /* worth trying half */
+      int s16 = (u32.u >> 16) & 0x8000;
+      int exp = (u32.u >> 23) & 0xff;
+      int mant = u32.u & 0x7fffff;
+      if (exp == 0 && mant == 0)
+        ;              /* 0.0, -0.0 */
+      else if (exp >= 113 && exp <= 142) /* normalized */
+        s16 += ((exp - 112) << 10) + (mant >> 13);
+      else if (exp >= 103 && exp < 113) { /* denorm, exp16 = 0 */
+        if (mant & ((1 << (126 - exp)) - 1))
+          goto float32;         /* loss of precision */
+        s16 += ((mant + 0x800000) >> (126 - exp));
+      } else if (exp == 255 && mant == 0) { /* Inf */
+        s16 += 0x7c00;
+      } else
+        goto float32;           /* loss of range */
+
+      ensure_writable(3);
+      u16 = s16;
+      be16 = hton16p((const uint8_t*)&u16);
+
+      write_byte_and_data(IB_PRIM | 25, (const void*)&be16, 2);
+      return;
+    }
+  float32:
+    ensure_writable(5);
+    be32 = hton32p((const uint8_t*)&u32.u);
+
+    write_byte_and_data(IB_PRIM | 26, (const void*)&be32, 4);
+
+  } else if (isnan(val)) {      /* NaN -- we always write a half NaN*/
+    ensure_writable(3);
+    write_byte_and_data(IB_PRIM | 25, (const void*)"\x7e\x00", 2);
+  } else {
+    uint64_t be64;
+    /* Copy the same problematic implementation from the decoder. */
+    union {
+      double d;
+      uint64_t u;
+    } u64;
+
+    u64.d = val;
+
+    ensure_writable(9);
+    be64 = hton64p((const uint8_t*)&u64.u);
+
+    write_byte_and_data(IB_PRIM | 27, (const void*)&be64, 8);
+
+  }
+}
+#endif /* CBOR_NO_FLOAT */
+
+// TODO: make public?
+typedef void (*cn_visit_func)(const cn_cbor *cb, int depth, void *context);
+static void _visit(const cn_cbor *cb,
+                   cn_visit_func visitor,
+                   cn_visit_func breaker,
+                   void *context)
+{
+    const cn_cbor *p = cb;
+    int depth = 0;
+    while (p)
+    {
+    visit:
+
+      visitor(p, depth, context);
+
+      if (p->first_child) {
+
+        p = p->first_child;
+        depth++;
+      } else{
+
+        // Empty indefinite
+        if (is_indefinite(p)) {
+
+          breaker(p->parent, depth, context);
+        }
+        if (p->next) {
+          p = p->next;
+        } else {
+          while (p->parent) {
+            depth--;
+            if (is_indefinite(p->parent)) {
+              breaker(p->parent, depth, context);
+            }
+            if (p->parent->next) {
+              p = p->parent->next;
+              goto visit;
+            }
+            p = p->parent;
+          }
+          return;
+        }
+      }
+    }
+}
+
+#define CHECK(st) (st); \
+if (ws->offset < 0) {return;}
+
+void _encoder_visitor(const cn_cbor *cb, int depth, void *context)
+{
+  cn_write_state *ws = context;
+  UNUSED_PARAM(depth);
+
+  switch (cb->type) {
+  case CN_CBOR_ARRAY:
+    if (is_indefinite(cb)) {
+      write_byte_ensured(IB_ARRAY | AI_INDEF);
+    } else {
+      CHECK(_write_positive(ws, CN_CBOR_ARRAY, cb->length));
+    }
+    break;
+  case CN_CBOR_MAP:
+    if (is_indefinite(cb)) {
+      write_byte_ensured(IB_MAP | AI_INDEF);
+    } else {
+      CHECK(_write_positive(ws, CN_CBOR_MAP, cb->length/2));
+    }
+    break;
+  case CN_CBOR_BYTES_CHUNKED:
+  case CN_CBOR_TEXT_CHUNKED:
+    write_byte_ensured(_xlate[cb->type] | AI_INDEF);
+    break;
+
+  case CN_CBOR_TEXT:
+  case CN_CBOR_BYTES:
+    CHECK(_write_positive(ws, cb->type, cb->length));
+    ensure_writable(cb->length);
+    if (ws->buf != NULL)
+    {
+	    memcpy(ws->buf + ws->offset, cb->v.str, cb->length);
+    }
+
+    ws->offset += cb->length;
+
+    break;
+
+  case CN_CBOR_FALSE:
+  case CN_CBOR_TRUE:
+  case CN_CBOR_NULL:
+  case CN_CBOR_UNDEF:
+    write_byte_ensured(_xlate[cb->type]);
+    break;
+
+  case CN_CBOR_TAG:
+  case CN_CBOR_UINT:
+  case CN_CBOR_SIMPLE:
+    CHECK(_write_positive(ws, cb->type, cb->v.uint));
+    break;
+
+  case CN_CBOR_INT:
+    assert(cb->v.sint < 0);
+    CHECK(_write_positive(ws, CN_CBOR_INT, ~(cb->v.sint)));
+    break;
+
+  case CN_CBOR_DOUBLE:
+#ifndef CBOR_NO_FLOAT
+    CHECK(_write_double(ws, cb->v.dbl));
+#endif /* CBOR_NO_FLOAT */
+    break;
+
+  case CN_CBOR_INVALID:
+    ws->offset = -1;
+    break;
+  }
+}
+
+void _encoder_breaker(const cn_cbor *cb, int depth, void *context)
+{
+  cn_write_state *ws = context;
+  UNUSED_PARAM(cb);
+  UNUSED_PARAM(depth);
+  write_byte_ensured(IB_BREAK);
+}
+
+/*
+If called with a NULL buf, will run as usual but will not copy any data.
+This is done in order to acquire the size of the buffer we will allocate for the decoded buffer.
+*/
+static int cn_cbor_encoder(uint8_t *buf,
+	size_t buf_offset,
+	size_t buf_size,
+	const cn_cbor *cb)
+{
+	int ret;
+	cn_write_state ws = { buf, buf_offset, buf_size };
+	_visit(cb, _encoder_visitor, _encoder_breaker, &ws);
+	
+	if (ws.offset < 0) { return -1; }
+	ret = ws.offset - buf_offset;
+	return ret;
+}
+
+int cn_cbor_get_encoded_size(const cn_cbor *cb, cn_cbor_errback *err)
+{
+	int ret;
+
+	if (cb == NULL) {
+		err->err = CN_CBOR_ERR_INVALID_PARAMETER;
+		return -1;
+	}
+
+	ret = cn_cbor_encoder(NULL, 0, INT_MAX, cb);
+	if (ret <= 0) {
+		err->err = CN_CBOR_ERR_ENCODER;
+		return -1;
+	}
+
+	err->err = CN_CBOR_NO_ERROR;
+	return ret;
+}
+
+int cn_cbor_encoder_write(const cn_cbor *cb, uint8_t *bufOut, int bufSize, cn_cbor_errback *err)
+{
+	int bytesWritten;
+	
+	if (bufOut == NULL) {
+		err->err = CN_CBOR_ERR_INVALID_PARAMETER;
+		return -1;
+	}
+	
+	bytesWritten = cn_cbor_encoder(bufOut, 0, bufSize, cb);
+	if (bytesWritten <= 0)
+	{
+		err->err = CN_CBOR_ERR_ENCODER;
+	}
+	else
+	{
+		err->err = CN_CBOR_NO_ERROR;
+
+	}
+
+	return bytesWritten;
+}
+
+int cn_cbor_get_encoded_container_size(const cn_cbor *cb_container) 
+{
+    int ret;
+    cn_cbor_errback err;
+    cn_cbor *sibling_backup = cb_container->next;
+    cn_cbor *parent_backup = cb_container->parent;
+
+    // Make sure the CBOR is a container
+    if (cb_container->type != CN_CBOR_MAP &&
+        cb_container->type != CN_CBOR_ARRAY) {
+        return -1;
+    }
+
+    // Disconnect parent sibling temporarily. We first cast to size_t to avoid compiler const warnings
+    ((cn_cbor*)(size_t)cb_container)->next = NULL;
+    ((cn_cbor*)(size_t)cb_container)->parent = NULL;
+
+    ret = cn_cbor_get_encoded_size(cb_container, &err);
+
+    // Restore sibling
+    ((cn_cbor*)(size_t)cb_container)->next = sibling_backup;
+    ((cn_cbor*)(size_t)cb_container)->parent = parent_backup;
+
+    return ret;
+}
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif  /* CN_CBOR_C */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/source/cn-error.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,14 @@
+const char *cn_cbor_error_str[] = {
+ "CN_CBOR_NO_ERROR",
+ "CN_CBOR_ERR_OUT_OF_DATA",
+ "CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED",
+ "CN_CBOR_ERR_ODD_SIZE_INDEF_MAP",
+ "CN_CBOR_ERR_BREAK_OUTSIDE_INDEF",
+ "CN_CBOR_ERR_MT_UNDEF_FOR_INDEF",
+ "CN_CBOR_ERR_RESERVED_AI",
+ "CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING",
+ "CN_CBOR_ERR_INVALID_PARAMETER",
+ "CN_CBOR_ERR_OUT_OF_MEMORY",
+ "CN_CBOR_ERR_FLOAT_NOT_SUPPORTED",
+ "CN_CBOR_ERR_ENCODER"
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/secsrv-cbor/source/cn-get.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,63 @@
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "cn-cbor.h"
+
+cn_cbor* cn_cbor_mapget_int(const cn_cbor* cb, int key) {
+  cn_cbor* cp;
+  assert(cb);
+  for (cp = cb->first_child; cp && cp->next; cp = cp->next->next) {
+    switch(cp->type) {
+    case CN_CBOR_UINT:
+      if (cp->v.uint == (unsigned long)key) {
+        return cp->next;
+      }
+      break;
+    case CN_CBOR_INT:
+      if (cp->v.sint == (long)key) {
+        return cp->next;
+      }
+      break;
+    default:
+      ; // skip non-integer keys
+    }
+  }
+  return NULL;
+}
+
+cn_cbor* cn_cbor_mapget_string(const cn_cbor* cb, const char* key) {
+  cn_cbor *cp;
+  int keylen;
+  assert(cb);
+  assert(key);
+  keylen = strlen(key);
+  for (cp = cb->first_child; cp && cp->next; cp = cp->next->next) {
+    switch(cp->type) {
+    case CN_CBOR_TEXT: // fall-through
+    case CN_CBOR_BYTES:
+      if (keylen != cp->length) {
+        continue;
+      }
+      if (memcmp(key, cp->v.str, keylen) == 0) {
+        return cp->next;
+      }
+    default:
+      ; // skip non-string keys
+    }
+  }
+  return NULL;
+}
+
+cn_cbor* cn_cbor_index(const cn_cbor* cb, unsigned int idx) {
+  cn_cbor *cp;
+  unsigned int i = 0;
+  assert(cb);
+  for (cp = cb->first_child; cp; cp = cp->next) {
+    if (i == idx) {
+      return cp;
+    }
+    i++;
+  }
+  return NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/storage/source/storage.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,522 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include <stdbool.h>
+#include "pv_error_handling.h"
+#include "storage.h"
+#include "esfs.h"
+
+static kcm_status_e error_handler(esfs_result_e esfs_status)
+{
+    switch (esfs_status) {
+        case ESFS_SUCCESS:
+            return KCM_STATUS_SUCCESS;
+        case ESFS_INVALID_PARAMETER:
+            return KCM_STATUS_INVALID_PARAMETER;
+        case ESFS_BUFFER_TOO_SMALL:
+            return KCM_STATUS_INSUFFICIENT_BUFFER;
+        case ESFS_EXISTS:
+            return KCM_STATUS_FILE_EXIST;
+        case ESFS_NOT_EXISTS:
+            return KCM_STATUS_ITEM_NOT_FOUND;
+        case ESFS_INVALID_FILE_VERSION:
+            return KCM_STATUS_INVALID_FILE_VERSION;
+        case ESFS_CMAC_DOES_NOT_MATCH:
+            return KCM_STATUS_FILE_CORRUPTED;
+        case ESFS_ERROR:
+            return KCM_STATUS_STORAGE_ERROR;
+        case ESFS_HASH_CONFLICT:
+            return KCM_STATUS_FILE_NAME_CORRUPTED;
+        case ESFS_FILE_OPEN_FOR_READ:
+        case ESFS_FILE_OPEN_FOR_WRITE:
+            return KCM_STATUS_INVALID_FILE_ACCESS_MODE;
+        default:
+            return  KCM_STATUS_UNKNOWN_STORAGE_ERROR;
+    }
+}
+
+
+static bool is_file_accessible(const kcm_ctx_s *ctx)
+{
+    // FIXME - We need to check file access availability by comparing KCM context TLVs vs the target file header stored in ESFS that contains
+    //         TLVs and access rights. In order to retrieve ESFS file TLVs and access rights we should use the following methods
+    //         that are currently not implemented:
+    //              - esfs_get_meta_data_qty
+    //              - esfs_get_meta_data_types
+    //              - esfs_get_meta_data_buffer_size
+    //              - esfs_read_meta_data
+    //              - esfs_get_meta_data_qty
+
+    ctx = ctx;                 // currently unused
+
+    return true;
+}
+
+kcm_status_e storage_init()
+{
+    esfs_result_e esfs_status;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    esfs_status = esfs_init();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed initializing ESFS (esfs_status %d)", esfs_status);
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return KCM_STATUS_SUCCESS;
+}
+
+kcm_status_e storage_finalize()
+{
+    esfs_result_e esfs_status;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    esfs_status = esfs_finalize();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed finalizing ESFS (esfs_status %d)", esfs_status);
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return KCM_STATUS_SUCCESS;
+}
+
+kcm_status_e storage_reset()
+{
+    esfs_result_e esfs_status;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    esfs_status = esfs_reset();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed reset ESFS (esfs_status %d)", esfs_status);
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return KCM_STATUS_SUCCESS;
+}
+
+
+kcm_status_e storage_factory_reset()
+{
+    esfs_result_e esfs_status;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    esfs_status = esfs_factory_reset();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed factory reset ESFS (esfs_status %d)", esfs_status);
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return KCM_STATUS_SUCCESS;
+}
+
+kcm_status_e storage_file_write(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, const uint8_t *data, size_t data_length, const kcm_meta_data_list_s *kcm_meta_data_list, bool is_factory, bool is_encrypted)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    kcm_status_e close_file_status = KCM_STATUS_SUCCESS;
+
+    kcm_status = storage_file_create(ctx, file_name, file_name_length, kcm_meta_data_list, is_factory, is_encrypted);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(kcm_status != KCM_STATUS_SUCCESS, kcm_status, "Failed to create new file");
+
+    kcm_status = storage_file_write_with_ctx(ctx, data, data_length);// we don't check error because we need to close the file in any case
+
+    // Data is only guaranteed to be flushed to the media on efs_close.
+    close_file_status = storage_file_close(ctx);
+
+    if (kcm_status != KCM_STATUS_SUCCESS) { // delete the file if didn't succeed to write
+        (void)storage_file_delete(ctx, file_name, file_name_length);
+        SA_PV_ERR_RECOVERABLE_RETURN(kcm_status, "Failed to write data");
+    }
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(close_file_status != KCM_STATUS_SUCCESS, close_file_status, "Failed to close file");
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+}
+
+kcm_status_e storage_file_size_get(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, size_t *file_size_out)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    kcm_status_e close_staus = KCM_STATUS_SUCCESS;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER("file_name_length=%" PRIu32 "", (uint32_t)file_name_length);
+
+    kcm_status = storage_file_open(ctx, file_name, file_name_length);
+    if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
+        goto exit;
+    }
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to open the given file");
+
+    kcm_status = storage_file_size_get_with_ctx(ctx, file_size_out);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Failed getting file size");
+
+exit:
+    if (kcm_status != KCM_STATUS_ITEM_NOT_FOUND) {
+        close_staus = storage_file_close(ctx);
+    }
+    if (kcm_status == KCM_STATUS_SUCCESS) {
+        kcm_status = close_staus;
+    }
+
+    return kcm_status;
+}
+
+kcm_status_e storage_file_read(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, uint8_t *buffer_out, size_t buffer_size, size_t *buffer_actual_size_out)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    kcm_status_e close_status = KCM_STATUS_SUCCESS;
+
+    kcm_status = storage_file_open(ctx, file_name, file_name_length);
+    if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
+        goto exit;
+    }
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed to open the given file");
+
+    kcm_status = storage_file_read_with_ctx(ctx, buffer_out, buffer_size, buffer_actual_size_out);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, exit, "Failed ti read file");
+
+exit:
+    if (kcm_status != KCM_STATUS_ITEM_NOT_FOUND) {
+        close_status = storage_file_close(ctx);
+    }
+    if (kcm_status == KCM_STATUS_SUCCESS) {
+        kcm_status = close_status;
+    }
+
+    return kcm_status;
+}
+
+kcm_status_e storage_file_delete(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    esfs_result_e esfs_status;
+    uint16_t esfs_mode = 0;        // FIXME - Unused, yet implemented
+    bool success;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER("file_name_length=%" PRIu32 "", (uint32_t)file_name_length);
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid file name context");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name_length == 0), KCM_STATUS_INVALID_PARAMETER, "Got empty file name");
+
+    esfs_status = esfs_open(file_name, file_name_length, &esfs_mode, &ctx->esfs_file_h);
+
+    //file does not exists, exit from delete function
+    if (esfs_status == ESFS_NOT_EXISTS) {
+        return error_handler(esfs_status);
+    }
+
+    if (esfs_status != ESFS_SUCCESS) { //file exists but there is some corruption. We will delete the file without checking it's permissions
+        SA_PV_LOG_ERR("The file exists but corrupted. Delete it without checking permissions");
+        esfs_status = ESFS_SUCCESS;
+
+    } else { // check permissions
+        success = is_file_accessible(ctx);
+        if (!success) {
+            SA_PV_LOG_ERR("Caller has no access rights to the given file");
+            kcm_status = KCM_STATUS_NOT_PERMITTED;
+        }
+
+        esfs_status = esfs_close(&ctx->esfs_file_h);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed closing file (esfs_status %d)", esfs_status);
+
+        if (kcm_status == KCM_STATUS_NOT_PERMITTED) {
+            return kcm_status;
+        }
+    }
+
+    // Delete the file
+    esfs_status = esfs_delete(file_name, file_name_length);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed deleting file (esfs_status %d)", esfs_status);
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+}
+
+
+kcm_status_e storage_file_create(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, const kcm_meta_data_list_s *kcm_meta_data_list, bool is_factory, bool is_encrypted)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    esfs_result_e esfs_status;
+    esfs_tlv_item_t meta_data_items[KCM_MD_TYPE_MAX_SIZE];
+    size_t meta_data_count = 0;
+    uint16_t access_flags = 0; // owner, signed, encrypted, factory, extended ACL bit mask
+
+    SA_PV_LOG_TRACE_FUNC_ENTER("file_name_length=%" PRIu32 " ", (uint32_t)file_name_length);
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid file name context");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name_length == 0), KCM_STATUS_INVALID_PARAMETER, "Got empty file name");
+
+    memset(ctx, 0, sizeof(kcm_ctx_s));
+
+    if (is_factory) {
+        access_flags |= ESFS_FACTORY_VAL;
+    }
+    if (is_encrypted) {
+        access_flags |= ESFS_ENCRYPTED;
+    }
+
+    // Convert kcm_meta_data_list to array of esfs_tlv_item
+    if (kcm_meta_data_list != NULL) {
+        for (meta_data_count = 0; meta_data_count < kcm_meta_data_list->meta_data_count; meta_data_count++) {
+            meta_data_items[meta_data_count].type = kcm_meta_data_list->meta_data[meta_data_count].type;
+            meta_data_items[meta_data_count].length_in_bytes = (uint16_t)kcm_meta_data_list->meta_data[meta_data_count].data_size;
+            meta_data_items[meta_data_count].value = (void*)kcm_meta_data_list->meta_data[meta_data_count].data;
+        }
+    }
+
+    esfs_status = esfs_create(file_name, file_name_length, meta_data_items, meta_data_count, access_flags, &ctx->esfs_file_h);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((esfs_status == ESFS_EXISTS), kcm_status = KCM_STATUS_FILE_EXIST, Exit, "File already exist in ESFS (esfs_status %" PRIu32 ")", (uint32_t)esfs_status);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((esfs_status != ESFS_SUCCESS), kcm_status = error_handler(esfs_status), Exit, "Failed creating file (esfs_status %" PRIu32 ")", (uint32_t)esfs_status);
+
+Exit:
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        memset(ctx, 0, sizeof(kcm_ctx_s));
+    }
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+}
+
+/** Open existing file
+*
+*   @param ctx KCM operation context.
+*   @param file_name A binary blob that uniquely identifies the file
+*   @param file_name_length The binary blob length in bytes.
+@param is_factory True if KCM item is factory item, or false otherwise
+@param is_encrypted True if KCM item should be encrypted, or false otherwise
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_open(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length)
+{
+
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    esfs_result_e esfs_status;
+    uint16_t esfs_mode = 0;        // FIXME - Unused, yet implemented
+    bool success;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER("file_name_length=%" PRIu32 "", (uint32_t)file_name_length);
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid file name context");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((file_name_length == 0), KCM_STATUS_INVALID_PARAMETER, "Got empty file name");
+
+    memset(ctx, 0, sizeof(kcm_ctx_s));
+
+    esfs_status = esfs_open(file_name, file_name_length, &esfs_mode, &ctx->esfs_file_h);
+    if (esfs_status == ESFS_NOT_EXISTS) {
+        kcm_status = error_handler(esfs_status);
+        goto Exit;
+    }
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((esfs_status != ESFS_SUCCESS), kcm_status = error_handler(esfs_status), Exit, "Failed opening file (esfs_status %d)", esfs_status);
+
+    success = is_file_accessible(ctx);
+    if (!success) {
+        kcm_status = KCM_STATUS_NOT_PERMITTED;
+        esfs_close(&ctx->esfs_file_h);
+        memset(ctx, 0, sizeof(kcm_ctx_s));
+    }
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status = kcm_status, Exit, "Caller has no access rights to the given file");
+
+Exit:
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        memset(ctx, 0, sizeof(kcm_ctx_s));
+    }
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+}
+
+/** Close file in storage
+*
+*   @param ctx KCM operation context.
+@param is_factory True if KCM item is factory item, or false otherwise
+@param is_encrypted True if KCM item should be encrypted, or false otherwise
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_close(kcm_ctx_s *ctx)
+{
+    esfs_result_e esfs_status;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
+
+    // Data is only guaranteed to be flushed to the media on efs_close.
+    esfs_status = esfs_close(&ctx->esfs_file_h);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed closing file (esfs_status %d)", esfs_status);
+
+    memset(ctx, 0, sizeof(kcm_ctx_s));
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return KCM_STATUS_SUCCESS;
+}
+
+
+kcm_status_e storage_file_write_with_ctx(kcm_ctx_s *ctx, const uint8_t *data, size_t data_length)
+{
+    esfs_result_e esfs_status;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER("data_length=%" PRIu32 "", (uint32_t)data_length);
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(((data == NULL) && (data_length > 0)), KCM_STATUS_INVALID_PARAMETER, "Provided NULL data buffer and data_length greater than 0");
+
+    if (data_length != 0) {
+        esfs_status = esfs_write(&ctx->esfs_file_h, data, data_length);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed writing (%" PRIu32 " B) size to file (esfs_status %" PRIu32 ")", (uint32_t)data_length, (uint32_t)esfs_status);
+    }
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return KCM_STATUS_SUCCESS;
+
+}
+
+kcm_status_e storage_file_size_get_with_ctx(kcm_ctx_s *ctx, size_t *file_size_out)
+{
+    esfs_result_e esfs_status;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((file_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to file size");
+
+    esfs_status = esfs_file_size(&ctx->esfs_file_h, file_size_out);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed getting file size (esfs_status %d)", esfs_status);
+
+    ctx->is_file_size_checked = true;
+    ctx->file_size = *file_size_out;
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return KCM_STATUS_SUCCESS;
+}
+
+
+kcm_status_e storage_file_read_with_ctx(kcm_ctx_s *ctx, uint8_t *buffer_out, size_t buffer_size, size_t *buffer_actual_size_out)
+{
+    esfs_result_e esfs_status;
+    kcm_status_e kcm_status;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER("buffer_size=%" PRIu32 "", (uint32_t)buffer_size);
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((buffer_out == NULL && buffer_size != 0), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to read buffer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((buffer_actual_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to output size");
+
+    *buffer_actual_size_out = 0;
+
+    if (ctx->is_file_size_checked == false) {
+        kcm_status = storage_file_size_get_with_ctx(ctx, buffer_actual_size_out);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed getting file data size (kcm_status %d)", kcm_status);
+    }
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((buffer_size < ctx->file_size), KCM_STATUS_INSUFFICIENT_BUFFER, "Buffer too small");
+
+    if (ctx->file_size != 0) {
+        esfs_status = esfs_read(&ctx->esfs_file_h, buffer_out, buffer_size, buffer_actual_size_out);
+        SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed reading file data (esfs_status %d)", esfs_status);
+    }
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return KCM_STATUS_SUCCESS;
+}
+
+static kcm_status_e storage_file_get_meta_data_size_and_index(kcm_ctx_s *ctx, kcm_meta_data_type_e type, size_t *meta_data_size_out, uint32_t *meta_data_index_out)
+{
+    esfs_result_e esfs_status;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    esfs_tlv_properties_t *meta_data_properties = NULL;
+    uint32_t index = 0;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((ctx == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid context");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((meta_data_size_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to meta_data_size_out");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((meta_data_index_out == NULL), KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to meta_data_index_out");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((type >= KCM_MD_TYPE_MAX_SIZE), KCM_STATUS_INVALID_PARAMETER, "Invalid meta data type");
+
+    esfs_status = esfs_get_meta_data_properties(&ctx->esfs_file_h, &meta_data_properties);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed reading meta data properties (esfs_status %d)", esfs_status);
+
+    for (index = 0; index < meta_data_properties->number_of_items; index++) {
+        if (type == meta_data_properties->tlv_items[index].type) {
+
+            *meta_data_size_out = (size_t)meta_data_properties->tlv_items[index].length_in_bytes;
+            *meta_data_index_out = index;
+            kcm_status = KCM_STATUS_SUCCESS;
+            break;
+        }
+    }
+
+    if (index >= meta_data_properties->number_of_items) {
+        return KCM_STATUS_META_DATA_NOT_FOUND;
+    }
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return kcm_status;
+}
+
+kcm_status_e storage_file_get_meta_data_size(kcm_ctx_s *ctx, kcm_meta_data_type_e type, size_t *meta_data_size_out)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    uint32_t index = 0;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    kcm_status = storage_file_get_meta_data_size_and_index(ctx, type, meta_data_size_out, &index);
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return kcm_status;
+}
+
+kcm_status_e storage_file_read_meta_data_by_type(kcm_ctx_s *ctx, kcm_meta_data_type_e type, uint8_t *buffer_out, size_t buffer_size, size_t *buffer_actual_size_out)
+{
+    esfs_result_e esfs_status;
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    esfs_tlv_item_t meta_data_item;
+    uint32_t index = 0;
+
+    SA_PV_LOG_TRACE_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF(buffer_out == NULL, KCM_STATUS_INVALID_PARAMETER, "Invalid pointer to kcm_meta_data");
+
+    kcm_status = storage_file_get_meta_data_size_and_index(ctx, type, buffer_actual_size_out, &index);
+    if (kcm_status == KCM_STATUS_META_DATA_NOT_FOUND) {
+        return kcm_status;
+    }
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), kcm_status, "Failed reading meta data size and index");
+
+    // return error in case the data buffer to read is too small
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((buffer_size < *buffer_actual_size_out), KCM_STATUS_INSUFFICIENT_BUFFER, "Data buffer to read is too small");
+
+    meta_data_item.value = buffer_out;
+    esfs_status = esfs_read_meta_data(&ctx->esfs_file_h, index, &meta_data_item);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((esfs_status != ESFS_SUCCESS), error_handler(esfs_status), "Failed reading meta data (esfs_status %d)", esfs_status);
+
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+
+    return kcm_status;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/storage/storage/storage.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,228 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __STORAGE_H__
+#define __STORAGE_H__
+
+#include <inttypes.h>
+#include "key_config_manager.h"
+#include "kcm_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// FIXME: change to esfs define when a new esfs release is out with ESFS_MAX_NAME_LENGTH defined in esfs.h
+/*
+* #include "esfs.h"
+* #define STORAGE_FILENAME_MAX_SIZE ESFS_MAX_NAME_LENGTH
+*/
+
+#define STORAGE_FILENAME_MAX_SIZE 1024
+
+#if ((STORAGE_FILENAME_MAX_SIZE - KCM_FILE_PREFIX_MAX_SIZE) != KCM_MAX_FILENAME_SIZE)
+#error "ESFS_MAX_NAME_LENGTH must be equal to KCM_FILE_PREFIX_MAX_SIZE + KCM_MAX_FILENAME_SIZE. Perhaps there was a change in one of the defines."
+#endif
+
+
+/* === Initialization and Finalization === */
+
+/** Initializes storage so that it can be used.
+*   Must be called once after boot.
+*   Existing data in storage would not compromised.
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_init(void);
+
+
+/** Finalize storage.
+*   Must be called once to close all storage resources.
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_finalize(void);
+
+/** Resets storage to an empty state.
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_reset(void);
+
+
+/** Resets storage to a factory state.
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_factory_reset(void);
+
+
+/* === File Operations === */
+
+/** Create a new file
+*
+*   @param KCM operation context.
+*   @param file_name A binary blob that uniquely identifies the file
+*   @param file_name_length The binary blob length in bytes.
+*   @param meta_data_list A pointer to structure with single meta data for each type
+*   @param is_factory A factory flag.
+*   @param is_encrypted Encryption flag
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_create(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, const kcm_meta_data_list_s *kcm_meta_data_list, bool is_factory, bool is_encrypted);
+
+/** Open existing file
+*
+*   @param KCM operation context.
+*   @param file_name A binary blob that uniquely identifies the file
+*   @param file_name_length The binary blob length in bytes.
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_open(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length);
+
+/** Close file in storage
+*
+*   @param ctx KCM operation context.
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_close(kcm_ctx_s *ctx);
+
+/** Write data to previously opened file in storage
+*
+*   @param ctx KCM operation context.
+*   @param data A pointer to memory with the data to write into the newly created file. Can be NULL if data_length is 0.
+*   @param data_length The data length in bytes. Can be 0 if we wish to write an empty file.
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_write_with_ctx(kcm_ctx_s *ctx, const uint8_t *data, size_t data_length);
+
+
+/** Writes a new file to storage
+*
+*   @param ctx KCM operation context.
+*   @param file_name A binary blob that uniquely identifies the file
+*   @param file_name_length The binary blob length in bytes.
+*   @param data A pointer to memory with the data to write into the newly created file. Can be NULL if data_length is 0.
+*   @param data_length The data length in bytes. Can be 0 if we wish to write an empty file.
+*   @param meta_data_list A pointer to structure with single meta data for each type
+*   @param is_factory True if KCM item is factory item, or false otherwise
+*   @param is_encrypted True if KCM item should be encrypted, or false otherwise
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_write(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, const uint8_t *data, size_t data_length, const kcm_meta_data_list_s *kcm_meta_data_list, bool is_factory, bool is_encrypted);
+
+
+/** Returns the size of the data in a file
+*
+*   @param ctx KCM operation context.
+*   @param file_name A binary blob that uniquely identifies the file
+*   @param file_name_length The binary blob length in bytes
+*   @param file_size_out A pointer to hold the size of the data in the file
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_size_get(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, size_t *file_size_out);
+
+/** Reads data from a file.
+*
+*   @param ctx KCM operation context.
+*   @param file_name A binary blob that uniquely identifies the file
+*   @param file_name_length The binary blob length in bytes
+*   @param buffer_out A pointer to memory buffer where the data will be read from the file. Can be NULL if buffer_size is 0.
+*   @param buffer_size The number of bytes to be read. Buffer must be big enough to contain this size. Can be 0 if we wish to read an empty file.
+*   @param buffer_actual_size_out The effective bytes size read from the file.
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_read(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length, uint8_t *buffer_out, size_t buffer_size, size_t *buffer_actual_size_out);
+
+/** Returns the size of the data in a file. The file should be opened by storage_file_open()
+*
+*   @param ctx KCM operation context.
+*   @param file_size_out A pointer to hold the size of the data in the file
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_size_get_with_ctx(kcm_ctx_s *ctx, size_t *file_size_out);
+
+/** Reads data from a file. The file should be opened by storage_file_open().
+*
+*   @param ctx KCM operation context.
+*   @param buffer_out A pointer to memory buffer where the data will be read from the file. Can be NULL if buffer_size is 0.
+*   @param buffer_size The number of bytes to be read. Buffer must be big enough to contain this size. Can be 0 if we wish to read an empty file.
+*   @param buffer_actual_size_out The effective bytes size read from the file.
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_read_with_ctx(kcm_ctx_s *ctx, uint8_t *buffer_out, size_t buffer_size, size_t *buffer_actual_size_out);
+/** Deletes the file from storage
+*
+*   @param ctx KCM operation context.
+*   @param file_name A binary blob that uniquely identifies the file
+*   @param file_name_length The binary blob length in bytes
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_delete(kcm_ctx_s *ctx, const uint8_t *file_name, size_t file_name_length);
+
+/** Get the size of the stored meta data type. The file should be opened by storage_file_open().
+*
+*   @param ctx KCM operation context.
+*   @param type the meta data type to get size for.
+*   @param metadata_size_out A pointer to hold the size of the meta data
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_get_meta_data_size(kcm_ctx_s *ctx, kcm_meta_data_type_e type, size_t *meta_data_size_out);
+
+/** Reads meta data into a kcm_meta_data
+*
+*   @param ctx KCM operation context.
+*   @param type the meta data type to get size for.
+*   @param buffer_out A pointer to memory buffer where the meta data will be read to.
+*   @param buffer_size The number of bytes to be read. Buffer must be big enough to contain this size.
+*   @param buffer_actual_size_out The effective bytes size read from the file.
+*
+*   @returns
+*       KCM_STATUS_SUCCESS in case of success otherwise one of kcm_status_e errors
+*/
+kcm_status_e storage_file_read_meta_data_by_type(kcm_ctx_s *ctx, kcm_meta_data_type_e type, uint8_t *buffer_out, size_t buffer_size, size_t *buffer_actual_size_out);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__STORAGE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/source/common_utils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,149 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "factory_configurator_client.h"
+#include "fcc_status.h"
+#include "fcc_verification.h"
+#include "key_config_manager.h"
+#include "pv_error_handling.h"
+#include "cs_der_certs.h"
+#include "cs_utils.h"
+#include "fcc_output_info_handler.h"
+#include "fcc_malloc.h"
+#include "time.h"
+#include "cs_utils.h"
+#include "fcc_sotp.h"
+
+
+fcc_status_e fcc_get_kcm_data(const uint8_t *parameter_name, size_t size_of_parameter_name, kcm_item_type_e kcm_type, uint8_t **kcm_data, size_t *kcm_data_size)
+{
+
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((parameter_name == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Wrong parameter_name pointer");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((size_of_parameter_name == 0), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Wrong parameter_name size.");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((*kcm_data != NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Wrong *kcm_data pointer, should be NULL");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_data_size == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Wrong kcm_data_size pointer.");
+
+    //Get size of kcm data
+    kcm_status = kcm_item_get_data_size(parameter_name,
+        size_of_parameter_name,
+        kcm_type,
+        kcm_data_size);
+    if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
+        return FCC_STATUS_ITEM_NOT_EXIST;
+    }
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_KCM_STORAGE_ERROR, "Failed to get kcm data size");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((*kcm_data_size == 0), fcc_status = FCC_STATUS_EMPTY_ITEM, "KCM item is empty");
+
+    //Alocate memory and get device certificate data
+    *kcm_data = fcc_malloc(*kcm_data_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((*kcm_data == NULL), fcc_status = FCC_STATUS_MEMORY_OUT, "Failed to allocate buffer for kcm data");
+
+    kcm_status = kcm_item_get_data(parameter_name,
+        size_of_parameter_name,
+        kcm_type,
+        *kcm_data, *kcm_data_size, kcm_data_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status == KCM_STATUS_ITEM_NOT_FOUND), fcc_status = FCC_STATUS_ITEM_NOT_EXIST, exit, "KCM is not found");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_KCM_STORAGE_ERROR, exit, "Failed to get device certificate data");
+
+exit:
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        fcc_free(*kcm_data);
+        *kcm_data = NULL;
+    }
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+fcc_status_e fcc_get_certificate_attribute(palX509Handle_t x509_cert, cs_certificate_attribute_type_e attribute_type, uint8_t **attribute_data, size_t *attribute_act_data_size)
+{
+
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((x509_cert == NULLPTR), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Wrong x509 handle.");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((*attribute_data != NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, "Wrong attribute_data pointer.");
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((attribute_act_data_size == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, "attribute_act_data_size pointer is NULL.");
+
+    //Get attribute size
+    kcm_status = cs_attr_get_data_size_x509_cert(x509_cert, attribute_type, attribute_act_data_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_INVALID_CERT_ATTRIBUTE, "Failed to get size of attribute");
+
+    *attribute_data = fcc_malloc(*attribute_act_data_size);
+    SA_PV_ERR_RECOVERABLE_RETURN_IF((*attribute_data == NULL), fcc_status = FCC_STATUS_MEMORY_OUT, "Failed to allocate memory for attribute");
+
+    //Get data of "CN" attribute
+    kcm_status = cs_attr_get_data_x509_cert(x509_cert,
+        attribute_type,
+        *attribute_data,
+        *attribute_act_data_size,
+        attribute_act_data_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS || *attribute_act_data_size == 0), fcc_status = FCC_STATUS_INVALID_CERT_ATTRIBUTE, exit, "Failed to get attribute data");
+
+
+exit:
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        fcc_free(*attribute_data);
+        *attribute_data = NULL;
+    }
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
+
+fcc_status_e fcc_get_certificate_attribute_by_name(const uint8_t *cert_name, size_t size_of_cert_name, cs_certificate_attribute_type_e attribute_type, uint8_t *attribute_data,size_t attribute_data_size, size_t *attribute_act_data_size)
+{
+    kcm_status_e kcm_status = KCM_STATUS_SUCCESS;
+    fcc_status_e fcc_status = FCC_STATUS_SUCCESS;
+    uint8_t *kcm_data = NULL;
+    size_t kcm_data_size = 0;
+    palX509Handle_t x509_cert = NULLPTR;
+
+    SA_PV_LOG_INFO_FUNC_ENTER_NO_ARGS();
+
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((cert_name == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Wrong cert name");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((size_of_cert_name == 0), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Wrong cert name size");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((attribute_data == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Wrong attribute data buffer pointer");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((attribute_data_size == 0), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Wrong attribute data buffer size");
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((attribute_act_data_size == NULL), fcc_status = FCC_STATUS_INVALID_PARAMETER, exit, "Wrong attribute_act_data_size pointer");
+
+    //For now we save ca id only for bootstrap server
+    fcc_status = fcc_get_kcm_data((const uint8_t*)cert_name, size_of_cert_name, KCM_CERTIFICATE_ITEM, &kcm_data, &kcm_data_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((fcc_status != FCC_STATUS_SUCCESS), fcc_status = fcc_status, exit, "Failed to read cert data");
+
+    //Create device certificate handle
+    kcm_status = cs_create_handle_from_der_x509_cert(kcm_data, kcm_data_size, &x509_cert);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_INVALID_CERTIFICATE, exit, "Failed to get device certificate descriptor");
+
+    //Get certificate attribute data
+    kcm_status = cs_attr_get_data_x509_cert(x509_cert,
+        attribute_type,
+        attribute_data,
+        attribute_data_size,
+        attribute_act_data_size);
+    SA_PV_ERR_RECOVERABLE_GOTO_IF((kcm_status != KCM_STATUS_SUCCESS), fcc_status = FCC_STATUS_INVALID_CERT_ATTRIBUTE, exit, "Failed to get attribute data");
+
+
+exit:
+    fcc_free(kcm_data);
+    cs_close_handle_x509_cert(&x509_cert);
+    SA_PV_LOG_TRACE_FUNC_EXIT_NO_ARGS();
+    return fcc_status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/source/fcc_stats.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,89 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifdef FCC_MEM_STATS_ENABLED
+
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include "fcc_malloc.h"
+#include "pv_log.h"
+
+typedef struct {
+    uint32_t current_size;      /* Bytes allocated currently */
+    uint32_t total_size;        /* Cumulative sum of bytes ever allocated. */
+    uint32_t max_peak_size;     /* Max peak allocated at a certain time (e.g.: getting worst case memory usage) */
+    uint32_t alloc_cnt;         /* Current number of allocations. */
+    uint32_t free_cnt;          /* Current number of frees. */
+    uint32_t alloc_fail_cnt;    /* Number of failed allocations. */
+} stats_heap_t;
+
+/* Size must be a multiple of 8 to keep alignment */
+typedef struct {
+    uint32_t size;
+    uint32_t pad;
+} alloc_info_t;
+
+static stats_heap_t g_fcc_heap_stats = { 0, 0, 0, 0, 0, 0 };
+
+void *fcc_malloc(size_t size)
+{
+    void *ptr = NULL;
+    alloc_info_t *alloc_info = (alloc_info_t *)malloc(sizeof(alloc_info_t) + size);
+
+    if (alloc_info != NULL) {
+        alloc_info->size = size;
+        ptr = (void *)(alloc_info + 1);
+
+        g_fcc_heap_stats.current_size += size;
+        g_fcc_heap_stats.total_size += size;
+        g_fcc_heap_stats.alloc_cnt += 1;
+
+        if (g_fcc_heap_stats.current_size > g_fcc_heap_stats.max_peak_size) {
+            g_fcc_heap_stats.max_peak_size = g_fcc_heap_stats.current_size;
+        }
+    } else {
+        g_fcc_heap_stats.alloc_fail_cnt += 1;
+    }
+
+    return ptr;
+}
+
+void fcc_free(void *ptr)
+{
+    alloc_info_t *alloc_info = NULL;
+
+    if (ptr != NULL) {
+        alloc_info = ((alloc_info_t *)ptr) - 1;
+        g_fcc_heap_stats.current_size -= alloc_info->size;
+        g_fcc_heap_stats.free_cnt += 1;
+        free(alloc_info);
+    }
+}
+
+void fcc_stats_print_summary(void)
+{
+    // Use printf since this is printed after mbed trace has been destroyed.
+    printf("  ********* FCC Heap Statistics *********\n");
+    printf("  * Total bytes allocated:           %" PRIu32 "\n", g_fcc_heap_stats.total_size);
+    printf("  * Max peak ever allocated:         %" PRIu32 "\n", g_fcc_heap_stats.max_peak_size);
+    printf("  * Number of allocation succeeded:  %" PRIu32 "\n", g_fcc_heap_stats.alloc_cnt);
+    printf("  * Number of frees succeeded:       %" PRIu32 "\n", g_fcc_heap_stats.free_cnt);
+    printf("  * Number of allocation failed:     %" PRIu32 "\n", g_fcc_heap_stats.alloc_fail_cnt);
+    printf("  ***************************************\n");
+}
+
+#endif //FCC_MEM_STATS_ENABLED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/source/fcc_time_profiling.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,29 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+
+#include "fcc_time_profiling.h"
+
+#ifdef FCC_TIME_PROFILING
+
+uint64_t fcc_gen_timer = 0;
+uint64_t fcc_bundle_timer = 0;
+uint64_t fcc_key_timer = 0;
+uint64_t fcc_certificate_timer = 0;
+uint64_t fcc_config_param_timer = 0;
+uint64_t fcc_certificate_chain_timer = 0;
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/source/general_utils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,23 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#include <stdbool.h>
+#include <string.h>
+
+bool is_memory_equal(const void *buf1, size_t size_of_buf1, const void *buf2, size_t size_of_buf2)
+{
+    return ((size_of_buf1 == size_of_buf2) && !memcmp(buf1, buf2, size_of_buf1));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/source/pv_error_handling.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,32 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+
+#include "stdbool.h"
+#include "pv_error_handling.h"
+
+static bool g_pv_is_error_occured = false;
+
+void pv_error_occured(void)
+{
+    g_pv_is_error_occured = true;
+}
+
+bool pv_error_is_error_occured(void)
+{
+    return g_pv_is_error_occured;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/common_utils.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,89 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __COMMON_UTILS_H__
+#define __COMMON_UTILS_H__
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include "key_config_manager.h"
+#include "factory_configurator_client.h"
+#include "fcc_defs.h"
+#include "cs_utils.h"
+#include "cs_der_certs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**This function retrieves kcm data buffer and its size according to the given name.
+* In case of success - The function allocates buffer for current kcm data and it is a user's responsibility to free the allocated memory.
+*
+* @param parameter_name[in]                  buffer of parameter name.
+* @param size_of_parameter_name[in]          size of parameter name.
+* @kcm_type[in]                              type of kcm data to retrieve
+* @param kcm_data[out]                       pointer to kcm data.
+* @param kcm_data_size[out]                  size of kcm data.
+*        fcc_status_e status.
+*/
+fcc_status_e fcc_get_kcm_data(const uint8_t *parameter_name, size_t size_of_parameter_name, kcm_item_type_e kcm_type, uint8_t **kcm_data, size_t *kcm_data_size);
+#if 0
+/**This function retrieves certificate's attribute using it's name.
+* The function allocates memory for attribute data buffer  and it is user's responsibility to free the allocated  memory.
+*
+* @param cert_name[in]                  The name of certificate
+* @param size_of_cert_name[in]          The size of certificate name.
+* @param attribute_type[in]             The type of attribute to retrieve.
+* @param attribute_data[out]            Attribute data buffer. If NULL and the size of the attribute_data_size is 0,the buffer is allocated by the function.
+*                                       Otherwise the function uses supplied buffer.
+* @param attribute_act_data_size[out]   The actual size of attribute data buffer.
+*        fcc_status_e status.
+*/
+fcc_status_e fcc_get_certificate_attribute_by_name_with_allocate(const uint8_t *cert_name, size_t size_of_cert_name, cs_certificate_attribute_type_e attribute_type, uint8_t **attribute_data, size_t attribute_data_size, size_t *attribute_act_data_size);
+#endif
+/**This function retrieves certificate's attribute using it's name.
+* The function allocates memory for attribute data buffer in case it was not allocated by user, and it is user's responsibility to free the allocated  memory.
+* @param cert_name[in]                  The name of certificate
+* @param size_of_cert_name[in]          The size of certificate name.
+* @param attribute_type[in]             The type of attribute to retrieve.
+* @param attribute_data[out]            Attribute data buffer. If NULL and the size of the attribute_data_size is 0,the buffer is allocated by the function.
+*                                       Otherwise the function uses supplied buffer.
+* @param attribute_data_size[in]       Attribute data buffer. Should be 0 in case the attribute_data is NULL.
+* @param attribute_act_data_size[out]   The actual size of attribute data buffer.
+*        fcc_status_e status.
+*/
+fcc_status_e fcc_get_certificate_attribute_by_name(const uint8_t *cert_name, size_t size_of_cert_name, cs_certificate_attribute_type_e attribute_type, uint8_t *attribute_data, size_t attribute_data_size, size_t *attribute_act_data_size);
+
+
+/**This function retrieves certificate's attribute and it's size according to its type.
+*   The function allocates memory for the attribute and it is a user's responsibility to free the allocated memory.
+*
+* @param certificate_data[in]                  buffer of certificate.
+* @param size_of_certificate_data[in]          size of certificate data.
+* @attribute_type[in]                          type of attribute to retrieve.
+* @param attribute_data[out]                   attribute data buffer.
+* @param attribute_act_data_size[out]          actual size of the attribute data
+*        fcc_status_e status.
+*/
+fcc_status_e fcc_get_certificate_attribute(palX509Handle_t x509_cert, cs_certificate_attribute_type_e attribute_type, uint8_t **attribute_data, size_t *attribute_act_data_size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__COMMON_UTILS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/fcc_malloc.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,58 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FCC_MALLOC_H__
+#define __FCC_MALLOC_H__
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+   
+/**
+* Allocate the requested amount of bytes and log heap statistics.
+* - It is assumed FCC running in a single thread (no thread safety)
+* - This function does not allows re-entrance
+*
+* @param size The amount of bytes to allocate on the heap memory
+*
+* @returns
+*     If allocation succeeded - a valid pointer to the beginning of the allocated heap memory
+*     If allocation failed - a NULL pointer will be returned
+*/
+void *fcc_malloc(size_t size);
+
+/**
+* Free the heap bytes followed by the given pointer and log heap statistics.
+* - It is assumed FCC running in a single thread (no thread safety)
+* - This function does not allows re-entrance
+*
+* @param ptr A pointer to the beginning of bytes allocated on the heap memory
+*/
+void fcc_free(void *ptr);
+
+#ifndef FCC_MEM_STATS_ENABLED
+#define fcc_malloc(size) malloc( (size) )
+#define fcc_free(ptr) free( (ptr) )
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/fcc_stats.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,40 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FCC_STATS_H__
+#define __FCC_STATS_H__
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+* Prints heap statistics results.
+* - Usually user will call this function at program end.
+*/
+void fcc_stats_print_summary(void);
+
+#ifndef FCC_MEM_STATS_ENABLED
+#define fcc_stats_print_summary()
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/fcc_time_profiling.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,99 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __FCC_TIME_PROFILING_H__
+#define __FCC_TIME_PROFILING_H__
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+#include "mbed-trace/mbed_trace.h"
+#include "pal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef FCC_TIME_PROFILING
+
+extern uint64_t fcc_gen_timer;
+extern uint64_t fcc_bundle_timer;
+extern uint64_t fcc_key_timer;
+extern uint64_t fcc_certificate_timer;
+extern uint64_t fcc_config_param_timer;
+extern uint64_t fcc_certificate_chain_timer;
+
+#define TRACE_GROUP     "fcc"
+
+/**
+* Init timer
+*/
+#define FCC_INIT_TIMER(ticks) calculate_time("",0,pal_osKernelSysTick() - ticks)
+/**
+* Start timer
+*/
+#define FCC_SET_START_TIMER(ticks) ticks=pal_osKernelSysTick();
+
+/**
+* End timer, print label and the calculated result.
+* If the label is string "size" should be 0, and if the label is buffer - "size" should be the size of buffer to print.
+*/
+#define FCC_END_TIMER(label,size, ticks) calculate_time(label,size,pal_osKernelSysTick() - ticks)
+/**
+*  The function calculates time from started timer, prints the label as string or as buffer with size and the calulated time.
+**/
+
+static inline void calculate_time(const char *label, int size, uint64_t ticks)
+{
+    static double ticks_persecond = 0.0;
+    static double ticks_permillisecond = 0.0;
+    static double ticks_permicrosecond = 0.0;
+
+    // Since the tick conversion to time functions on some of the reference platforms give incorrect results,
+    // we use pal_osDelay() to estimate how many ticks per second. We do this once and then base all
+    // subsequent calculations on the values that we store in static variables.
+    // For new platforms the accuracy of pal_osDelay() should be verified before accepting the time results.
+    if (ticks_persecond == 0.0)
+    {
+        // Calculate how many ticks per second
+        uint64_t tick1 = pal_osKernelSysTick();
+        // One second delay
+        pal_osDelay(1000);
+        uint64_t tick2 = pal_osKernelSysTick();
+        ticks_persecond = tick2 - tick1;
+        ticks_permillisecond = ticks_persecond / 1000.0;
+        ticks_permicrosecond = ticks_persecond / 1000000.0;
+    }
+    if (size == 0) {
+        //Print string
+        mbed_tracef(TRACE_LEVEL_ERROR, TRACE_GROUP, "%s: %20lu ticks, %10.2lf milli, %10.2lf micro\n", (char*)label, (long unsigned int)ticks, (double)(ticks / ticks_permillisecond), (double)(ticks / ticks_permicrosecond));
+    }  else {
+        //Print buffer with size "size"
+        mbed_tracef(TRACE_LEVEL_ERROR, TRACE_GROUP, "%.*s: %20lu ticks, %10.2lf milli, %10.2lf micro\n",size, label, (long unsigned int)ticks, (double)(ticks / ticks_permillisecond), (double)(ticks / ticks_permicrosecond));
+    }
+}
+#else 
+#define FCC_INIT_TIMER(ticks)  do {} while (0)
+#define FCC_SET_START_TIMER(ticks) do {} while (0)
+#define FCC_END_TIMER(label, size, ticks) do {} while (0)
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // __PV_MACROS_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/general_utils.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,27 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool is_memory_equal(const void *buf1, size_t size_of_buf1, const void *buf2, size_t size_of_buf2);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/pv_endian.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,118 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __PV_ENDIAN_H__
+#define __PV_ENDIAN_H__
+
+#include <inttypes.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @file pv_endian.h
+ *
+ *    Utility functions that treats endianness.
+ */
+
+
+/** Converts a little endian 32 bit integer to the host endianness, in a platform independent manner.
+ *
+ *  @param le32  [in] 32 bit integer in little endian format.	
+ *
+ *  @returns
+ *	    32 bit integer in host endianness format.
+ */
+static inline uint32_t pv_le32_to_h(uint32_t le32)
+{
+    const uint8_t* le32ptr = (uint8_t*)&le32;
+    return (le32ptr[0] << 0)  +
+           (le32ptr[1] << 8)  +
+           (le32ptr[2] << 16) +
+           (le32ptr[3] << 24);
+}
+
+/** Converts a big endian 32 bit integer to the host endianness, in a platform independent manner.
+ *
+ *  @param be32  [in] 32 bit integer in big endian format.
+ *
+ *  @returns
+ *      32 bit integer in host endianness format.
+ */
+static inline uint32_t pv_be32_to_h(uint32_t be32)
+{
+    const uint8_t* be32ptr = (uint8_t*)&be32;
+    return (be32ptr[0] << 24) +
+           (be32ptr[1] << 16) +
+           (be32ptr[2] << 8)  +
+           (be32ptr[3] << 0);
+}
+
+
+/**  Converts a host endianness 32 bit integer to little endian, in a platform independent manner.
+ * 
+ *    @param host32  [in] 32 bit integer in host endianness format
+ *
+ *    @returns 
+ *        32 bit integer in little endian format.
+ */
+static inline uint32_t pv_h_to_le32(uint32_t host32)
+{
+    uint32_t le32;
+    uint8_t *le32_ptr = (uint8_t*)&le32;
+
+    le32_ptr[0] = (host32 >> 0)  & 0xff;
+    le32_ptr[1] = (host32 >> 8)  & 0xff;
+    le32_ptr[2] = (host32 >> 16) & 0xff;
+    le32_ptr[3] = (uint8_t)(host32 >> 24) & 0xff;
+
+    /*@-usedef@*/
+    // le32 is being initialized through a pointer.
+    return le32;
+    /*@+usedef@*/
+}
+
+
+/** Converts a host endianness 32 bit integer to big endian, in a platform independent manner.
+ *
+ *    @param host32  [in] 32 bit integer in host endianness format
+ *
+ *    @returns
+ *       32 bit integer in big endian format.
+ */
+static inline uint32_t pv_h_to_be32(uint32_t host32)
+{
+    uint32_t be32;
+    uint8_t *be32_ptr = (uint8_t*)&be32;
+
+    be32_ptr[0] = (uint8_t)(host32 >> 24) & 0xff;
+    be32_ptr[1] = (host32 >> 16) & 0xff;
+    be32_ptr[2] = (host32 >> 8)  & 0xff;
+    be32_ptr[3] = (host32 >> 0)  & 0xff;
+
+    /*@-usedef@*/
+    // be32 is being initialized through a pointer.
+    return be32;
+    /*@+usedef@*/
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // __PV_ENDIAN_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/pv_error_handling.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,295 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __PV_ERROR_HANDLING_H__
+#define __PV_ERROR_HANDLING_H__
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <assert.h>
+#include <stdbool.h>
+
+#include "pv_log.h"
+
+
+/** The following are macros to enable different error handling in development
+ *    environment and production environment:
+ *    On development environment, in oredr to speed up bug fixing we might want
+ *    to assert or disable CK services. On production we shall not halt since
+ *    we might get the whole device stuck.
+ *    The errors are devided into 2 categories:
+ *    1. recoverable errors - like invalid parameter to API function
+ *    2. non-recoverable errors - like allocation failures
+ *    default values for production is to not halt in any case,
+ *    for development the default is to halt in non-recovrable error only
+ *    since recoverable error may occure in negative tests
+ */
+#ifdef DEVELOPMENT_ENV
+#define HALT_ON_RECOVERABLE_ERRORS()  	0
+#define HALT_ON_UNRECOVERABLE_ERRORS()  0
+#else //if PRODUCTION_ENV
+#define HALT_ON_RECOVERABLE_ERRORS()  	0
+#define HALT_ON_UNRECOVERABLE_ERRORS()  0
+#endif
+
+/**  Set this to 1 to immediately assert when an unrecoverable error is
+ *    detected in PC environment.
+ *    While it can be nice to get an immediate assert, often seeing the
+ *    call trace is more useful - so the default is NOT to assert.
+ */
+#define ASSERT_IN_PC_ENV() 0
+
+// Currently, this flag is defined in makefile errors.mk
+// Set this to 1 in order to completely ignore unrecoverable errors -
+// condition won't be checked, nothing would be printed.
+// This should only be used in situations where memory is very tight,
+// and would render debugging very complicated!
+//#define IGNORE_UNRECOVERABLE_ERRORS 0
+
+
+void pv_error_occured(void);
+bool pv_error_is_error_occured(void);
+
+#if  ((HALT_ON_RECOVERABLE_ERRORS()) || (HALT_ON_UNRECOVERABLE_ERRORS()))
+#define SA_PV_IS_PREV_ERROR_OCCURED() (pv_error_is_error_occured())
+#else
+#define SA_PV_IS_PREV_ERROR_OCCURED() (false)
+#endif
+
+
+
+#define _SA_PV_ERR_ASSERT_UPON_ERROR(cond, return_code, ...) {\
+	if (cond) { \
+		SA_PV_LOG_ERR_FUNC_EXIT(__VA_ARGS__);\
+		assert(!(cond));\
+		(void)return_code;  /* Mention explicitly to fail compilation if return_code is not compilable. */ \
+		abort();\
+	}\
+}
+
+#define _SA_PV_ERR_ASSERT_UPON_ERROR_GOTO(cond, return_code_assignment, goto_label, ...) {\
+	if (cond) {\
+		SA_PV_LOG_ERR(__VA_ARGS__);\
+		assert(!(cond));\
+		abort();\
+		return_code_assignment;  /* Mention explicitly to fail compilation if return_code_assignment is not compilable. */ \
+		goto goto_label;\
+	}\
+}
+
+#define _SA_PV_ERR_OCCURED_AND_RETURN_UPON_ERROR(cond, return_code, ...) {\
+	if (cond) {\
+		SA_PV_LOG_ERR_FUNC_EXIT(__VA_ARGS__); \
+		pv_error_occured();\
+		return return_code;\
+	}\
+}
+
+#define _SA_PV_RETURN_UPON_ERROR(level, cond, return_code, ...) {\
+	if (cond) {\
+		SA_PV_LOG_ ## level ## _FUNC_EXIT(__VA_ARGS__);\
+		return return_code;\
+	}\
+}
+#define _SA_PV_ERR_OCCURED_AND_GOTO_UPON_ERROR(cond, return_code_assignment, goto_label, ...) {\
+	if (cond) {\
+		SA_PV_LOG_ERR(__VA_ARGS__);\
+		pv_error_occured();\
+		return_code_assignment;\
+		goto goto_label;\
+	}\
+}
+
+#define _SA_PV_GOTO_UPON_ERROR(level, cond, return_code_assignment, goto_label, ...) {\
+	if (cond) {\
+		SA_PV_LOG_ ## level(__VA_ARGS__); \
+		return_code_assignment;\
+		goto goto_label;\
+	}\
+}
+
+
+/**  For non-recoverable errors, if condition fails:
+ *    log error message
+ *    if in development and running on PC - assert
+ *    if in development but not PC - disable further processing with CK and return error code
+ *    if in case in production (default  behavior), just return error code
+ */
+#if HALT_ON_UNRECOVERABLE_ERRORS()
+#if defined(SA_PV_PC_ENV) && ASSERT_IN_PC_ENV()
+#ifndef IGNORE_UNRECOVERABLE_ERRORS
+#define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \
+				_SA_PV_ERR_ASSERT_UPON_ERROR((cond), (return_code), ##__VA_ARGS__)
+#else
+#define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \
+				if (false && (cond)) {}  /* Dummy use of the condition to avoid compiler warnings */
+#endif
+#else
+#ifndef IGNORE_UNRECOVERABLE_ERRORS
+#define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \
+				_SA_PV_ERR_OCCURED_AND_RETURN_UPON_ERROR((cond), (return_code), ##__VA_ARGS__)
+#else
+#define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \
+				if (false && (cond)) {}  /* Dummy use of the condition to avoid compiler warnings */
+#endif
+#endif
+#else   // HALT_ON_UNRECOVERABLE_ERRORS  
+#ifndef IGNORE_UNRECOVERABLE_ERRORS
+#define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \
+			_SA_PV_RETURN_UPON_ERROR(ERR, (cond), (return_code), ##__VA_ARGS__)
+#else
+#define SA_PV_ERR_UNRECOVERABLE_RETURN_IF(cond, return_code, ...) \
+			if (false && (cond)) {}  /* Dummy use of the condition to avoid compiler warnings */
+#endif
+#endif // HALT_ON_UNRECOVERABLE_ERRORS
+
+/**  For non-recoverable errors, if condition fails:
+ *     log error message
+ *     if in development and running on PC - assert
+ *     if in development but not PC - disable further processing with CK and assign error code and goto label
+ *     if in case in production (default  behavior), just  assign error code and goto label
+ */
+#if HALT_ON_UNRECOVERABLE_ERRORS()
+#if defined(SA_PV_PC_ENV) && ASSERT_IN_PC_ENV()
+#ifndef IGNORE_UNRECOVERABLE_ERRORS
+#define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+				_SA_PV_ERR_ASSERT_UPON_ERROR_GOTO((cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
+#else
+#define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+				if (false && (cond)) {  /* Dummy use of the condition to avoid compiler warnings */ \
+					return_code_assignment;  /* Dummy use of the assignment to avoid compiler warnings */ \
+					goto goto_label;  /* Dummy use of the goto label to avoid compiler warnings. */ \
+				}
+#endif
+#else
+#ifndef IGNORE_UNRECOVERABLE_ERRORS
+#define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+				_SA_PV_ERR_OCCURED_AND_GOTO_UPON_ERROR((cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
+#else
+#define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+				if (false && (cond)) {  /* Dummy use of the condition to avoid compiler warnings */ \
+					return_code_assignment;  /* Dummy use of the assignment to avoid compiler warnings */ \
+					goto goto_label;  /* Dummy use of the goto label to avoid compiler warnings. */ \
+				}
+#endif
+#endif
+#else // HALT_ON_UNRECOVERABLE_ERRORS  
+#ifndef IGNORE_UNRECOVERABLE_ERRORS
+#define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+			_SA_PV_GOTO_UPON_ERROR(ERR, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
+#else
+#define SA_PV_ERR_UNRECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+			if (false && (cond)) {  /* Dummy use of the condition to avoid compiler warnings */ \
+				return_code_assignment;  /* Dummy use of the assignment to avoid compiler warnings */ \
+				goto goto_label;  /* Dummy use of the goto label to avoid compiler warnings. */ \
+			}
+#endif
+#endif // HALT_ON_UNRECOVERABLE_ERRORS
+
+
+/** Recoverable errors handling
+ *    For recoverable errors, if condition fails:
+ *    log error message
+ *    if in development and running on PC - assert
+ *    if in development but not PC - disable further processing with CK and return error code
+ *    if in case in production (default  behavior), just log and return error code
+ *    this is all only regarding errors. INFO, TRACE, etc. will not cause halt, will just log and return error code
+ */
+#if HALT_ON_RECOVERABLE_ERRORS()
+#if defined(SA_PV_PC_ENV) && ASSERT_IN_PC_ENV()
+#define SA_PV_ERR_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
+			_SA_PV_ERR_ASSERT_UPON_ERROR((cond), return_code, ##__VA_ARGS__)
+#else
+#define SA_PV_ERR_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
+			_SA_PV_ERR_OCCURED_AND_RETURN_UPON_ERROR((cond), (return_code), ##__VA_ARGS__)
+#endif
+#else // HALT_ON_RECOVERABLE_ERRORS
+#define SA_PV_ERR_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
+		_SA_PV_RETURN_UPON_ERROR(ERR, (cond), (return_code), ##__VA_ARGS__)
+
+#define SA_PV_ERR_RECOVERABLE_RETURN(return_code, ...) \
+        SA_PV_LOG_ERR_FUNC_EXIT(__VA_ARGS__); \
+        return return_code;
+#endif // HALT_ON_RECOVERABLE_ERRORS
+
+// if the condition is true:
+// Theses macros return with return_code and perform the exit function log (if the log level is appropriate).
+
+// FIXME: This is partial solution, for critical level, also unrecoverable return should be treated and
+// the macros for different  flags should be implemented (HALT_ON_RECOVERABLE_ERRORS etc.)
+#define SA_PV_CRITICAL_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
+	_SA_PV_RETURN_UPON_ERROR(CRITICAL, (cond), (return_code), ##__VA_ARGS__)
+//	used in errors that are not critical (such as failure to read data from a socket - a retry is scheduled)
+#define SA_PV_WARN_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
+	_SA_PV_RETURN_UPON_ERROR(WARN, (cond), (return_code), ##__VA_ARGS__)
+//	used in external APIs
+#define SA_PV_INFO_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
+	_SA_PV_RETURN_UPON_ERROR(INFO, (cond), (return_code), ##__VA_ARGS__)
+//	used in internal APIs
+#define SA_PV_TRACE_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
+	_SA_PV_RETURN_UPON_ERROR(TRACE, (cond), (return_code), ##__VA_ARGS__)
+#define SA_PV_DATA_RECOVERABLE_RETURN_IF(cond, return_code, ...) \
+	_SA_PV_RETURN_UPON_ERROR(DATA, (cond), (return_code), ##__VA_ARGS__)
+
+/** For recoverable errors, if condition fails:
+ *    log error message
+ *    if in development and running on PC - assert
+ *    if in development but not PC - disable further processing with CK and assign error code and goto label
+ *    if in case in production (default  behavior), just log, assign error code and goto label
+ *    this is all only regarding errors. INFO, TRACE, etc. will not cause halt, will just log, assign error code and goto label
+ */
+#if HALT_ON_RECOVERABLE_ERRORS()
+#if defined(SA_PV_PC_ENV) && ASSERT_IN_PC_ENV()
+#define SA_PV_ERR_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+			_SA_PV_ERR_ASSERT_UPON_ERROR_GOTO((cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
+#else
+#define SA_PV_ERR_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+			_SA_PV_ERR_OCCURED_AND_GOTO_UPON_ERROR((cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
+#endif
+#else // HALT_ON_RECOVERABLE_ERRORS
+#define SA_PV_ERR_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+		_SA_PV_GOTO_UPON_ERROR(ERR, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
+#endif // HALT_ON_RECOVERABLE_ERRORS
+
+// if the condition is true:
+// Theses macros jump to goto_label with return_code and perform log (if the log level is appropriate).
+
+// FIXME: This is partial solution, for critical level, also unrecoverable goto should be treated and
+// the macros for differnet  flags should be implemented (HALT_ON_RECOVERABLE_ERRORS etc.)
+#define SA_PV_CRITICAL_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+	_SA_PV_GOTO_UPON_ERROR(CRITICAL, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
+//	used in errors that are not critical (such as failure to read data from a socket - a retry is scheduled)
+#define SA_PV_WARN_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+	_SA_PV_GOTO_UPON_ERROR(WARN, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
+//	used in external APIs
+#define SA_PV_INFO_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+	_SA_PV_GOTO_UPON_ERROR(INFO, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
+//	used in internal APIs
+#define SA_PV_TRACE_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+	_SA_PV_GOTO_UPON_ERROR(TRACE, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
+//	used in functions that are called many times and we don't necessary want to see all its logging even in TRACE mode
+#define SA_PV_DATA_RECOVERABLE_GOTO_IF(cond, return_code_assignment, goto_label, ...) \
+	_SA_PV_GOTO_UPON_ERROR(DATA, (cond), (return_code_assignment), goto_label, ##__VA_ARGS__)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // __PV_ERROR_HANDLING_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/factory-configurator-client/utils/utils/pv_macros.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,179 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//  
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __PV_MACROS_H__
+#define __PV_MACROS_H__
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Ignore a pointer parameter */
+#define PV_IGNORE_PARAM_PTR NULL
+
+/* Ignore parameter value */
+#define PV_IGNORE_PARAM_VAL 0
+
+/* This parameter is temporarily muted or unused for good resons */
+#define PV_UNUSED_PARAM(param) \
+    (void)(param)
+
+/* Variable used only for DEBUG targets (like prints or macros
+*  which are effective only in debug mode) */
+#define PV_DEBUG_USE(var) \
+    PV_UNUSED_PARAM(var)
+
+
+/* Compile time assertion (we do not have static_assert support). */
+#define PV_ASSERT_CONCAT_(a, b) a##b
+#define PV_ASSERT_CONCAT(a, b) PV_ASSERT_CONCAT_(a, b)
+#define PV_CASSERT(cond, message) \
+    enum { PV_ASSERT_CONCAT(assert_line_, __LINE__) = 1 / (int)(!!(cond)) }
+
+/* Returns the amount of elements in an array. */
+#define PV_ARRAY_LENGTH(array) (sizeof(array)/sizeof((array)[0]))
+
+/*Returns number in range between max and min */
+#define PV_NUMBER_LIMIT(number, max, min ) ((number % (max - min + 1)) + min)
+
+
+/**
+ * Returns the size of a member in a struct.
+ */
+#define PV_SIZEOF_MEMBER(struct_type, member_name) sizeof(((struct_type *)0)->member_name)
+
+/**
+ *  Checks alignment of val to uint32_t
+*/
+#ifndef SA_PV_PLAT_PC
+#define PV_IS_ALIGNED(val) 		\
+    ((val & ((sizeof(uint32_t) - 1))) ==  0)
+#else
+#define PV_IS_ALIGNED(val) 	 \
+    ((sizeof(uint32_t) & ((sizeof(uint32_t) - 1))) ==  0)
+#endif
+
+
+/** Reads a uint32_t from a potentially unaligned uint8_t pointer.
+ *   As we cannot know if unaligned access is allowed, using this approach is the
+ *   only way to guarantee correct behavior.
+ *
+ *    @param buf	
+ *
+ *    @returns
+ *	    32 bit number
+ */
+static inline uint32_t pv_read_uint32(const uint8_t *buf)
+{
+    uint32_t number;
+    memcpy(&number, buf, sizeof(number));
+    return number;
+}
+
+
+
+/** Reads a uint64_t from a potentially unaligned uint8_t pointer.
+*     As we cannot know if unaligned access is allowed, using this approach is the
+*     only way to guarantee correct behavior.
+*
+*    @param buf    
+*
+*    @returns
+*        64 bit number
+*/
+static inline uint64_t pv_read_uint64(const uint8_t *buf)
+{
+    uint64_t number;
+    memcpy(&number, buf, sizeof(number));
+    return number;
+}
+
+
+/** Writes a uint32_t to a potentially unaligned uint8_t pointer.
+ *    As we cannot know if unaligned access is allowed, using this approach is the
+ *    only way to guarantee correct behavior.
+ *
+ *    @param buf
+ *    @param number
+ *
+ */
+static inline void pv_write_uint32(uint8_t *buf, uint32_t number)
+{
+    memcpy(buf, &number, sizeof(number));
+}
+
+
+/** Calculates the length of a string.
+ * 
+ *    @param str [in] - A pointer to an input string. If NULL, 0  will be returned.
+ *                                                  
+ *    @returns
+ *        the number of characters in a string without counting the null termination character.
+ *        There is no strnlen in libC. It's posix extension that also exists in mbed-os, but may not exist in other OS
+ */
+static inline uint32_t pv_str_n_len(const char* str, uint32_t max_size)
+{
+    uint32_t i = 0;
+    if (str == NULL) {
+        return 0;
+    }
+
+    while (i < max_size && str[i] != '\0') {
+        i++;
+    }
+
+    return i;
+}
+
+
+/** Compares strings (source with target)
+ * 
+ *    @param str1 [in]  - First string to compare
+ *    @param str2 [in]  - Second string to compare
+ *    @param a_max_size [in]	- Max number of characters to compare
+ *
+ *    @returns
+ *        true - if strings are identical.
+ *        false -if strings are not identical
+ */
+static inline bool pv_str_equals(const char* str1, const char* str2, uint32_t a_max_size)
+{
+    uint32_t str_size = pv_str_n_len(str1, a_max_size);
+
+    if (str_size == a_max_size) {
+        return false;
+    }
+    if (str_size != pv_str_n_len(str2, a_max_size)) {
+        return false;
+    }
+
+    if (strncmp(str1, str2, a_max_size) != 0) {
+        return false;
+    }
+
+    return true;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // __PV_MACROS_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+Docs/*
+out/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/CMakeLists.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,91 @@
+if(NOT YOTTA_TARGET)
+    INCLUDE(CMakeForceCompiler)
+    # CROSS COMPILER SETTING
+    cmake_minimum_required (VERSION 2.8)
+    SET(CMAKE_SYSTEM_NAME Generic)
+
+    project(mbedPal)
+
+    
+    macro(SET_COMPILER_DBG_RLZ_FLAG flag value)
+        SET(${flag}_DEBUG "${${flag}_DEBUG} ${value}")
+        SET(${flag}_RELEASE "${${flag}_RELEASE} ${value}")
+    #enable this if for debugging
+    if (0)
+     message("flag = ${flag}")
+     message("value = ${value}")
+     message("MY_C_FLAGS_RELEASE2 = ${CMAKE_C_FLAGS_RELEASE}")
+    endif(0) # comment end
+    endmacro(SET_COMPILER_DBG_RLZ_FLAG)
+
+    if(DISALLOW_WARNINGS)
+        if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+            SET_COMPILER_DBG_RLZ_FLAG (CMAKE_C_FLAGS "-Werror")
+            SET_COMPILER_DBG_RLZ_FLAG (CMAKE_CXX_FLAGS "-Werror")
+        endif()
+    endif()
+
+    SET (PAL_VERSION ${PAL_VERSION_MAJOR}.${PAL_VERSION_MINOR}.${PAL_VERSION_PATCH})
+
+    # configure a header file generator .in to pass some of the CMake settings
+    # to the source code
+    configure_file (
+      "${PROJECT_SOURCE_DIR}/pal_version.h.in"
+      "${PROJECT_BINARY_DIR}/pal_version.h"
+      )
+     
+    if ((${OS_BRAND} MATCHES "Linux"))
+        add_definitions(-DPAL_LINUX)
+    endif() 
+
+    MACRO(HEADER_DIRECTORIES return_list)
+      FILE(GLOB_RECURSE new_list ${CMAKE_CURRENT_SOURCE_DIR}/Configs/pal_config/${OS_BRAND}/*.h)
+      SET(dir_list "")
+      FOREACH(file_path ${new_list})
+          GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
+          SET(dir_list ${dir_list} ${dir_path})
+      ENDFOREACH()
+      LIST(REMOVE_DUPLICATES dir_list)
+      SET(${return_list} ${dir_list})
+    ENDMACRO()
+
+    set(config_list "")
+    HEADER_DIRECTORIES(config_list)
+    foreach(config_dir ${config_list})
+      ADD_GLOBALDIR("${config_dir}")
+    endforeach()
+    
+    ADD_GLOBALDIR(${CMAKE_CURRENT_SOURCE_DIR}/Configs/pal_config)
+
+    # add the binary tree to the search path for include files
+    # so that we will find TutorialConfig.h????????????????????????????????????????????????????????????????????????????
+    ADDSUBDIRS() 
+else()
+    set(OS_BRAND "Linux")
+    set(TLS_LIBRARY "mbedTLS")
+    set(PAL_MODULE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Source)
+
+    # find source files from the relavent directories
+    set(PAL_IMPL_SOURCE_DIR ${PAL_MODULE_SOURCE_DIR}/PAL-Impl)
+    set(PAL_PORT_SOURCE_DIR ${PAL_MODULE_SOURCE_DIR}/Port/Reference-Impl/OS_Specific/${OS_BRAND})
+    set(PAL_TLS_SOURCE_DIR ${PAL_MODULE_SOURCE_DIR}/Port/Reference-Impl/Lib_Specific/${TLS_LIBRARY})
+    set(PAL_EXAMPLE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Examples/PlatformBSP)
+
+    file(GLOB_RECURSE PAL_SRCS "${PAL_IMPL_SOURCE_DIR}/*.c"
+                               "${PAL_PORT_SOURCE_DIR}/Storage/FileSystem/*.c"
+                               "${PAL_PORT_SOURCE_DIR}/Storage/Flash/*.c"
+                               "${PAL_PORT_SOURCE_DIR}/Networking/*.c"
+                               "${PAL_PORT_SOURCE_DIR}/RTOS/*.c"
+                               "${PAL_PORT_SOURCE_DIR}/Update/*.c"
+                               "${PAL_PORT_SOURCE_DIR}/Board_Specific/${PAL_TARGET_DEVICE}/*.c"
+                               "${PAL_EXAMPLE_DIR}/pal_insecure_ROT.c"
+                               "${PAL_TLS_SOURCE_DIR}/*.c")
+
+    add_library(${YOTTA_MODULE_NAME} ${PAL_SRCS})
+
+    # need to specify the yotta dependency here, otherwise yotta won't consider them when linking against this library
+    target_link_libraries(${YOTTA_MODULE_NAME} mbedtls mbed-trace)
+
+    # includes are taken care of via the module.json extraIncludes mechanism in order to be global
+    # link libraries are handled by the module.josn dependencies mechanism
+endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_ARIA_mbedOS.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,278 @@
+//----------------------------------------------------------------------------
+// The confidential and proprietary information contained in this file may
+// only be used by a person authorised under and to the extent permitted
+// by a subsisting licensing agreement from ARM Limited or its affiliates.
+//
+// (C) COPYRIGHT 2016 ARM Limited or its affiliates.
+// ALL RIGHTS RESERVED
+//
+// This entire notice must be reproduced on all copies of this file
+// and copies of this file may only be made by a person if such person is
+// permitted to do so under the terms of a subsisting license agreement
+// from ARM Limited or its affiliates.
+//----------------------------------------------------------------------------
+
+#ifndef PAL_MBEDTLS_USER_CONFIG_H
+#define PAL_MBEDTLS_USER_CONFIG_H
+
+
+/*! All of the following definitions are mandatory requirements for correct 
+*   fucntionality of PAL TLS and Crypto components.
+*   Please do not disable them.
+*/
+
+/* Platform has time function to provide time for certificates verifications */
+#if 1 //Please set to 1 if you are using secure time
+#ifndef MBEDTLS_HAVE_TIME
+    #define MBEDTLS_HAVE_TIME
+#endif //MBEDTLS_HAVE_TIME
+
+#ifndef MBEDTLS_HAVE_TIME_DATE
+    #define MBEDTLS_HAVE_TIME_DATE
+#endif //MBEDTLS_HAVE_TIME_DATE
+
+#ifndef MBEDTLS_PLATFORM_TIME_ALT
+    #define MBEDTLS_PLATFORM_TIME_ALT
+#endif //MBEDTLS_PLATFORM_TIME_ALT
+
+/* System support */
+#ifndef MBEDTLS_HAVE_ASM
+    #define MBEDTLS_HAVE_ASM
+#endif //MBEDTLS_HAVE_ASM
+#endif
+/* mbed TLS feature support */
+#ifndef MBEDTLS_ECP_DP_SECP256R1_ENABLED
+    #define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#endif //MBEDTLS_ECP_DP_SECP256R1_ENABLED
+
+#ifndef MBEDTLS_ECP_NIST_OPTIM
+    #define MBEDTLS_ECP_NIST_OPTIM
+#endif //MBEDTLS_ECP_NIST_OPTIM
+
+#ifndef MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+    #define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+#endif //MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+
+#ifndef MBEDTLS_SSL_PROTO_TLS1_2
+    #define MBEDTLS_SSL_PROTO_TLS1_2
+#endif //MBEDTLS_SSL_PROTO_TLS1_2
+
+#ifndef MBEDTLS_SSL_PROTO_DTLS
+    #define MBEDTLS_SSL_PROTO_DTLS
+#endif //MBEDTLS_SSL_PROTO_DTLS
+
+#ifndef MBEDTLS_SSL_DTLS_ANTI_REPLAY
+    #define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#endif //MBEDTLS_SSL_DTLS_ANTI_REPLAY
+
+#ifndef MBEDTLS_SSL_DTLS_HELLO_VERIFY
+    #define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+#endif //MBEDTLS_SSL_DTLS_HELLO_VERIFY
+
+#ifndef MBEDTLS_SSL_EXPORT_KEYS
+    #define MBEDTLS_SSL_EXPORT_KEYS
+#endif //MBEDTLS_SSL_EXPORT_KEYS
+
+/* mbed TLS modules */
+#ifndef MBEDTLS_AES_C
+    #define MBEDTLS_AES_C
+#endif //MBEDTLS_AES_C
+
+#ifndef MBEDTLS_ASN1_PARSE_C
+    #define MBEDTLS_ASN1_PARSE_C
+#endif //MBEDTLS_ASN1_PARSE_C
+
+#ifndef MBEDTLS_ASN1_WRITE_C
+    #define MBEDTLS_ASN1_WRITE_C
+#endif //MBEDTLS_ASN1_WRITE_C
+
+#ifndef MBEDTLS_BIGNUM_C
+    #define MBEDTLS_BIGNUM_C
+#endif //MBEDTLS_BIGNUM_C
+
+#ifndef MBEDTLS_CIPHER_C
+    #define MBEDTLS_CIPHER_C
+#endif //MBEDTLS_CIPHER_C
+
+#ifndef MBEDTLS_CTR_DRBG_C
+    #define MBEDTLS_CTR_DRBG_C
+#endif //MBEDTLS_CTR_DRBG_C
+
+#ifndef MBEDTLS_ECP_C
+    #define MBEDTLS_ECP_C
+#endif //MBEDTLS_ECP_C
+
+#ifndef MBEDTLS_ENTROPY_C
+    #define MBEDTLS_ENTROPY_C
+#endif //MBEDTLS_ENTROPY_C
+
+#ifndef MBEDTLS_MD_C
+    #define MBEDTLS_MD_C
+#endif //MBEDTLS_MD_C
+
+#ifndef MBEDTLS_OID_C
+    #define MBEDTLS_OID_C
+#endif //MBEDTLS_OID_C
+
+#ifndef MBEDTLS_PK_C
+    #define MBEDTLS_PK_C
+#endif //MBEDTLS_PK_C
+
+#ifndef MBEDTLS_PK_PARSE_C
+    #define MBEDTLS_PK_PARSE_C
+#endif //MBEDTLS_PK_PARSE_C
+
+#ifndef MBEDTLS_SHA256_C
+    #define MBEDTLS_SHA256_C
+#endif //MBEDTLS_SHA256_C
+
+#ifndef MBEDTLS_SSL_COOKIE_C
+    #define MBEDTLS_SSL_COOKIE_C
+#endif //MBEDTLS_SSL_COOKIE_C
+
+#ifndef MBEDTLS_SSL_CLI_C
+    #define MBEDTLS_SSL_CLI_C
+#endif //MBEDTLS_SSL_CLI_C
+
+#ifndef MBEDTLS_SSL_TLS_C
+    #define MBEDTLS_SSL_TLS_C
+#endif //MBEDTLS_SSL_TLS_C
+// XXX mbedclient needs these: mbedtls_x509_crt_free, mbedtls_x509_crt_init, mbedtls_x509_crt_parse
+#ifndef MBEDTLS_X509_USE_C
+    #define MBEDTLS_X509_USE_C
+#endif //MBEDTLS_X509_USE_C
+
+#ifndef MBEDTLS_X509_CRT_PARSE_C
+    #define MBEDTLS_X509_CRT_PARSE_C
+#endif //MBEDTLS_X509_CRT_PARSE_C
+// a bit wrong way to get mbedtls_ssl_conf_psk:
+#ifndef MBEDTLS_CMAC_C
+    #define MBEDTLS_CMAC_C
+#endif //MBEDTLS_CMAC_C
+
+#ifndef MBEDTLS_ECDH_C
+    #define MBEDTLS_ECDH_C
+#endif //MBEDTLS_ECDH_C
+
+#ifndef MBEDTLS_ECDSA_C
+    #define MBEDTLS_ECDSA_C
+#endif //MBEDTLS_ECDSA_C
+
+#ifndef MBEDTLS_GCM_C
+    #define MBEDTLS_GCM_C
+#endif //MBEDTLS_GCM_C
+
+#ifndef MBEDTLS_X509_CRT_PARSE_C
+    #define MBEDTLS_X509_CRT_PARSE_C
+#endif //MBEDTLS_X509_CRT_PARSE_C
+
+#ifndef MBEDTLS_X509_CSR_PARSE_C
+    #define MBEDTLS_X509_CSR_PARSE_C
+#endif //MBEDTLS_X509_CSR_PARSE_C
+
+#ifndef MBEDTLS_X509_CREATE_C
+    #define MBEDTLS_X509_CREATE_C
+#endif //MBEDTLS_X509_CREATE_C
+
+#ifndef MBEDTLS_X509_CSR_WRITE_C
+    #define MBEDTLS_X509_CSR_WRITE_C
+#endif //MBEDTLS_X509_CSR_WRITE_C
+
+#ifndef MBEDTLS_CTR_DRBG_MAX_REQUEST
+    #define MBEDTLS_CTR_DRBG_MAX_REQUEST 2048
+#endif //MBEDTLS_CTR_DRBG_MAX_REQUEST
+
+// Needed by update
+#ifndef MBEDTLS_CIPHER_MODE_CTR
+    #define MBEDTLS_CIPHER_MODE_CTR
+#endif //MBEDTLS_CIPHER_MODE_CTR
+
+/**
+ * Enable ARIA ciphersuites.
+ */
+
+#define MBEDTLS_ARIA_C
+
+// Save ROM and a few bytes of RAM by specifying our own ciphersuite list
+#ifndef MBEDTLS_SSL_CIPHERSUITES
+    #define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, \
+                                     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \
+                                     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \
+                                     MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, \
+                                     MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, \
+                                     MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, \
+                                     MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, \
+                                     MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256
+#endif //MBEDTLS_SSL_CIPHERSUITES
+
+/*! All of the following definitions are optimizations (reduce mbedTLS memory usage and size),
+*   changing them is on the user responsibility since they can enlarge
+*   the binary footprint and the memory usage
+*/
+
+// define to save 8KB RAM at the expense of ROM
+#ifndef MBEDTLS_AES_ROM_TABLES
+    #define MBEDTLS_AES_ROM_TABLES
+#endif //MBEDTLS_AES_ROM_TABLES
+
+// Reduce IO buffer to save RAM, default is 16KB
+#ifndef MBEDTLS_SSL_MAX_CONTENT_LEN
+    #define MBEDTLS_SSL_MAX_CONTENT_LEN 4096
+#endif //MBEDTLS_SSL_MAX_CONTENT_LEN
+
+// needed for Base64 encoding Opaque data for
+// registration payload, adds 500 bytes to flash.
+#ifndef MBEDTLS_BASE64_C
+    #define MBEDTLS_BASE64_C
+#endif // MBEDTLS_BASE64_C
+
+// Needed by provisioning
+#undef MBEDTLS_PEM_WRITE_C
+
+// Remove RSA, save 20KB at total
+#if !MBED_CONF_MBED_CLIENT_PAL_RSA_REQUIRED
+    #undef MBEDTLS_RSA_C
+    #undef MBEDTLS_PK_RSA_ALT_SUPPORT
+    #undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+    #undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+    #undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+#endif // MBED_CONF_MBED_CLIENT_PAL_RSA_REQUIRED
+
+// Remove error messages, save 10KB of ROM
+#undef MBEDTLS_ERROR_C
+
+// Remove selftesting and save 11KB of ROM
+#undef MBEDTLS_SELF_TEST
+
+#undef MBEDTLS_CERTS_C
+
+// Reduces ROM size by 30 kB
+#undef MBEDTLS_ERROR_STRERROR_DUMMY
+
+#undef MBEDTLS_VERSION_FEATURES
+
+#undef MBEDTLS_DEBUG_C
+
+// needed for parsing the certificates
+#undef MBEDTLS_PEM_PARSE_C
+
+#undef MBEDTLS_SHA512_C
+
+#undef MBEDTLS_SSL_SRV_C
+
+#undef MBEDTLS_ECP_DP_SECP192R1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP224R1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP521R1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP192K1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP224K1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP256K1_ENABLED
+#undef MBEDTLS_ECP_DP_BP256R1_ENABLED
+#undef MBEDTLS_ECP_DP_BP384R1_ENABLED
+#undef MBEDTLS_ECP_DP_BP512R1_ENABLED
+#undef MBEDTLS_ECP_DP_CURVE25519_ENABLED
+
+
+#include "mbedtls/check_config.h"
+
+#endif /* PAL_MBEDTLS_USER_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_FreeRTOS.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2563 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration options (set of defines)
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  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.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+/*
+ * This set of compile-time options may be used to enable
+ * or disable features selectively, and reduce the global
+ * memory footprint.
+ */
+#ifndef KSDK_MBEDTLS_CONFIG_H
+#define KSDK_MBEDTLS_CONFIG_H
+
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+/**************************** KSDK ********************************************/
+
+#include "fsl_device_registers.h"
+
+/* Enable LTC use in library if there is LTC on chip. */
+#if defined(FSL_FEATURE_SOC_LTC_COUNT) && (FSL_FEATURE_SOC_LTC_COUNT > 0)
+    #include "fsl_ltc.h"
+
+    #define LTC_INSTANCE                LTC0    /* LTC base register.*/
+
+    #if defined(FSL_FEATURE_LTC_HAS_DES) && FSL_FEATURE_LTC_HAS_DES
+        #define MBEDTLS_FREESCALE_LTC_DES       /* Enable use of LTC DES.*/
+    #endif
+    #define MBEDTLS_FREESCALE_LTC_AES           /* Enable use of LTC AES.*/
+    #if defined(FSL_FEATURE_LTC_HAS_GCM) && FSL_FEATURE_LTC_HAS_GCM 
+        #define MBEDTLS_FREESCALE_LTC_AES_GCM   /* Enable use of LTC AES GCM.*/
+    #endif
+    #if defined(FSL_FEATURE_LTC_HAS_PKHA) && FSL_FEATURE_LTC_HAS_PKHA 
+        #define MBEDTLS_FREESCALE_LTC_PKHA      /* Enable use of LTC PKHA.*/
+    #endif
+#endif
+
+/* Enable MMCAU use in library if there is MMCAU on chip. */
+#if defined(FSL_FEATURE_SOC_MMCAU_COUNT) && (FSL_FEATURE_SOC_MMCAU_COUNT > 0) 
+    #include "fsl_mmcau.h"
+
+    #define MBEDTLS_FREESCALE_MMCAU_MD5         /* Enable use of MMCAU MD5.*/
+    #define MBEDTLS_FREESCALE_MMCAU_SHA1        /* Enable use of MMCAU SHA1.*/
+    #define MBEDTLS_FREESCALE_MMCAU_SHA256      /* Enable use of MMCAU SHA256.*/
+    #define MBEDTLS_FREESCALE_MMCAU_DES         /* Enable use of MMCAU DES, when LTC is disabled.*/
+    #define MBEDTLS_FREESCALE_MMCAU_AES         /* Enable use of MMCAU AES, when LTC is disabled.*/
+#endif
+
+/* Define ALT MMCAU & LTC functions. Do not change it. */
+#if defined(MBEDTLS_FREESCALE_MMCAU_DES) || defined(MBEDTLS_FREESCALE_LTC_DES)
+    #define MBEDTLS_DES_SETKEY_ENC_ALT
+    #define MBEDTLS_DES_SETKEY_DEC_ALT
+    #define MBEDTLS_DES_CRYPT_ECB_ALT
+    #define MBEDTLS_DES3_CRYPT_ECB_ALT
+#endif
+#if defined(MBEDTLS_FREESCALE_LTC_DES)
+    #define MBEDTLS_DES_CRYPT_CBC_ALT
+    #define MBEDTLS_DES3_CRYPT_CBC_ALT
+#endif
+#if defined(MBEDTLS_FREESCALE_LTC_AES) || defined(MBEDTLS_FREESCALE_MMCAU_AES)
+    #define MBEDTLS_AES_SETKEY_ENC_ALT
+    #define MBEDTLS_AES_SETKEY_DEC_ALT
+    #define MBEDTLS_AES_ENCRYPT_ALT
+    #define MBEDTLS_AES_DECRYPT_ALT
+#endif
+#if defined(MBEDTLS_FREESCALE_LTC_AES)
+    #define MBEDTLS_AES_CRYPT_CBC_ALT
+    #define MBEDTLS_AES_CRYPT_CTR_ALT
+    #define MBEDTLS_CCM_CRYPT_ALT
+#endif
+#if defined(MBEDTLS_FREESCALE_LTC_AES_GCM)
+    #define MBEDTLS_GCM_CRYPT_ALT
+#endif
+#if defined(MBEDTLS_FREESCALE_LTC_PKHA)
+    #define MBEDTLS_MPI_ADD_ABS_ALT
+    #define MBEDTLS_MPI_SUB_ABS_ALT
+    #define MBEDTLS_MPI_MUL_MPI_ALT
+    #define MBEDTLS_MPI_MOD_MPI_ALT
+    #define MBEDTLS_MPI_EXP_MOD_ALT
+    #define MBEDTLS_MPI_GCD_ALT
+    #define MBEDTLS_MPI_INV_MOD_ALT
+    #define MBEDTLS_MPI_IS_PRIME_ALT
+    #define MBEDTLS_ECP_MUL_COMB_ALT
+    #define MBEDTLS_ECP_ADD_ALT
+#endif
+#if defined(MBEDTLS_FREESCALE_MMCAU_MD5)
+    #define MBEDTLS_MD5_PROCESS_ALT
+#endif
+#if defined(MBEDTLS_FREESCALE_MMCAU_SHA1)
+    #define MBEDTLS_SHA1_PROCESS_ALT
+#endif
+#if defined(MBEDTLS_FREESCALE_MMCAU_SHA256)
+    #define MBEDTLS_SHA256_PROCESS_ALT
+#endif
+/**************************** KSDK end ****************************************/
+
+/**
+ * \name SECTION: System support
+ *
+ * This section sets system specific settings.
+ * \{
+ */
+#if 1 //Please set to 1 if you are using secure time
+/**
+ * \def MBEDTLS_HAVE_ASM
+ *
+ * The compiler has support for asm().
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ *      library/timing.c
+ *      library/padlock.c
+ *      include/mbedtls/bn_mul.h
+ *
+ * Comment to disable the use of assembly code.
+ */
+#define MBEDTLS_HAVE_ASM
+
+/**
+ * \def MBEDTLS_HAVE_SSE2
+ *
+ * CPU supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ */
+//#define MBEDTLS_HAVE_SSE2
+
+/**
+ * \def MBEDTLS_HAVE_TIME
+ *
+ * System has time.h and time().
+ * The time does not need to be correct, only time differences are used,
+ * by contrast with MBEDTLS_HAVE_TIME_DATE
+ *
+ * Comment if your system does not support time functions
+ */
+#define MBEDTLS_HAVE_TIME
+
+/**
+ * \def MBEDTLS_HAVE_TIME_DATE
+ *
+ * System has time.h and time(), gmtime() and the clock is correct.
+ * The time needs to be correct (not necesarily very accurate, but at least
+ * the date should be correct). This is used to verify the validity period of
+ * X.509 certificates.
+ *
+ * Comment if your system does not have a correct clock.
+ */
+#define MBEDTLS_HAVE_TIME_DATE
+#define MBEDTLS_PLATFORM_TIME_ALT
+#endif //0
+/**
+ * \def MBEDTLS_PLATFORM_MEMORY
+ *
+ * Enable the memory allocation layer.
+ *
+ * By default mbed TLS uses the system-provided calloc() and free().
+ * This allows different allocators (self-implemented or provided) to be
+ * provided to the platform abstraction layer.
+ *
+ * Enabling MBEDTLS_PLATFORM_MEMORY without the
+ * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide
+ * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and
+ * free() function pointer at runtime.
+ *
+ * Enabling MBEDTLS_PLATFORM_MEMORY and specifying
+ * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the
+ * alternate function at compile time.
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *
+ * Enable this layer to allow use of alternative memory allocators.
+ */
+//#define MBEDTLS_PLATFORM_MEMORY
+
+/**
+ * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+ *
+ * Do not assign standard functions in the platform layer (e.g. calloc() to
+ * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF)
+ *
+ * This makes sure there are no linking errors on platforms that do not support
+ * these functions. You will HAVE to provide alternatives, either at runtime
+ * via the platform_set_xxx() functions or at compile time by setting
+ * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a
+ * MBEDTLS_PLATFORM_XXX_MACRO.
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *
+ * Uncomment to prevent default assignment of standard functions in the
+ * platform layer.
+ */
+//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+
+/**
+ * \def MBEDTLS_PLATFORM_XXX_ALT
+ *
+ * Uncomment a macro to let mbed TLS support the function in the platform
+ * abstraction layer.
+ *
+ * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will
+ * provide a function "mbedtls_platform_set_printf()" that allows you to set an
+ * alternative printf function pointer.
+ *
+ * All these define require MBEDTLS_PLATFORM_C to be defined!
+ *
+ * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows;
+ * it will be enabled automatically by check_config.h
+ *
+ * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as
+ * MBEDTLS_PLATFORM_XXX_MACRO!
+ *
+ * Uncomment a macro to enable alternate implementation of specific base
+ * platform function
+ */
+//#define MBEDTLS_PLATFORM_EXIT_ALT
+//#define MBEDTLS_PLATFORM_FPRINTF_ALT
+//#define MBEDTLS_PLATFORM_PRINTF_ALT
+//#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+
+/**
+ * \def MBEDTLS_DEPRECATED_WARNING
+ *
+ * Mark deprecated functions so that they generate a warning if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * This only works with GCC and Clang. With other compilers, you may want to
+ * use MBEDTLS_DEPRECATED_REMOVED
+ *
+ * Uncomment to get warnings on using deprecated functions.
+ */
+//#define MBEDTLS_DEPRECATED_WARNING
+
+/**
+ * \def MBEDTLS_DEPRECATED_REMOVED
+ *
+ * Remove deprecated functions so that they generate an error if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * Uncomment to get errors on using deprecated functions.
+ */
+//#define MBEDTLS_DEPRECATED_REMOVED
+
+/* \} name SECTION: System support */
+
+/**
+ * \name SECTION: mbed TLS feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_TIMING_ALT
+ *
+ * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(),
+ * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay()
+ *
+ * Only works if you have MBEDTLS_TIMING_C enabled.
+ *
+ * You will need to provide a header "timing_alt.h" and an implementation at
+ * compile time.
+ */
+//#define MBEDTLS_TIMING_ALT
+
+/**
+ * \def MBEDTLS__MODULE_NAME__ALT
+ *
+ * Uncomment a macro to let mbed TLS use your alternate core implementation of
+ * a symmetric crypto or hash module (e.g. platform specific assembly
+ * optimized implementations). Keep in mind that the function prototypes
+ * should remain the same.
+ *
+ * This replaces the whole module. If you only want to replace one of the
+ * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer
+ * provide the "struct mbedtls_aes_context" definition and omit the base function
+ * declarations and implementations. "aes_alt.h" will be included from
+ * "aes.h" to include the new function definitions.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * module.
+ */
+//#define MBEDTLS_AES_ALT
+//#define MBEDTLS_ARC4_ALT
+//#define MBEDTLS_BLOWFISH_ALT
+//#define MBEDTLS_CAMELLIA_ALT
+//#define MBEDTLS_DES_ALT
+//#define MBEDTLS_XTEA_ALT
+//#define MBEDTLS_MD2_ALT
+//#define MBEDTLS_MD4_ALT
+//#define MBEDTLS_MD5_ALT
+//#define MBEDTLS_RIPEMD160_ALT
+//#define MBEDTLS_SHA1_ALT
+//#define MBEDTLS_SHA256_ALT
+//#define MBEDTLS_SHA512_ALT
+
+/**
+ * \def MBEDTLS__FUNCTION_NAME__ALT
+ *
+ * Uncomment a macro to let mbed TLS use you alternate core implementation of
+ * symmetric crypto or hash function. Keep in mind that function prototypes
+ * should remain the same.
+ *
+ * This replaces only one function. The header file from mbed TLS is still
+ * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will
+ * no longer provide the mbedtls_sha1_process() function, but it will still provide
+ * the other function (using your mbedtls_sha1_process() function) and the definition
+ * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible
+ * with this definition.
+ *
+ * Note: if you use the AES_xxx_ALT macros, then is is recommended to also set
+ * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES
+ * tables.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * function.
+ */
+//#define MBEDTLS_MD2_PROCESS_ALT
+//#define MBEDTLS_MD4_PROCESS_ALT
+//#define MBEDTLS_MD5_PROCESS_ALT
+//#define MBEDTLS_RIPEMD160_PROCESS_ALT
+//#define MBEDTLS_SHA1_PROCESS_ALT
+//#define MBEDTLS_SHA256_PROCESS_ALT
+//#define MBEDTLS_SHA512_PROCESS_ALT
+//#define MBEDTLS_DES_SETKEY_ALT
+//#define MBEDTLS_DES_CRYPT_ECB_ALT
+//#define MBEDTLS_DES3_CRYPT_ECB_ALT
+//#define MBEDTLS_AES_SETKEY_ENC_ALT
+//#define MBEDTLS_AES_SETKEY_DEC_ALT
+//#define MBEDTLS_AES_ENCRYPT_ALT
+//#define MBEDTLS_AES_DECRYPT_ALT
+
+/**
+ * \def MBEDTLS_ENTROPY_HARDWARE_ALT
+ *
+ * Uncomment this macro to let mbed TLS use your own implementation of a
+ * hardware entropy collector.
+ *
+ * Your function must be called \c mbedtls_hardware_poll(), have the same
+ * prototype as declared in entropy_poll.h, and accept NULL as first argument.
+ *
+ * Uncomment to use your own hardware entropy collector.
+ */
+//#define MBEDTLS_ENTROPY_HARDWARE_ALT
+
+/**
+ * \def MBEDTLS_AES_ROM_TABLES
+ *
+ * Store the AES tables in ROM.
+ *
+ * Uncomment this macro to store the AES tables in ROM.
+ */
+//#define MBEDTLS_AES_ROM_TABLES
+
+/**
+ * \def MBEDTLS_CAMELLIA_SMALL_MEMORY
+ *
+ * Use less ROM for the Camellia implementation (saves about 768 bytes).
+ *
+ * Uncomment this macro to use less memory for Camellia.
+ */
+//#define MBEDTLS_CAMELLIA_SMALL_MEMORY
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CBC
+ *
+ * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CBC
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+//#define MBEDTLS_CIPHER_MODE_CFB
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CTR
+
+/**
+ * \def MBEDTLS_CIPHER_NULL_CIPHER
+ *
+ * Enable NULL cipher.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * encryption or channels without any security!
+ *
+ * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable
+ * the following ciphersuites:
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA
+ *      MBEDTLS_TLS_RSA_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_RSA_WITH_NULL_MD5
+ *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA
+ *      MBEDTLS_TLS_PSK_WITH_NULL_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_NULL_SHA
+ *
+ * Uncomment this macro to enable the NULL cipher and ciphersuites
+ */
+//#define MBEDTLS_CIPHER_NULL_CIPHER
+
+/**
+ * \def MBEDTLS_CIPHER_PADDING_XXX
+ *
+ * Uncomment or comment macros to add support for specific padding modes
+ * in the cipher layer with cipher modes that support padding (e.g. CBC)
+ *
+ * If you disable all padding modes, only full blocks can be used with CBC.
+ *
+ * Enable padding modes in the cipher layer.
+ */
+#define MBEDTLS_CIPHER_PADDING_PKCS7
+//#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
+//#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
+//#define MBEDTLS_CIPHER_PADDING_ZEROS
+
+/**
+ * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES
+ *
+ * Enable weak ciphersuites in SSL / TLS.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * channels with virtually no security at all!
+ *
+ * This enables the following ciphersuites:
+ *      MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA
+ *
+ * Uncomment this macro to enable weak ciphersuites
+ */
+//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES
+
+/**
+ * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES
+ *
+ * Remove RC4 ciphersuites by default in SSL / TLS.
+ * This flag removes the ciphersuites based on RC4 from the default list as
+ * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to
+ * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them
+ * explicitly.
+ *
+ * Uncomment this macro to remove RC4 ciphersuites by default.
+ */
+#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
+
+/**
+ * \def MBEDTLS_ECP_XXXX_ENABLED
+ *
+ * Enables specific curves within the Elliptic Curve module.
+ * By default all supported curves are enabled.
+ *
+ * Comment macros to disable the curve and functions for it
+ */
+//#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
+//#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+//#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+//#ifndef MBEDTLS_FREESCALE_LTC_PKHA /* PKHA suports only <=512 */
+//#define MBEDTLS_ECP_DP_SECP521R1_ENABLED 
+//#endif
+//#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
+//#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
+//#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
+//#define MBEDTLS_ECP_DP_BP256R1_ENABLED
+//#define MBEDTLS_ECP_DP_BP384R1_ENABLED
+//#define MBEDTLS_ECP_DP_BP512R1_ENABLED
+//#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
+
+/**
+ * \def MBEDTLS_ECP_NIST_OPTIM
+ *
+ * Enable specific 'modulo p' routines for each NIST prime.
+ * Depending on the prime and architecture, makes operations 4 to 8 times
+ * faster on the corresponding curve.
+ *
+ * Comment this macro to disable NIST curves optimisation.
+ */
+#define MBEDTLS_ECP_NIST_OPTIM
+
+/**
+ * \def MBEDTLS_ECDSA_DETERMINISTIC
+ *
+ * Enable deterministic ECDSA (RFC 6979).
+ * Standard ECDSA is "fragile" in the sense that lack of entropy when signing
+ * may result in a compromise of the long-term signing key. This is avoided by
+ * the deterministic variant.
+ *
+ * Requires: MBEDTLS_HMAC_DRBG_C
+ *
+ * Comment this macro to disable deterministic ECDSA.
+ */
+#define MBEDTLS_ECDSA_DETERMINISTIC
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+ *
+ * Enable the PSK based ciphersuite modes in SSL / TLS.
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_RC4_128_SHA
+ */
+//#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+ *
+ * Enable the DHE-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_DHM_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA
+ */
+//#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ *
+ * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA
+ */
+//#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+ *
+ * Enable the RSA-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
+ *           MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA
+ */
+//#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+ *
+ * Enable the RSA-only based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
+ *           MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_RSA_WITH_RC4_128_MD5
+ */
+//#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+ *
+ * Enable the DHE-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
+ *           MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ */
+//#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+ *
+ * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
+ *           MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ */
+//#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+ *
+ * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C,
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ */
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+ *
+ * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ */
+//#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+ *
+ * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ */
+//#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+
+/**
+ * \def MBEDTLS_PK_PARSE_EC_EXTENDED
+ *
+ * Enhance support for reading EC keys using variants of SEC1 not allowed by
+ * RFC 5915 and RFC 5480.
+ *
+ * Currently this means parsing the SpecifiedECDomain choice of EC
+ * parameters (only known groups are supported, not arbitrary domains, to
+ * avoid validation issues).
+ *
+ * Disable if you only need to support RFC 5915 + 5480 key formats.
+ */
+//#define MBEDTLS_PK_PARSE_EC_EXTENDED
+
+/**
+ * \def MBEDTLS_ERROR_STRERROR_DUMMY
+ *
+ * Enable a dummy error function to make use of mbedtls_strerror() in
+ * third party libraries easier when MBEDTLS_ERROR_C is disabled
+ * (no effect when MBEDTLS_ERROR_C is enabled).
+ *
+ * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're
+ * not using mbedtls_strerror() or error_strerror() in your application.
+ *
+ * Disable if you run into name conflicts and want to really remove the
+ * mbedtls_strerror()
+ */
+//#define MBEDTLS_ERROR_STRERROR_DUMMY
+
+/**
+ * \def MBEDTLS_GENPRIME
+ *
+ * Enable the prime-number generation code.
+ *
+ * Requires: MBEDTLS_BIGNUM_C
+ */
+//#define MBEDTLS_GENPRIME
+
+/**
+ * \def MBEDTLS_FS_IO
+ *
+ * Enable functions that use the filesystem.
+ */
+//#define MBEDTLS_FS_IO
+
+/**
+ * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ * Do not add default entropy sources. These are the platform specific,
+ * mbedtls_timing_hardclock and HAVEGE based poll functions.
+ *
+ * This is useful to have more control over the added entropy sources in an
+ * application.
+ *
+ * Uncomment this macro to prevent loading of default entropy functions.
+ */
+//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+
+/**
+ * \def MBEDTLS_NO_PLATFORM_ENTROPY
+ *
+ * Do not use built-in platform entropy functions.
+ * This is useful if your platform does not support
+ * standards like the /dev/urandom or Windows CryptoAPI.
+ *
+ * Uncomment this macro to disable the built-in platform entropy functions.
+ */
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+
+/**
+ * \def MBEDTLS_ENTROPY_FORCE_SHA256
+ *
+ * Force the entropy accumulator to use a SHA-256 accumulator instead of the
+ * default SHA-512 based one (if both are available).
+ *
+ * Requires: MBEDTLS_SHA256_C
+ *
+ * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option
+ * if you have performance concerns.
+ *
+ * This option is only useful if both MBEDTLS_SHA256_C and
+ * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used.
+ */
+//#define MBEDTLS_ENTROPY_FORCE_SHA256
+
+/**
+ * \def MBEDTLS_MEMORY_DEBUG
+ *
+ * Enable debugging of buffer allocator memory issues. Automatically prints
+ * (to stderr) all (fatal) messages on memory allocation issues. Enables
+ * function for 'debug output' of allocated memory.
+ *
+ * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *
+ * Uncomment this macro to let the buffer allocator print out error messages.
+ */
+//#define MBEDTLS_MEMORY_DEBUG
+
+/**
+ * \def MBEDTLS_MEMORY_BACKTRACE
+ *
+ * Include backtrace information with each allocated block.
+ *
+ * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *           GLIBC-compatible backtrace() an backtrace_symbols() support
+ *
+ * Uncomment this macro to include backtrace information
+ */
+//#define MBEDTLS_MEMORY_BACKTRACE
+
+/**
+ * \def MBEDTLS_PK_RSA_ALT_SUPPORT
+ *
+ * Support external private RSA keys (eg from a HSM) in the PK layer.
+ *
+ * Comment this macro to disable support for external private RSA keys.
+ */
+//#define MBEDTLS_PK_RSA_ALT_SUPPORT
+
+/**
+ * \def MBEDTLS_PKCS1_V15
+ *
+ * Enable support for PKCS#1 v1.5 encoding.
+ *
+ * Requires: MBEDTLS_RSA_C
+ *
+ * This enables support for PKCS#1 v1.5 operations.
+ */
+#define MBEDTLS_PKCS1_V15
+
+/**
+ * \def MBEDTLS_PKCS1_V21
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ *
+ * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C
+ *
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+#define MBEDTLS_PKCS1_V21
+
+/**
+ * \def MBEDTLS_RSA_NO_CRT
+ *
+ * Do not use the Chinese Remainder Theorem for the RSA private operation.
+ *
+ * Uncomment this macro to disable the use of CRT in RSA.
+ *
+ */
+//#define MBEDTLS_RSA_NO_CRT
+
+/**
+ * \def MBEDTLS_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+ */
+//#define MBEDTLS_SELF_TEST
+
+/**
+ * \def MBEDTLS_SHA256_SMALLER
+ *
+ * Enable an implementation of SHA-256 that has lower ROM footprint but also
+ * lower performance.
+ *
+ * The default implementation is meant to be a reasonnable compromise between
+ * performance and size. This version optimizes more aggressively for size at
+ * the expense of performance. Eg on Cortex-M4 it reduces the size of
+ * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
+ * 30%.
+ *
+ * Uncomment to enable the smaller implementation of SHA256.
+ */
+//#define MBEDTLS_SHA256_SMALLER
+
+/**
+ * \def MBEDTLS_SSL_AEAD_RANDOM_IV
+ *
+ * Generate a random IV rather than using the record sequence number as a
+ * nonce for ciphersuites using and AEAD algorithm (GCM or CCM).
+ *
+ * Using the sequence number is generally recommended.
+ *
+ * Uncomment this macro to always use random IVs with AEAD ciphersuites.
+ */
+//#define MBEDTLS_SSL_AEAD_RANDOM_IV
+
+/**
+ * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES
+ *
+ * Enable sending of alert messages in case of encountered errors as per RFC.
+ * If you choose not to send the alert messages, mbed TLS can still communicate
+ * with other servers, only debugging of failures is harder.
+ *
+ * The advantage of not sending alert messages, is that no information is given
+ * about reasons for failures thus preventing adversaries of gaining intel.
+ *
+ * Enable sending of all alert messages
+ */
+#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
+
+/**
+ * \def MBEDTLS_SSL_DEBUG_ALL
+ *
+ * Enable the debug messages in SSL module for all issues.
+ * Debug messages have been disabled in some places to prevent timing
+ * attacks due to (unbalanced) debugging function calls.
+ *
+ * If you need all error reporting you should enable this during debugging,
+ * but remove this for production servers that should log as well.
+ *
+ * Uncomment this macro to report all debug messages on errors introducing
+ * a timing side-channel.
+ *
+ */
+//#define MBEDTLS_SSL_DEBUG_ALL
+
+/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC
+ *
+ * Enable support for Encrypt-then-MAC, RFC 7366.
+ *
+ * This allows peers that both support it to use a more robust protection for
+ * ciphersuites using CBC, providing deep resistance against timing attacks
+ * on the padding or underlying cipher.
+ *
+ * This only affects CBC ciphersuites, and is useless if none is defined.
+ *
+ * Requires: MBEDTLS_SSL_PROTO_TLS1    or
+ *           MBEDTLS_SSL_PROTO_TLS1_1  or
+ *           MBEDTLS_SSL_PROTO_TLS1_2
+ *
+ * Comment this macro to disable support for Encrypt-then-MAC
+ */
+#define MBEDTLS_SSL_ENCRYPT_THEN_MAC
+
+/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+ *
+ * Enable support for Extended Master Secret, aka Session Hash
+ * (draft-ietf-tls-session-hash-02).
+ *
+ * This was introduced as "the proper fix" to the Triple Handshake familiy of
+ * attacks, but it is recommended to always use it (even if you disable
+ * renegotiation), since it actually fixes a more fundamental issue in the
+ * original SSL/TLS design, and has implications beyond Triple Handshake.
+ *
+ * Requires: MBEDTLS_SSL_PROTO_TLS1    or
+ *           MBEDTLS_SSL_PROTO_TLS1_1  or
+ *           MBEDTLS_SSL_PROTO_TLS1_2
+ *
+ * Comment this macro to disable support for Extended Master Secret.
+ */
+#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+
+/**
+ * \def MBEDTLS_SSL_FALLBACK_SCSV
+ *
+ * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00).
+ *
+ * For servers, it is recommended to always enable this, unless you support
+ * only one version of TLS, or know for sure that none of your clients
+ * implements a fallback strategy.
+ *
+ * For clients, you only need this if you're using a fallback strategy, which
+ * is not recommended in the first place, unless you absolutely need it to
+ * interoperate with buggy (version-intolerant) servers.
+ *
+ * Comment this macro to disable support for FALLBACK_SCSV
+ */
+//#define MBEDTLS_SSL_FALLBACK_SCSV
+
+/**
+ * \def MBEDTLS_SSL_HW_RECORD_ACCEL
+ *
+ * Enable hooking functions in SSL module for hardware acceleration of
+ * individual records.
+ *
+ * Uncomment this macro to enable hooking functions.
+ */
+//#define MBEDTLS_SSL_HW_RECORD_ACCEL
+
+/**
+ * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING
+ *
+ * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0.
+ *
+ * This is a countermeasure to the BEAST attack, which also minimizes the risk
+ * of interoperability issues compared to sending 0-length records.
+ *
+ * Comment this macro to disable 1/n-1 record splitting.
+ */
+//#define MBEDTLS_SSL_CBC_RECORD_SPLITTING
+
+/**
+ * \def MBEDTLS_SSL_RENEGOTIATION
+ *
+ * Disable support for TLS renegotiation.
+ *
+ * The two main uses of renegotiation are (1) refresh keys on long-lived
+ * connections and (2) client authentication after the initial handshake.
+ * If you don't need renegotiation, it's probably better to disable it, since
+ * it has been associated with security issues in the past and is easy to
+ * misuse/misunderstand.
+ *
+ * Comment this to disable support for renegotiation.
+ */
+#define MBEDTLS_SSL_RENEGOTIATION
+
+/**
+ * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+ *
+ * Enable support for receiving and parsing SSLv2 Client Hello messages for the
+ * SSL Server module (MBEDTLS_SSL_SRV_C).
+ *
+ * Uncomment this macro to enable support for SSLv2 Client Hello messages.
+ */
+//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+
+/**
+ * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+ *
+ * Pick the ciphersuite according to the client's preferences rather than ours
+ * in the SSL Server module (MBEDTLS_SSL_SRV_C).
+ *
+ * Uncomment this macro to respect client's ciphersuite order
+ */
+//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+
+/**
+ * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+ *
+ * Enable support for RFC 6066 max_fragment_length extension in SSL.
+ *
+ * Comment this macro to disable support for the max_fragment_length extension
+ */
+#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+
+/**
+ * \def MBEDTLS_SSL_PROTO_SSL3
+ *
+ * Enable support for SSL 3.0.
+ *
+ * Requires: MBEDTLS_MD5_C
+ *           MBEDTLS_SHA1_C
+ *
+ * Comment this macro to disable support for SSL 3.0
+ */
+//#define MBEDTLS_SSL_PROTO_SSL3
+
+/**
+ * \def MBEDTLS_SSL_PROTO_TLS1
+ *
+ * Enable support for TLS 1.0.
+ *
+ * Requires: MBEDTLS_MD5_C
+ *           MBEDTLS_SHA1_C
+ *
+ * Comment this macro to disable support for TLS 1.0
+ */
+//#define MBEDTLS_SSL_PROTO_TLS1
+
+/**
+ * \def MBEDTLS_SSL_PROTO_TLS1_1
+ *
+ * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled).
+ *
+ * Requires: MBEDTLS_MD5_C
+ *           MBEDTLS_SHA1_C
+ *
+ * Comment this macro to disable support for TLS 1.1 / DTLS 1.0
+ */
+//#define MBEDTLS_SSL_PROTO_TLS1_1
+
+/**
+ * \def MBEDTLS_SSL_PROTO_TLS1_2
+ *
+ * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled).
+ *
+ * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C
+ *           (Depends on ciphersuites)
+ *
+ * Comment this macro to disable support for TLS 1.2 / DTLS 1.2
+ */
+#define MBEDTLS_SSL_PROTO_TLS1_2
+
+/**
+ * \def MBEDTLS_SSL_PROTO_DTLS
+ *
+ * Enable support for DTLS (all available versions).
+ *
+ * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0,
+ * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2.
+ *
+ * Requires: MBEDTLS_SSL_PROTO_TLS1_1
+ *        or MBEDTLS_SSL_PROTO_TLS1_2
+ *
+ * Comment this macro to disable support for DTLS
+ */
+#define MBEDTLS_SSL_PROTO_DTLS
+
+/**
+ * \def MBEDTLS_SSL_ALPN
+ *
+ * Enable support for RFC 7301 Application Layer Protocol Negotiation.
+ *
+ * Comment this macro to disable support for ALPN.
+ */
+#define MBEDTLS_SSL_ALPN
+
+/**
+ * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY
+ *
+ * Enable support for the anti-replay mechanism in DTLS.
+ *
+ * Requires: MBEDTLS_SSL_TLS_C
+ *           MBEDTLS_SSL_PROTO_DTLS
+ *
+ * \warning Disabling this is often a security risk!
+ * See mbedtls_ssl_conf_dtls_anti_replay() for details.
+ *
+ * Comment this to disable anti-replay in DTLS.
+ */
+#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+
+/**
+ * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY
+ *
+ * Enable support for HelloVerifyRequest on DTLS servers.
+ *
+ * This feature is highly recommended to prevent DTLS servers being used as
+ * amplifiers in DoS attacks against other hosts. It should always be enabled
+ * unless you know for sure amplification cannot be a problem in the
+ * environment in which your server operates.
+ *
+ * \warning Disabling this can ba a security risk! (see above)
+ *
+ * Requires: MBEDTLS_SSL_PROTO_DTLS
+ *
+ * Comment this to disable support for HelloVerifyRequest.
+ */
+#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+
+/**
+ * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
+ *
+ * Enable server-side support for clients that reconnect from the same port.
+ *
+ * Some clients unexpectedly close the connection and try to reconnect using the
+ * same source port. This needs special support from the server to handle the
+ * new connection securely, as described in section 4.2.8 of RFC 6347. This
+ * flag enables that support.
+ *
+ * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY
+ *
+ * Comment this to disable support for clients reusing the source port.
+ */
+#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
+
+/**
+ * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT
+ *
+ * Enable support for a limit of records with bad MAC.
+ *
+ * See mbedtls_ssl_conf_dtls_badmac_limit().
+ *
+ * Requires: MBEDTLS_SSL_PROTO_DTLS
+ */
+#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT
+
+/**
+ * \def MBEDTLS_SSL_SESSION_TICKETS
+ *
+ * Enable support for RFC 5077 session tickets in SSL.
+ * Client-side, provides full support for session tickets (maintainance of a
+ * session store remains the responsibility of the application, though).
+ * Server-side, you also need to provide callbacks for writing and parsing
+ * tickets, including authenticated encryption and key management. Example
+ * callbacks are provided by MBEDTLS_SSL_TICKET_C.
+ *
+ * Comment this macro to disable support for SSL session tickets
+ */
+#define MBEDTLS_SSL_SESSION_TICKETS
+
+/**
+ * \def MBEDTLS_SSL_SERVER_NAME_INDICATION
+ *
+ * Enable support for RFC 6066 server name indication (SNI) in SSL.
+ *
+ * Requires: MBEDTLS_X509_CRT_PARSE_C
+ *
+ * Comment this macro to disable support for server name indication in SSL
+ */
+#define MBEDTLS_SSL_SERVER_NAME_INDICATION
+/**
+ * \def MBEDTLS_SSL_TRUNCATED_HMAC
+ *
+ * Enable support for RFC 6066 truncated HMAC in SSL.
+ *
+ * Comment this macro to disable support for truncated HMAC in SSL
+ */
+//#define MBEDTLS_SSL_TRUNCATED_HMAC
+
+/**
+ * \def MBEDTLS_THREADING_ALT
+ *
+ * Provide your own alternate threading implementation.
+ *
+ * Requires: MBEDTLS_THREADING_C
+ *
+ * Uncomment this to allow your own alternate threading implementation.
+ */
+//#define MBEDTLS_THREADING_ALT
+
+/**
+ * \def MBEDTLS_THREADING_PTHREAD
+ *
+ * Enable the pthread wrapper layer for the threading layer.
+ *
+ * Requires: MBEDTLS_THREADING_C
+ *
+ * Uncomment this to enable pthread mutexes.
+ */
+//#define MBEDTLS_THREADING_PTHREAD
+
+/**
+ * \def MBEDTLS_VERSION_FEATURES
+ *
+ * Allow run-time checking of compile-time enabled features. Thus allowing users
+ * to check at run-time if the library is for instance compiled with threading
+ * support via mbedtls_version_check_feature().
+ *
+ * Requires: MBEDTLS_VERSION_C
+ *
+ * Comment this to disable run-time checking and save ROM space
+ */
+//#define MBEDTLS_VERSION_FEATURES
+
+/**
+ * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an extension in a v1 or v2 certificate.
+ *
+ * Uncomment to prevent an error.
+ */
+//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
+
+/**
+ * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an unknown critical extension.
+ *
+ * Uncomment to prevent an error.
+ */
+//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+
+/**
+ * \def MBEDTLS_X509_CHECK_KEY_USAGE
+ *
+ * Enable verification of the keyUsage extension (CA and leaf certificates).
+ *
+ * Disabling this avoids problems with mis-issued and/or misused
+ * (intermediate) CA and leaf certificates.
+ *
+ * \warning Depending on your PKI use, disabling this can be a security risk!
+ *
+ * Comment to skip keyUsage checking for both CA and leaf certificates.
+ */
+#define MBEDTLS_X509_CHECK_KEY_USAGE
+
+/**
+ * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+ *
+ * Enable verification of the extendedKeyUsage extension (leaf certificates).
+ *
+ * Disabling this avoids problems with mis-issued and/or misused certificates.
+ *
+ * \warning Depending on your PKI use, disabling this can be a security risk!
+ *
+ * Comment to skip extendedKeyUsage checking for certificates.
+ */
+#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+
+/**
+ * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT
+ *
+ * Enable parsing and verification of X.509 certificates, CRLs and CSRS
+ * signed with RSASSA-PSS (aka PKCS#1 v2.1).
+ *
+ * Comment this macro to disallow using RSASSA-PSS in certificates.
+ */
+//#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
+/**
+ * \def MBEDTLS_ZLIB_SUPPORT
+ *
+ * If set, the SSL/TLS module uses ZLIB to support compression and
+ * decompression of packet data.
+ *
+ * \warning TLS-level compression MAY REDUCE SECURITY! See for example the
+ * CRIME attack. Before enabling this option, you should examine with care if
+ * CRIME or similar exploits may be a applicable to your use case.
+ *
+ * \note Currently compression can't be used with DTLS.
+ *
+ * Used in: library/ssl_tls.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This feature requires zlib library and headers to be present.
+ *
+ * Uncomment to enable use of ZLIB
+ */
+//#define MBEDTLS_ZLIB_SUPPORT
+/* \} name SECTION: mbed TLS feature support */
+
+/**
+ * \name SECTION: mbed TLS modules
+ *
+ * This section enables or disables entire modules in mbed TLS
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_AESNI_C
+ *
+ * Enable AES-NI support on x86-64.
+ *
+ * Module:  library/aesni.c
+ * Caller:  library/aes.c
+ *
+ * Requires: MBEDTLS_HAVE_ASM
+ *
+ * This modules adds support for the AES-NI instructions on x86-64
+ */
+//#define MBEDTLS_AESNI_C
+
+/**
+ * \def MBEDTLS_AES_C
+ *
+ * Enable the AES block cipher.
+ *
+ * Module:  library/aes.c
+ * Caller:  library/ssl_tls.c
+ *          library/pem.c
+ *          library/ctr_drbg.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA
+ *
+ * PEM_PARSE uses AES for decrypting encrypted keys.
+ */
+#define MBEDTLS_AES_C
+
+/**
+ * \def MBEDTLS_ARC4_C
+ *
+ * Enable the ARCFOUR stream cipher.
+ *
+ * Module:  library/arc4.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_RSA_WITH_RC4_128_MD5
+ *      MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_PSK_WITH_RC4_128_SHA
+ */
+//#define MBEDTLS_ARC4_C
+
+/**
+ * \def MBEDTLS_ASN1_PARSE_C
+ *
+ * Enable the generic ASN1 parser.
+ *
+ * Module:  library/asn1.c
+ * Caller:  library/x509.c
+ *          library/dhm.c
+ *          library/pkcs12.c
+ *          library/pkcs5.c
+ *          library/pkparse.c
+ */
+#define MBEDTLS_ASN1_PARSE_C
+
+/**
+ * \def MBEDTLS_ASN1_WRITE_C
+ *
+ * Enable the generic ASN1 writer.
+ *
+ * Module:  library/asn1write.c
+ * Caller:  library/ecdsa.c
+ *          library/pkwrite.c
+ *          library/x509_create.c
+ *          library/x509write_crt.c
+ *          library/mbedtls_x509write_csr.c
+ */
+#define MBEDTLS_ASN1_WRITE_C
+
+/**
+ * \def MBEDTLS_BASE64_C
+ *
+ * Enable the Base64 module.
+ *
+ * Module:  library/base64.c
+ * Caller:  library/pem.c
+ *
+ * This module is required for PEM support (required by X.509).
+ */
+// needed for Base64 encoding Opaque data for
+// registration payload, adds 500 bytes to flash.
+#define MBEDTLS_BASE64_C
+
+/**
+ * \def MBEDTLS_BIGNUM_C
+ *
+ * Enable the multi-precision integer library.
+ *
+ * Module:  library/bignum.c
+ * Caller:  library/dhm.c
+ *          library/ecp.c
+ *          library/ecdsa.c
+ *          library/rsa.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support.
+ */
+#define MBEDTLS_BIGNUM_C
+
+/**
+ * \def MBEDTLS_BLOWFISH_C
+ *
+ * Enable the Blowfish block cipher.
+ *
+ * Module:  library/blowfish.c
+ */
+//#define MBEDTLS_BLOWFISH_C
+
+/**
+ * \def MBEDTLS_CAMELLIA_C
+ *
+ * Enable the Camellia block cipher.
+ *
+ * Module:  library/camellia.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ */
+//#define MBEDTLS_CAMELLIA_C
+
+/**
+ * \def MBEDTLS_CCM_C
+ *
+ * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher.
+ *
+ * Module:  library/ccm.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C
+ *
+ * This module enables the AES-CCM ciphersuites, if other requisites are
+ * enabled as well.
+ */
+#define MBEDTLS_CCM_C
+
+/**
+ * \def MBEDTLS_CERTS_C
+ *
+ * Enable the test certificates.
+ *
+ * Module:  library/certs.c
+ * Caller:
+ *
+ * This module is used for testing (ssl_client/server).
+ */
+//#define MBEDTLS_CERTS_C
+
+/**
+ * \def MBEDTLS_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module:  library/cipher.c
+ * Caller:  library/ssl_tls.c
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define MBEDTLS_CIPHER_C
+
+/**
+ * \def MBEDTLS_CMAC_C
+ *
+ * Enable the CMAC (Cipher-based Message Authentication Code) mode for block
+ * ciphers.
+ *
+ * Module:  library/cmac.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C
+ *
+ */
+#define MBEDTLS_CMAC_C
+
+/**
+ * \def MBEDTLS_CTR_DRBG_C
+ *
+ * Enable the CTR_DRBG AES-256-based random generator.
+ *
+ * Module:  library/ctr_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_AES_C
+ *
+ * This module provides the CTR_DRBG AES-256 random number generator.
+ */
+#define MBEDTLS_CTR_DRBG_C
+
+/**
+ * \def MBEDTLS_DEBUG_C
+ *
+ * Enable the debug functions.
+ *
+ * Module:  library/debug.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module provides debugging functions.
+ */
+//#define MBEDTLS_DEBUG_C
+
+/**
+ * \def MBEDTLS_DES_C
+ *
+ * Enable the DES block cipher.
+ *
+ * Module:  library/des.c
+ * Caller:  library/pem.c
+ *          library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA
+ *
+ * PEM_PARSE uses DES/3DES for decrypting encrypted keys.
+ */
+//#define MBEDTLS_DES_C
+
+/**
+ * \def MBEDTLS_DHM_C
+ *
+ * Enable the Diffie-Hellman-Merkle module.
+ *
+ * Module:  library/dhm.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module is used by the following key exchanges:
+ *      DHE-RSA, DHE-PSK
+ */
+//#define MBEDTLS_DHM_C
+
+/**
+ * \def MBEDTLS_ECDH_C
+ *
+ * Enable the elliptic curve Diffie-Hellman library.
+ *
+ * Module:  library/ecdh.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module is used by the following key exchanges:
+ *      ECDHE-ECDSA, ECDHE-RSA, DHE-PSK
+ *
+ * Requires: MBEDTLS_ECP_C
+ */
+#define MBEDTLS_ECDH_C
+
+/**
+ * \def MBEDTLS_ECDSA_C
+ *
+ * Enable the elliptic curve DSA library.
+ *
+ * Module:  library/ecdsa.c
+ * Caller:
+ *
+ * This module is used by the following key exchanges:
+ *      ECDHE-ECDSA
+ *
+ * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C
+ */
+#define MBEDTLS_ECDSA_C
+
+/**
+ * \def MBEDTLS_ECP_C
+ *
+ * Enable the elliptic curve over GF(p) library.
+ *
+ * Module:  library/ecp.c
+ * Caller:  library/ecdh.c
+ *          library/ecdsa.c
+ *
+ * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED
+ */
+#define MBEDTLS_ECP_C
+
+/**
+ * \def MBEDTLS_ENTROPY_C
+ *
+ * Enable the platform-specific entropy code.
+ *
+ * Module:  library/entropy.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C
+ *
+ * This module provides a generic entropy pool
+ */
+#define MBEDTLS_ENTROPY_C
+
+/**
+ * \def MBEDTLS_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module:  library/error.c
+ * Caller:
+ *
+ * This module enables mbedtls_strerror().
+ */
+//#define MBEDTLS_ERROR_C
+
+/**
+ * \def MBEDTLS_GCM_C
+ *
+ * Enable the Galois/Counter Mode (GCM) for AES.
+ *
+ * Module:  library/gcm.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C
+ *
+ * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other
+ * requisites are enabled as well.
+ */
+#define MBEDTLS_GCM_C
+
+/**
+ * \def MBEDTLS_HAVEGE_C
+ *
+ * Enable the HAVEGE random generator.
+ *
+ * Warning: the HAVEGE random generator is not suitable for virtualized
+ *          environments
+ *
+ * Warning: the HAVEGE random generator is dependent on timing and specific
+ *          processor traits. It is therefore not advised to use HAVEGE as
+ *          your applications primary random generator or primary entropy pool
+ *          input. As a secondary input to your entropy pool, it IS able add
+ *          the (limited) extra entropy it provides.
+ *
+ * Module:  library/havege.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_TIMING_C
+ *
+ * Uncomment to enable the HAVEGE random generator.
+ */
+//#define MBEDTLS_HAVEGE_C
+
+/**
+ * \def MBEDTLS_HMAC_DRBG_C
+ *
+ * Enable the HMAC_DRBG random generator.
+ *
+ * Module:  library/hmac_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * Uncomment to enable the HMAC_DRBG random number geerator.
+ */
+#define MBEDTLS_HMAC_DRBG_C
+
+/**
+ * \def MBEDTLS_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module:  library/mbedtls_md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+#define MBEDTLS_MD_C
+
+/**
+ * \def MBEDTLS_MD2_C
+ *
+ * Enable the MD2 hash algorithm.
+ *
+ * Module:  library/mbedtls_md2.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ */
+//#define MBEDTLS_MD2_C
+
+/**
+ * \def MBEDTLS_MD4_C
+ *
+ * Enable the MD4 hash algorithm.
+ *
+ * Module:  library/mbedtls_md4.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ */
+//#define MBEDTLS_MD4_C
+
+/**
+ * \def MBEDTLS_MD5_C
+ *
+ * Enable the MD5 hash algorithm.
+ *
+ * Module:  library/mbedtls_md5.c
+ * Caller:  library/mbedtls_md.c
+ *          library/pem.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for SSL/TLS and X.509.
+ * PEM_PARSE uses MD5 for decrypting encrypted keys.
+ */
+//#define MBEDTLS_MD5_C
+
+/**
+ * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *
+ * Enable the buffer allocator implementation that makes use of a (stack)
+ * based buffer to 'allocate' dynamic memory. (replaces calloc() and free()
+ * calls)
+ *
+ * Module:  library/memory_buffer_alloc.c
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *           MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS)
+ *
+ * Enable this module to enable the buffer memory allocator.
+ */
+//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
+
+/**
+ * \def MBEDTLS_NET_C
+ *
+ * Enable the TCP/IP networking routines.
+ *
+ * Module:  library/net.c
+ *
+ * This module provides TCP/IP networking routines.
+ */
+//#define MBEDTLS_NET_C
+
+/**
+ * \def MBEDTLS_OID_C
+ *
+ * Enable the OID database.
+ *
+ * Module:  library/oid.c
+ * Caller:  library/asn1write.c
+ *          library/pkcs5.c
+ *          library/pkparse.c
+ *          library/pkwrite.c
+ *          library/rsa.c
+ *          library/x509.c
+ *          library/x509_create.c
+ *          library/mbedtls_x509_crl.c
+ *          library/mbedtls_x509_crt.c
+ *          library/mbedtls_x509_csr.c
+ *          library/x509write_crt.c
+ *          library/mbedtls_x509write_csr.c
+ *
+ * This modules translates between OIDs and internal values.
+ */
+#define MBEDTLS_OID_C
+
+/**
+ * \def MBEDTLS_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module:  library/padlock.c
+ * Caller:  library/aes.c
+ *
+ * Requires: MBEDTLS_HAVE_ASM
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+//#define MBEDTLS_PADLOCK_C
+
+/**
+ * \def MBEDTLS_PEM_PARSE_C
+ *
+ * Enable PEM decoding / parsing.
+ *
+ * Module:  library/pem.c
+ * Caller:  library/dhm.c
+ *          library/pkparse.c
+ *          library/mbedtls_x509_crl.c
+ *          library/mbedtls_x509_crt.c
+ *          library/mbedtls_x509_csr.c
+ *
+ * Requires: MBEDTLS_BASE64_C
+ *
+ * This modules adds support for decoding / parsing PEM files.
+ */
+//#define MBEDTLS_PEM_PARSE_C
+
+/**
+ * \def MBEDTLS_PEM_WRITE_C
+ *
+ * Enable PEM encoding / writing.
+ *
+ * Module:  library/pem.c
+ * Caller:  library/pkwrite.c
+ *          library/x509write_crt.c
+ *          library/mbedtls_x509write_csr.c
+ *
+ * Requires: MBEDTLS_BASE64_C
+ *
+ * This modules adds support for encoding / writing PEM files.
+ */
+//#define MBEDTLS_PEM_WRITE_C
+
+/**
+ * \def MBEDTLS_PK_C
+ *
+ * Enable the generic public (asymetric) key layer.
+ *
+ * Module:  library/pk.c
+ * Caller:  library/ssl_tls.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C
+ *
+ * Uncomment to enable generic public key wrappers.
+ */
+#define MBEDTLS_PK_C
+
+/**
+ * \def MBEDTLS_PK_PARSE_C
+ *
+ * Enable the generic public (asymetric) key parser.
+ *
+ * Module:  library/pkparse.c
+ * Caller:  library/mbedtls_x509_crt.c
+ *          library/mbedtls_x509_csr.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * Uncomment to enable generic public key parse functions.
+ */
+#define MBEDTLS_PK_PARSE_C
+
+/**
+ * \def MBEDTLS_PK_WRITE_C
+ *
+ * Enable the generic public (asymetric) key writer.
+ *
+ * Module:  library/pkwrite.c
+ * Caller:  library/x509write.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * Uncomment to enable generic public key write functions.
+ */
+#define MBEDTLS_PK_WRITE_C
+
+/**
+ * \def MBEDTLS_PKCS5_C
+ *
+ * Enable PKCS#5 functions.
+ *
+ * Module:  library/pkcs5.c
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * This module adds support for the PKCS#5 functions.
+ */
+//#define MBEDTLS_PKCS5_C
+
+/**
+ * \def MBEDTLS_PKCS11_C
+ *
+ * Enable wrapper for PKCS#11 smartcard support.
+ *
+ * Module:  library/pkcs11.c
+ * Caller:  library/pk.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * This module enables SSL/TLS PKCS #11 smartcard support.
+ * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
+ */
+//#define MBEDTLS_PKCS11_C
+
+/**
+ * \def MBEDTLS_PKCS12_C
+ *
+ * Enable PKCS#12 PBE functions.
+ * Adds algorithms for parsing PKCS#8 encrypted private keys
+ *
+ * Module:  library/pkcs12.c
+ * Caller:  library/pkparse.c
+ *
+ * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C
+ * Can use:  MBEDTLS_ARC4_C
+ *
+ * This module enables PKCS#12 functions.
+ */
+//#define MBEDTLS_PKCS12_C
+
+/**
+ * \def MBEDTLS_PLATFORM_C
+ *
+ * Enable the platform abstraction layer that allows you to re-assign
+ * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit().
+ *
+ * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT
+ * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned
+ * above to be specified at runtime or compile time respectively.
+ *
+ * \note This abstraction layer must be enabled on Windows (including MSYS2)
+ * as other module rely on it for a fixed snprintf implementation.
+ *
+ * Module:  library/platform.c
+ * Caller:  Most other .c files
+ *
+ * This module enables abstraction of common (libc) functions.
+ */
+#define MBEDTLS_PLATFORM_C
+
+/**
+ * \def MBEDTLS_RIPEMD160_C
+ *
+ * Enable the RIPEMD-160 hash algorithm.
+ *
+ * Module:  library/mbedtls_ripemd160.c
+ * Caller:  library/mbedtls_md.c
+ *
+ */
+//#define MBEDTLS_RIPEMD160_C
+
+/**
+ * \def MBEDTLS_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module:  library/rsa.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509.c
+ *
+ * This module is used by the following key exchanges:
+ *      RSA, DHE-RSA, ECDHE-RSA, RSA-PSK
+ *
+ * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C
+ */
+//#define MBEDTLS_RSA_C
+
+/**
+ * \def MBEDTLS_SHA1_C
+ *
+ * Enable the SHA1 cryptographic hash algorithm.
+ *
+ * Module:  library/mbedtls_sha1.c
+ * Caller:  library/mbedtls_md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509write_crt.c
+ *
+ * This module is required for SSL/TLS and SHA1-signed certificates.
+ */
+//#define MBEDTLS_SHA1_C
+
+/**
+ * \def MBEDTLS_SHA256_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ *
+ * Module:  library/mbedtls_sha256.c
+ * Caller:  library/entropy.c
+ *          library/mbedtls_md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ * This module is required for the SSL/TLS 1.2 PRF function.
+ */
+#define MBEDTLS_SHA256_C
+
+/**
+ * \def MBEDTLS_SHA512_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ *
+ * Module:  library/mbedtls_sha512.c
+ * Caller:  library/entropy.c
+ *          library/mbedtls_md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+//#define MBEDTLS_SHA512_C
+
+/**
+ * \def MBEDTLS_SSL_CACHE_C
+ *
+ * Enable simple SSL cache implementation.
+ *
+ * Module:  library/ssl_cache.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SSL_CACHE_C
+ */
+#define MBEDTLS_SSL_CACHE_C
+
+/**
+ * \def MBEDTLS_SSL_COOKIE_C
+ *
+ * Enable basic implementation of DTLS cookies for hello verification.
+ *
+ * Module:  library/ssl_cookie.c
+ * Caller:
+ */
+#define MBEDTLS_SSL_COOKIE_C
+
+/**
+ * \def MBEDTLS_SSL_TICKET_C
+ *
+ * Enable an implementation of TLS server-side callbacks for session tickets.
+ *
+ * Module:  library/ssl_ticket.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_CIPHER_C
+ */
+#define MBEDTLS_SSL_TICKET_C
+
+/**
+ * \def MBEDTLS_SSL_CLI_C
+ *
+ * Enable the SSL/TLS client code.
+ *
+ * Module:  library/ssl_cli.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS client support.
+ */
+#define MBEDTLS_SSL_CLI_C
+
+/**
+ * \def MBEDTLS_SSL_SRV_C
+ *
+ * Enable the SSL/TLS server code.
+ *
+ * Module:  library/ssl_srv.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS server support.
+ */
+//#define MBEDTLS_SSL_SRV_C
+
+/**
+ * \def MBEDTLS_SSL_TLS_C
+ *
+ * Enable the generic SSL/TLS code.
+ *
+ * Module:  library/ssl_tls.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C
+ *           and at least one of the MBEDTLS_SSL_PROTO_XXX defines
+ *
+ * This module is required for SSL/TLS.
+ */
+#define MBEDTLS_SSL_TLS_C
+
+/**
+ * \def MBEDTLS_THREADING_C
+ *
+ * Enable the threading abstraction layer.
+ * By default mbed TLS assumes it is used in a non-threaded environment or that
+ * contexts are not shared between threads. If you do intend to use contexts
+ * between threads, you will need to enable this layer to prevent race
+ * conditions.
+ *
+ * Module:  library/threading.c
+ *
+ * This allows different threading implementations (self-implemented or
+ * provided).
+ *
+ * You will have to enable either MBEDTLS_THREADING_ALT or
+ * MBEDTLS_THREADING_PTHREAD.
+ *
+ * Enable this layer to allow use of mutexes within mbed TLS
+ */
+//#define MBEDTLS_THREADING_C
+
+/**
+ * \def MBEDTLS_TIMING_C
+ *
+ * Enable the portable timing interface.
+ *
+ * Module:  library/timing.c
+ * Caller:  library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+//#define MBEDTLS_TIMING_C
+
+/**
+ * \def MBEDTLS_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module:  library/version.c
+ *
+ * This module provides run-time version information.
+ */
+#define MBEDTLS_VERSION_C
+
+/**
+ * \def MBEDTLS_X509_USE_C
+ *
+ * Enable X.509 core for using certificates.
+ *
+ * Module:  library/x509.c
+ * Caller:  library/mbedtls_x509_crl.c
+ *          library/mbedtls_x509_crt.c
+ *          library/mbedtls_x509_csr.c
+ *
+ * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C,
+ *           MBEDTLS_PK_PARSE_C
+ *
+ * This module is required for the X.509 parsing modules.
+ */
+#define MBEDTLS_X509_USE_C
+
+/**
+ * \def MBEDTLS_X509_CRT_PARSE_C
+ *
+ * Enable X.509 certificate parsing.
+ *
+ * Module:  library/mbedtls_x509_crt.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * Requires: MBEDTLS_X509_USE_C
+ *
+ * This module is required for X.509 certificate parsing.
+ */
+
+#define MBEDTLS_X509_CRT_PARSE_C
+
+/**
+ * \def MBEDTLS_X509_CRL_PARSE_C
+ *
+ * Enable X.509 CRL parsing.
+ *
+ * Module:  library/mbedtls_x509_crl.c
+ * Caller:  library/mbedtls_x509_crt.c
+ *
+ * Requires: MBEDTLS_X509_USE_C
+ *
+ * This module is required for X.509 CRL parsing.
+ */
+#define MBEDTLS_X509_CRL_PARSE_C
+
+/**
+ * \def MBEDTLS_X509_CSR_PARSE_C
+ *
+ * Enable X.509 Certificate Signing Request (CSR) parsing.
+ *
+ * Module:  library/mbedtls_x509_csr.c
+ * Caller:  library/x509_crt_write.c
+ *
+ * Requires: MBEDTLS_X509_USE_C
+ *
+ * This module is used for reading X.509 certificate request.
+ */
+#define MBEDTLS_X509_CSR_PARSE_C
+
+/**
+ * \def MBEDTLS_X509_CREATE_C
+ *
+ * Enable X.509 core for creating certificates.
+ *
+ * Module:  library/x509_create.c
+ *
+ * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C
+ *
+ * This module is the basis for creating X.509 certificates and CSRs.
+ */
+#define MBEDTLS_X509_CREATE_C
+
+/**
+ * \def MBEDTLS_X509_CRT_WRITE_C
+ *
+ * Enable creating X.509 certificates.
+ *
+ * Module:  library/x509_crt_write.c
+ *
+ * Requires: MBEDTLS_X509_CREATE_C
+ *
+ * This module is required for X.509 certificate creation.
+ */
+//#define MBEDTLS_X509_CRT_WRITE_C
+
+/**
+ * \def MBEDTLS_X509_CSR_WRITE_C
+ *
+ * Enable creating X.509 Certificate Signing Requests (CSR).
+ *
+ * Module:  library/x509_csr_write.c
+ *
+ * Requires: MBEDTLS_X509_CREATE_C
+ *
+ * This module is required for X.509 certificate request writing.
+ */
+#define MBEDTLS_X509_CSR_WRITE_C
+/**
+ * \def MBEDTLS_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module:  library/xtea.c
+ * Caller:
+ */
+//#define MBEDTLS_XTEA_C
+
+/* \} name SECTION: mbed TLS modules */
+
+/**
+ * \name SECTION: Module configuration options
+ *
+ * This section allows for the setting of module specific sizes and
+ * configuration options. The default values are already present in the
+ * relevant header files and should suffice for the regular use cases.
+ *
+ * Our advice is to enable options and change their values here
+ * only if you have a good reason and know the consequences.
+ *
+ * Please check the respective header file for documentation on these
+ * parameters (to prevent duplicate documentation).
+ * \{
+ */
+
+/* MPI / BIGNUM options */
+//#define MBEDTLS_MPI_WINDOW_SIZE            6 /**< Maximum windows size used. */
+//#define MBEDTLS_MPI_MAX_SIZE            1024 /**< Maximum number of bytes for usable MPIs. */
+
+/* CTR_DRBG options */
+//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN               48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL        10000 /**< Interval before reseed is performed by default */
+//#define MBEDTLS_CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */
+//#define MBEDTLS_CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */
+//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT           384 /**< Maximum size of (re)seed buffer */
+
+/* HMAC_DRBG options */
+//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL   10000 /**< Interval before reseed is performed by default */
+//#define MBEDTLS_HMAC_DRBG_MAX_INPUT           256 /**< Maximum number of additional input bytes */
+//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST        1024 /**< Maximum number of requested bytes per call */
+//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT      384 /**< Maximum size of (re)seed buffer */
+
+/* ECP options */
+//#define MBEDTLS_ECP_MAX_BITS             521 /**< Maximum bit size of groups */
+//#define MBEDTLS_ECP_WINDOW_SIZE            6 /**< Maximum window size used */
+//#define MBEDTLS_ECP_FIXED_POINT_OPTIM      1 /**< Enable fixed-point speed-up */
+
+/* Entropy options */
+//#define MBEDTLS_ENTROPY_MAX_SOURCES                20 /**< Maximum number of sources supported */
+//#define MBEDTLS_ENTROPY_MAX_GATHER                128 /**< Maximum amount requested from entropy sources */
+
+/* Memory buffer allocator options */
+//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE      4 /**< Align on multiples of this value */
+
+/* Platform options */
+//#define MBEDTLS_PLATFORM_STD_MEM_HDR   <stdlib.h> /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
+//#define MBEDTLS_PLATFORM_STD_CALLOC        calloc /**< Default allocator to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_FREE            free /**< Default free to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_EXIT            exit /**< Default exit to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_FPRINTF      fprintf /**< Default fprintf to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_PRINTF        printf /**< Default printf to use, can be undefined */
+/* Note: your snprintf must correclty zero-terminate the buffer! */
+//#define MBEDTLS_PLATFORM_STD_SNPRINTF    snprintf /**< Default snprintf to use, can be undefined */
+
+/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */
+/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */
+//#define MBEDTLS_PLATFORM_CALLOC_MACRO        calloc /**< Default allocator macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_FREE_MACRO            free /**< Default free macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_EXIT_MACRO            exit /**< Default exit macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_FPRINTF_MACRO      fprintf /**< Default fprintf macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_PRINTF_MACRO        printf /**< Default printf macro to use, can be undefined */
+/* Note: your snprintf must correclty zero-terminate the buffer! */
+//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO    snprintf /**< Default snprintf macro to use, can be undefined */
+
+/* SSL Cache options */
+//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT       86400 /**< 1 day  */
+//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES      50 /**< Maximum entries in cache */
+
+/* SSL options */
+
+#define MBEDTLS_SSL_MAX_CONTENT_LEN 4096
+
+//#define MBEDTLS_SSL_MAX_CONTENT_LEN             16384 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */
+//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME     86400 /**< Lifetime of session tickets (if enabled) */
+//#define MBEDTLS_PSK_MAX_LEN               32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
+//#define MBEDTLS_SSL_COOKIE_TIMEOUT        60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
+
+/**
+ * Complete list of ciphersuites to use, in order of preference.
+ *
+ * \warning No dependency checking is done on that field! This option can only
+ * be used to restrict the set of available ciphersuites. It is your
+ * responsibility to make sure the needed modules are active.
+ *
+ * Use this to save a few hundred bytes of ROM (default ordering of all
+ * available ciphersuites) and a few to a few hundred bytes of RAM.
+ *
+ * The value below is only an example, not the default.
+ */
+#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, \
+                                 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \
+                                 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \
+                                 MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, \
+                                 MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, \
+                                 MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
+/* X509 options */
+//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA   8   /**< Maximum number of intermediate CAs in a verification chain. */
+
+/* \} name SECTION: Module configuration options */
+
+#if defined(TARGET_LIKE_MBED)
+#include "mbedtls/target_config.h"
+#endif
+
+/*
+ * Allow user to override any previous default.
+ *
+ * Use two macro names for that, as:
+ * - with yotta the prefix YOTTA_CFG_ is forced
+ * - without yotta is looks weird to have a YOTTA prefix.
+ */
+#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE)
+#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE
+#elif defined(MBEDTLS_USER_CONFIG_FILE)
+#include MBEDTLS_USER_CONFIG_FILE
+#endif
+
+#include "mbedtls/check_config.h"
+
+#endif /* KSDK_MBEDTLS_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_Linux.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2665 @@
+/**
+ * \file config.h
+ *
+ * \brief Configuration options (set of defines)
+ *
+ *  This set of compile-time options may be used to enable
+ *  or disable features selectively, and reduce the global
+ *  memory footprint.
+ *
+ *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  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.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_CONFIG_H
+#define MBEDTLS_CONFIG_H
+
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+/**
+ * \name SECTION: System support
+ *
+ * This section sets system specific settings.
+ * \{
+ */
+#if 1 //Please set to 1 if you are using secure time
+/**
+ * \def MBEDTLS_HAVE_ASM
+ *
+ * The compiler has support for asm().
+ *
+ * Requires support for asm() in compiler.
+ *
+ * Used in:
+ *      library/timing.c
+ *      library/padlock.c
+ *      include/mbedtls/bn_mul.h
+ *
+ * Comment to disable the use of assembly code.
+ */
+#define MBEDTLS_HAVE_ASM
+
+/**
+ * \def MBEDTLS_HAVE_SSE2
+ *
+ * CPU supports SSE2 instruction set.
+ *
+ * Uncomment if the CPU supports SSE2 (IA-32 specific).
+ */
+//#define MBEDTLS_HAVE_SSE2
+
+/**
+ * \def MBEDTLS_HAVE_TIME
+ *
+ * System has time.h and time().
+ * The time does not need to be correct, only time differences are used,
+ * by contrast with MBEDTLS_HAVE_TIME_DATE
+ *
+ * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT,
+ * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and
+ * MBEDTLS_PLATFORM_STD_TIME.
+ *
+ * Comment if your system does not support time functions
+ */
+#define MBEDTLS_HAVE_TIME
+
+/**
+ * \def MBEDTLS_HAVE_TIME_DATE
+ *
+ * System has time.h and time(), gmtime() and the clock is correct.
+ * The time needs to be correct (not necesarily very accurate, but at least
+ * the date should be correct). This is used to verify the validity period of
+ * X.509 certificates.
+ *
+ * Comment if your system does not have a correct clock.
+ */
+#define MBEDTLS_HAVE_TIME_DATE
+
+/**
+ * \def MBEDTLS_PLATFORM_MEMORY
+ *
+ * Enable the memory allocation layer.
+ *
+ * By default mbed TLS uses the system-provided calloc() and free().
+ * This allows different allocators (self-implemented or provided) to be
+ * provided to the platform abstraction layer.
+ *
+ * Enabling MBEDTLS_PLATFORM_MEMORY without the
+ * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide
+ * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and
+ * free() function pointer at runtime.
+ *
+ * Enabling MBEDTLS_PLATFORM_MEMORY and specifying
+ * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the
+ * alternate function at compile time.
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *
+ * Enable this layer to allow use of alternative memory allocators.
+ */
+//#define MBEDTLS_PLATFORM_MEMORY
+
+/**
+ * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+ *
+ * Do not assign standard functions in the platform layer (e.g. calloc() to
+ * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF)
+ *
+ * This makes sure there are no linking errors on platforms that do not support
+ * these functions. You will HAVE to provide alternatives, either at runtime
+ * via the platform_set_xxx() functions or at compile time by setting
+ * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a
+ * MBEDTLS_PLATFORM_XXX_MACRO.
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *
+ * Uncomment to prevent default assignment of standard functions in the
+ * platform layer.
+ */
+//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+
+/**
+ * \def MBEDTLS_PLATFORM_EXIT_ALT
+ *
+ * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the
+ * function in the platform abstraction layer.
+ *
+ * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will
+ * provide a function "mbedtls_platform_set_printf()" that allows you to set an
+ * alternative printf function pointer.
+ *
+ * All these define require MBEDTLS_PLATFORM_C to be defined!
+ *
+ * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows;
+ * it will be enabled automatically by check_config.h
+ *
+ * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as
+ * MBEDTLS_PLATFORM_XXX_MACRO!
+ *
+ * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME
+ *
+ * Uncomment a macro to enable alternate implementation of specific base
+ * platform function
+ */
+#define MBEDTLS_PLATFORM_TIME_ALT
+#endif //0
+//#define MBEDTLS_PLATFORM_EXIT_ALT
+//#define MBEDTLS_PLATFORM_FPRINTF_ALT
+//#define MBEDTLS_PLATFORM_PRINTF_ALT
+//#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+//#define MBEDTLS_PLATFORM_NV_SEED_ALT
+
+/**
+ * \def MBEDTLS_DEPRECATED_WARNING
+ *
+ * Mark deprecated functions so that they generate a warning if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * This only works with GCC and Clang. With other compilers, you may want to
+ * use MBEDTLS_DEPRECATED_REMOVED
+ *
+ * Uncomment to get warnings on using deprecated functions.
+ */
+//#define MBEDTLS_DEPRECATED_WARNING
+
+/**
+ * \def MBEDTLS_DEPRECATED_REMOVED
+ *
+ * Remove deprecated functions so that they generate an error if used.
+ * Functions deprecated in one version will usually be removed in the next
+ * version. You can enable this to help you prepare the transition to a new
+ * major version by making sure your code is not using these functions.
+ *
+ * Uncomment to get errors on using deprecated functions.
+ */
+//#define MBEDTLS_DEPRECATED_REMOVED
+
+/* \} name SECTION: System support */
+
+/**
+ * \name SECTION: mbed TLS feature support
+ *
+ * This section sets support for features that are or are not needed
+ * within the modules that are enabled.
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_TIMING_ALT
+ *
+ * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(),
+ * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay()
+ *
+ * Only works if you have MBEDTLS_TIMING_C enabled.
+ *
+ * You will need to provide a header "timing_alt.h" and an implementation at
+ * compile time.
+ */
+//#define MBEDTLS_TIMING_ALT
+
+/**
+ * \def MBEDTLS_AES_ALT
+ *
+ * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your
+ * alternate core implementation of a symmetric crypto, an arithmetic or hash
+ * module (e.g. platform specific assembly optimized implementations). Keep
+ * in mind that the function prototypes should remain the same.
+ *
+ * This replaces the whole module. If you only want to replace one of the
+ * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer
+ * provide the "struct mbedtls_aes_context" definition and omit the base
+ * function declarations and implementations. "aes_alt.h" will be included from
+ * "aes.h" to include the new function definitions.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * module.
+ */
+//#define MBEDTLS_AES_ALT
+//#define MBEDTLS_ARC4_ALT
+//#define MBEDTLS_BLOWFISH_ALT
+//#define MBEDTLS_CAMELLIA_ALT
+//#define MBEDTLS_DES_ALT
+//#define MBEDTLS_XTEA_ALT
+//#define MBEDTLS_MD2_ALT
+//#define MBEDTLS_MD4_ALT
+//#define MBEDTLS_MD5_ALT
+//#define MBEDTLS_RIPEMD160_ALT
+//#define MBEDTLS_SHA1_ALT
+//#define MBEDTLS_SHA256_ALT
+//#define MBEDTLS_SHA512_ALT
+/*
+ * When replacing the elliptic curve module, pleace consider, that it is
+ * implemented with two .c files:
+ *      - ecp.c
+ *      - ecp_curves.c
+ * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT
+ * macros as described above. The only difference is that you have to make sure
+ * that you provide functionality for both .c files.
+ */
+//#define MBEDTLS_ECP_ALT
+
+/**
+ * \def MBEDTLS_MD2_PROCESS_ALT
+ *
+ * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you
+ * alternate core implementation of symmetric crypto or hash function. Keep in
+ * mind that function prototypes should remain the same.
+ *
+ * This replaces only one function. The header file from mbed TLS is still
+ * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags.
+ *
+ * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will
+ * no longer provide the mbedtls_sha1_process() function, but it will still provide
+ * the other function (using your mbedtls_sha1_process() function) and the definition
+ * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible
+ * with this definition.
+ *
+ * Note: if you use the AES_xxx_ALT macros, then is is recommended to also set
+ * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES
+ * tables.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * function.
+ */
+//#define MBEDTLS_MD2_PROCESS_ALT
+//#define MBEDTLS_MD4_PROCESS_ALT
+//#define MBEDTLS_MD5_PROCESS_ALT
+//#define MBEDTLS_RIPEMD160_PROCESS_ALT
+//#define MBEDTLS_SHA1_PROCESS_ALT
+//#define MBEDTLS_SHA256_PROCESS_ALT
+//#define MBEDTLS_SHA512_PROCESS_ALT
+//#define MBEDTLS_DES_SETKEY_ALT
+//#define MBEDTLS_DES_CRYPT_ECB_ALT
+//#define MBEDTLS_DES3_CRYPT_ECB_ALT
+//#define MBEDTLS_AES_SETKEY_ENC_ALT
+//#define MBEDTLS_AES_SETKEY_DEC_ALT
+//#define MBEDTLS_AES_ENCRYPT_ALT
+//#define MBEDTLS_AES_DECRYPT_ALT
+
+/**
+ * \def MBEDTLS_ECP_INTERNAL_ALT
+ *
+ * Expose a part of the internal interface of the Elliptic Curve Point module.
+ *
+ * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your
+ * alternative core implementation of elliptic curve arithmetic. Keep in mind
+ * that function prototypes should remain the same.
+ *
+ * This partially replaces one function. The header file from mbed TLS is still
+ * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation
+ * is still present and it is used for group structures not supported by the
+ * alternative.
+ *
+ * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT
+ * and implementing the following functions:
+ *      unsigned char mbedtls_internal_ecp_grp_capable(
+ *          const mbedtls_ecp_group *grp )
+ *      int  mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp )
+ *      void mbedtls_internal_ecp_deinit( const mbedtls_ecp_group *grp )
+ * The mbedtls_internal_ecp_grp_capable function should return 1 if the
+ * replacement functions implement arithmetic for the given group and 0
+ * otherwise.
+ * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_deinit are
+ * called before and after each point operation and provide an opportunity to
+ * implement optimized set up and tear down instructions.
+ *
+ * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and
+ * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac
+ * function, but will use your mbedtls_internal_ecp_double_jac if the group is
+ * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when
+ * receives it as an argument). If the group is not supported then the original
+ * implementation is used. The other functions and the definition of
+ * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your
+ * implementation of mbedtls_internal_ecp_double_jac and
+ * mbedtls_internal_ecp_grp_capable must be compatible with this definition.
+ *
+ * Uncomment a macro to enable alternate implementation of the corresponding
+ * function.
+ */
+/* Required for all the functions in this section */
+//#define MBEDTLS_ECP_INTERNAL_ALT
+/* Support for Weierstrass curves with Jacobi representation */
+//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT
+//#define MBEDTLS_ECP_ADD_MIXED_ALT
+//#define MBEDTLS_ECP_DOUBLE_JAC_ALT
+//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
+//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
+/* Support for curves with Montgomery arithmetic */
+//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT
+//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT
+//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT
+
+/**
+ * \def MBEDTLS_TEST_NULL_ENTROPY
+ *
+ * Enables testing and use of mbed TLS without any configured entropy sources.
+ * This permits use of the library on platforms before an entropy source has
+ * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the
+ * MBEDTLS_ENTROPY_NV_SEED switches).
+ *
+ * WARNING! This switch MUST be disabled in production builds, and is suitable
+ * only for development.
+ * Enabling the switch negates any security provided by the library.
+ *
+ * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ */
+//#define MBEDTLS_TEST_NULL_ENTROPY
+
+/**
+ * \def MBEDTLS_ENTROPY_HARDWARE_ALT
+ *
+ * Uncomment this macro to let mbed TLS use your own implementation of a
+ * hardware entropy collector.
+ *
+ * Your function must be called \c mbedtls_hardware_poll(), have the same
+ * prototype as declared in entropy_poll.h, and accept NULL as first argument.
+ *
+ * Uncomment to use your own hardware entropy collector.
+ */
+//#define MBEDTLS_ENTROPY_HARDWARE_ALT
+
+/**
+ * \def MBEDTLS_AES_ROM_TABLES
+ *
+ * Store the AES tables in ROM.
+ *
+ * Uncomment this macro to store the AES tables in ROM.
+ */
+//#define MBEDTLS_AES_ROM_TABLES
+
+/**
+ * \def MBEDTLS_CAMELLIA_SMALL_MEMORY
+ *
+ * Use less ROM for the Camellia implementation (saves about 768 bytes).
+ *
+ * Uncomment this macro to use less memory for Camellia.
+ */
+//#define MBEDTLS_CAMELLIA_SMALL_MEMORY
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CBC
+ *
+ * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CBC
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CFB
+ *
+ * Enable Cipher Feedback mode (CFB) for symmetric ciphers.
+ */
+//#define MBEDTLS_CIPHER_MODE_CFB
+
+/**
+ * \def MBEDTLS_CIPHER_MODE_CTR
+ *
+ * Enable Counter Block Cipher mode (CTR) for symmetric ciphers.
+ */
+#define MBEDTLS_CIPHER_MODE_CTR
+
+/**
+ * \def MBEDTLS_CIPHER_NULL_CIPHER
+ *
+ * Enable NULL cipher.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * encryption or channels without any security!
+ *
+ * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable
+ * the following ciphersuites:
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA
+ *      MBEDTLS_TLS_RSA_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_NULL_SHA
+ *      MBEDTLS_TLS_RSA_WITH_NULL_MD5
+ *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA
+ *      MBEDTLS_TLS_PSK_WITH_NULL_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_NULL_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_NULL_SHA
+ *
+ * Uncomment this macro to enable the NULL cipher and ciphersuites
+ */
+//#define MBEDTLS_CIPHER_NULL_CIPHER
+
+/**
+ * \def MBEDTLS_CIPHER_PADDING_PKCS7
+ *
+ * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for
+ * specific padding modes in the cipher layer with cipher modes that support
+ * padding (e.g. CBC)
+ *
+ * If you disable all padding modes, only full blocks can be used with CBC.
+ *
+ * Enable padding modes in the cipher layer.
+ */
+#define MBEDTLS_CIPHER_PADDING_PKCS7
+//#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS
+//#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN
+//#define MBEDTLS_CIPHER_PADDING_ZEROS
+
+/**
+ * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES
+ *
+ * Enable weak ciphersuites in SSL / TLS.
+ * Warning: Only do so when you know what you are doing. This allows for
+ * channels with virtually no security at all!
+ *
+ * This enables the following ciphersuites:
+ *      MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA
+ *
+ * Uncomment this macro to enable weak ciphersuites
+ */
+//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES
+
+/**
+ * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES
+ *
+ * Remove RC4 ciphersuites by default in SSL / TLS.
+ * This flag removes the ciphersuites based on RC4 from the default list as
+ * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to
+ * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them
+ * explicitly.
+ *
+ * Uncomment this macro to remove RC4 ciphersuites by default.
+ */
+#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES
+
+/**
+ * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED
+ *
+ * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve
+ * module.  By default all supported curves are enabled.
+ *
+ * Comment macros to disable the curve and functions for it
+ */
+//#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
+//#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+//#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+//#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
+//#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
+//#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
+//#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
+//#define MBEDTLS_ECP_DP_BP256R1_ENABLED
+//#define MBEDTLS_ECP_DP_BP384R1_ENABLED
+//#define MBEDTLS_ECP_DP_BP512R1_ENABLED
+//#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
+
+/**
+ * \def MBEDTLS_ECP_NIST_OPTIM
+ *
+ * Enable specific 'modulo p' routines for each NIST prime.
+ * Depending on the prime and architecture, makes operations 4 to 8 times
+ * faster on the corresponding curve.
+ *
+ * Comment this macro to disable NIST curves optimisation.
+ */
+#define MBEDTLS_ECP_NIST_OPTIM
+
+/**
+ * \def MBEDTLS_ECDSA_DETERMINISTIC
+ *
+ * Enable deterministic ECDSA (RFC 6979).
+ * Standard ECDSA is "fragile" in the sense that lack of entropy when signing
+ * may result in a compromise of the long-term signing key. This is avoided by
+ * the deterministic variant.
+ *
+ * Requires: MBEDTLS_HMAC_DRBG_C
+ *
+ * Comment this macro to disable deterministic ECDSA.
+ */
+#define MBEDTLS_ECDSA_DETERMINISTIC
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+ *
+ * Enable the PSK based ciphersuite modes in SSL / TLS.
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_RC4_128_SHA
+ */
+//#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+ *
+ * Enable the DHE-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_DHM_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA
+ */
+//#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+ *
+ * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA
+ */
+//#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+ *
+ * Enable the RSA-PSK based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
+ *           MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA
+ */
+//#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+ *
+ * Enable the RSA-only based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
+ *           MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_RSA_WITH_RC4_128_MD5
+ */
+//#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+ *
+ * Enable the DHE-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
+ *           MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ */
+//#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+ *
+ * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15,
+ *           MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ */
+//#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+ *
+ * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C,
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ */
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+ *
+ * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ */
+//#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+ *
+ * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS.
+ *
+ * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ */
+//#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+
+/**
+ * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+ *
+ * Enable the ECJPAKE based ciphersuite modes in SSL / TLS.
+ *
+ * \warning This is currently experimental. EC J-PAKE support is based on the
+ * Thread v1.0.0 specification; incompatible changes to the specification
+ * might still happen. For this reason, this is disabled by default.
+ *
+ * Requires: MBEDTLS_ECJPAKE_C
+ *           MBEDTLS_SHA256_C
+ *           MBEDTLS_ECP_DP_SECP256R1_ENABLED
+ *
+ * This enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
+ */
+//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+
+/**
+ * \def MBEDTLS_PK_PARSE_EC_EXTENDED
+ *
+ * Enhance support for reading EC keys using variants of SEC1 not allowed by
+ * RFC 5915 and RFC 5480.
+ *
+ * Currently this means parsing the SpecifiedECDomain choice of EC
+ * parameters (only known groups are supported, not arbitrary domains, to
+ * avoid validation issues).
+ *
+ * Disable if you only need to support RFC 5915 + 5480 key formats.
+ */
+//#define MBEDTLS_PK_PARSE_EC_EXTENDED
+
+/**
+ * \def MBEDTLS_ERROR_STRERROR_DUMMY
+ *
+ * Enable a dummy error function to make use of mbedtls_strerror() in
+ * third party libraries easier when MBEDTLS_ERROR_C is disabled
+ * (no effect when MBEDTLS_ERROR_C is enabled).
+ *
+ * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're
+ * not using mbedtls_strerror() or error_strerror() in your application.
+ *
+ * Disable if you run into name conflicts and want to really remove the
+ * mbedtls_strerror()
+ */
+//#define MBEDTLS_ERROR_STRERROR_DUMMY
+
+/**
+ * \def MBEDTLS_GENPRIME
+ *
+ * Enable the prime-number generation code.
+ *
+ * Requires: MBEDTLS_BIGNUM_C
+ */
+//#define MBEDTLS_GENPRIME
+
+/**
+ * \def MBEDTLS_FS_IO
+ *
+ * Enable functions that use the filesystem.
+ */
+//#define MBEDTLS_FS_IO
+
+/**
+ * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+ *
+ * Do not add default entropy sources. These are the platform specific,
+ * mbedtls_timing_hardclock and HAVEGE based poll functions.
+ *
+ * This is useful to have more control over the added entropy sources in an
+ * application.
+ *
+ * Uncomment this macro to prevent loading of default entropy functions.
+ */
+//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+
+/**
+ * \def MBEDTLS_NO_PLATFORM_ENTROPY
+ *
+ * Do not use built-in platform entropy functions.
+ * This is useful if your platform does not support
+ * standards like the /dev/urandom or Windows CryptoAPI.
+ *
+ * Uncomment this macro to disable the built-in platform entropy functions.
+ */
+//#define MBEDTLS_NO_PLATFORM_ENTROPY
+
+/**
+ * \def MBEDTLS_ENTROPY_FORCE_SHA256
+ *
+ * Force the entropy accumulator to use a SHA-256 accumulator instead of the
+ * default SHA-512 based one (if both are available).
+ *
+ * Requires: MBEDTLS_SHA256_C
+ *
+ * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option
+ * if you have performance concerns.
+ *
+ * This option is only useful if both MBEDTLS_SHA256_C and
+ * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used.
+ */
+//#define MBEDTLS_ENTROPY_FORCE_SHA256
+
+/**
+ * \def MBEDTLS_ENTROPY_NV_SEED
+ *
+ * Enable the non-volatile (NV) seed file-based entropy source.
+ * (Also enables the NV seed read/write functions in the platform layer)
+ *
+ * This is crucial (if not required) on systems that do not have a
+ * cryptographic entropy source (in hardware or kernel) available.
+ *
+ * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C
+ *
+ * \note The read/write functions that are used by the entropy source are
+ *       determined in the platform layer, and can be modified at runtime and/or
+ *       compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used.
+ *
+ * \note If you use the default implementation functions that read a seedfile
+ *       with regular fopen(), please make sure you make a seedfile with the
+ *       proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at
+ *       least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from
+ *       and written to or you will get an entropy source error! The default
+ *       implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE
+ *       bytes from the file.
+ *
+ * \note The entropy collector will write to the seed file before entropy is
+ *       given to an external source, to update it.
+ */
+//#define MBEDTLS_ENTROPY_NV_SEED
+
+/**
+ * \def MBEDTLS_MEMORY_DEBUG
+ *
+ * Enable debugging of buffer allocator memory issues. Automatically prints
+ * (to stderr) all (fatal) messages on memory allocation issues. Enables
+ * function for 'debug output' of allocated memory.
+ *
+ * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *
+ * Uncomment this macro to let the buffer allocator print out error messages.
+ */
+//#define MBEDTLS_MEMORY_DEBUG
+
+/**
+ * \def MBEDTLS_MEMORY_BACKTRACE
+ *
+ * Include backtrace information with each allocated block.
+ *
+ * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *           GLIBC-compatible backtrace() an backtrace_symbols() support
+ *
+ * Uncomment this macro to include backtrace information
+ */
+//#define MBEDTLS_MEMORY_BACKTRACE
+
+/**
+ * \def MBEDTLS_PK_RSA_ALT_SUPPORT
+ *
+ * Support external private RSA keys (eg from a HSM) in the PK layer.
+ *
+ * Comment this macro to disable support for external private RSA keys.
+ */
+//#define MBEDTLS_PK_RSA_ALT_SUPPORT
+
+/**
+ * \def MBEDTLS_PKCS1_V15
+ *
+ * Enable support for PKCS#1 v1.5 encoding.
+ *
+ * Requires: MBEDTLS_RSA_C
+ *
+ * This enables support for PKCS#1 v1.5 operations.
+ */
+#define MBEDTLS_PKCS1_V15
+
+/**
+ * \def MBEDTLS_PKCS1_V21
+ *
+ * Enable support for PKCS#1 v2.1 encoding.
+ *
+ * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C
+ *
+ * This enables support for RSAES-OAEP and RSASSA-PSS operations.
+ */
+#define MBEDTLS_PKCS1_V21
+
+/**
+ * \def MBEDTLS_RSA_NO_CRT
+ *
+ * Do not use the Chinese Remainder Theorem for the RSA private operation.
+ *
+ * Uncomment this macro to disable the use of CRT in RSA.
+ *
+ */
+//#define MBEDTLS_RSA_NO_CRT
+
+/**
+ * \def MBEDTLS_SELF_TEST
+ *
+ * Enable the checkup functions (*_self_test).
+ */
+//#define MBEDTLS_SELF_TEST
+
+/**
+ * \def MBEDTLS_SHA256_SMALLER
+ *
+ * Enable an implementation of SHA-256 that has lower ROM footprint but also
+ * lower performance.
+ *
+ * The default implementation is meant to be a reasonnable compromise between
+ * performance and size. This version optimizes more aggressively for size at
+ * the expense of performance. Eg on Cortex-M4 it reduces the size of
+ * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
+ * 30%.
+ *
+ * Uncomment to enable the smaller implementation of SHA256.
+ */
+//#define MBEDTLS_SHA256_SMALLER
+
+/**
+ * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES
+ *
+ * Enable sending of alert messages in case of encountered errors as per RFC.
+ * If you choose not to send the alert messages, mbed TLS can still communicate
+ * with other servers, only debugging of failures is harder.
+ *
+ * The advantage of not sending alert messages, is that no information is given
+ * about reasons for failures thus preventing adversaries of gaining intel.
+ *
+ * Enable sending of all alert messages
+ */
+#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
+
+/**
+ * \def MBEDTLS_SSL_DEBUG_ALL
+ *
+ * Enable the debug messages in SSL module for all issues.
+ * Debug messages have been disabled in some places to prevent timing
+ * attacks due to (unbalanced) debugging function calls.
+ *
+ * If you need all error reporting you should enable this during debugging,
+ * but remove this for production servers that should log as well.
+ *
+ * Uncomment this macro to report all debug messages on errors introducing
+ * a timing side-channel.
+ *
+ */
+//#define MBEDTLS_SSL_DEBUG_ALL
+
+/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC
+ *
+ * Enable support for Encrypt-then-MAC, RFC 7366.
+ *
+ * This allows peers that both support it to use a more robust protection for
+ * ciphersuites using CBC, providing deep resistance against timing attacks
+ * on the padding or underlying cipher.
+ *
+ * This only affects CBC ciphersuites, and is useless if none is defined.
+ *
+ * Requires: MBEDTLS_SSL_PROTO_TLS1    or
+ *           MBEDTLS_SSL_PROTO_TLS1_1  or
+ *           MBEDTLS_SSL_PROTO_TLS1_2
+ *
+ * Comment this macro to disable support for Encrypt-then-MAC
+ */
+#define MBEDTLS_SSL_ENCRYPT_THEN_MAC
+
+/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+ *
+ * Enable support for Extended Master Secret, aka Session Hash
+ * (draft-ietf-tls-session-hash-02).
+ *
+ * This was introduced as "the proper fix" to the Triple Handshake familiy of
+ * attacks, but it is recommended to always use it (even if you disable
+ * renegotiation), since it actually fixes a more fundamental issue in the
+ * original SSL/TLS design, and has implications beyond Triple Handshake.
+ *
+ * Requires: MBEDTLS_SSL_PROTO_TLS1    or
+ *           MBEDTLS_SSL_PROTO_TLS1_1  or
+ *           MBEDTLS_SSL_PROTO_TLS1_2
+ *
+ * Comment this macro to disable support for Extended Master Secret.
+ */
+#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+
+/**
+ * \def MBEDTLS_SSL_FALLBACK_SCSV
+ *
+ * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00).
+ *
+ * For servers, it is recommended to always enable this, unless you support
+ * only one version of TLS, or know for sure that none of your clients
+ * implements a fallback strategy.
+ *
+ * For clients, you only need this if you're using a fallback strategy, which
+ * is not recommended in the first place, unless you absolutely need it to
+ * interoperate with buggy (version-intolerant) servers.
+ *
+ * Comment this macro to disable support for FALLBACK_SCSV
+ */
+//#define MBEDTLS_SSL_FALLBACK_SCSV
+
+/**
+ * \def MBEDTLS_SSL_HW_RECORD_ACCEL
+ *
+ * Enable hooking functions in SSL module for hardware acceleration of
+ * individual records.
+ *
+ * Uncomment this macro to enable hooking functions.
+ */
+//#define MBEDTLS_SSL_HW_RECORD_ACCEL
+
+/**
+ * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING
+ *
+ * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0.
+ *
+ * This is a countermeasure to the BEAST attack, which also minimizes the risk
+ * of interoperability issues compared to sending 0-length records.
+ *
+ * Comment this macro to disable 1/n-1 record splitting.
+ */
+//#define MBEDTLS_SSL_CBC_RECORD_SPLITTING
+
+/**
+ * \def MBEDTLS_SSL_RENEGOTIATION
+ *
+ * Disable support for TLS renegotiation.
+ *
+ * The two main uses of renegotiation are (1) refresh keys on long-lived
+ * connections and (2) client authentication after the initial handshake.
+ * If you don't need renegotiation, it's probably better to disable it, since
+ * it has been associated with security issues in the past and is easy to
+ * misuse/misunderstand.
+ *
+ * Comment this to disable support for renegotiation.
+ */
+#define MBEDTLS_SSL_RENEGOTIATION
+
+/**
+ * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+ *
+ * Enable support for receiving and parsing SSLv2 Client Hello messages for the
+ * SSL Server module (MBEDTLS_SSL_SRV_C).
+ *
+ * Uncomment this macro to enable support for SSLv2 Client Hello messages.
+ */
+//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO
+
+/**
+ * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+ *
+ * Pick the ciphersuite according to the client's preferences rather than ours
+ * in the SSL Server module (MBEDTLS_SSL_SRV_C).
+ *
+ * Uncomment this macro to respect client's ciphersuite order
+ */
+//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE
+
+/**
+ * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+ *
+ * Enable support for RFC 6066 max_fragment_length extension in SSL.
+ *
+ * Comment this macro to disable support for the max_fragment_length extension
+ */
+#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+
+/**
+ * \def MBEDTLS_SSL_PROTO_SSL3
+ *
+ * Enable support for SSL 3.0.
+ *
+ * Requires: MBEDTLS_MD5_C
+ *           MBEDTLS_SHA1_C
+ *
+ * Comment this macro to disable support for SSL 3.0
+ */
+//#define MBEDTLS_SSL_PROTO_SSL3
+
+/**
+ * \def MBEDTLS_SSL_PROTO_TLS1
+ *
+ * Enable support for TLS 1.0.
+ *
+ * Requires: MBEDTLS_MD5_C
+ *           MBEDTLS_SHA1_C
+ *
+ * Comment this macro to disable support for TLS 1.0
+ */
+//#define MBEDTLS_SSL_PROTO_TLS1
+
+/**
+ * \def MBEDTLS_SSL_PROTO_TLS1_1
+ *
+ * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled).
+ *
+ * Requires: MBEDTLS_MD5_C
+ *           MBEDTLS_SHA1_C
+ *
+ * Comment this macro to disable support for TLS 1.1 / DTLS 1.0
+ */
+//#define MBEDTLS_SSL_PROTO_TLS1_1
+
+/**
+ * \def MBEDTLS_SSL_PROTO_TLS1_2
+ *
+ * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled).
+ *
+ * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C
+ *           (Depends on ciphersuites)
+ *
+ * Comment this macro to disable support for TLS 1.2 / DTLS 1.2
+ */
+#define MBEDTLS_SSL_PROTO_TLS1_2
+
+/**
+ * \def MBEDTLS_SSL_PROTO_DTLS
+ *
+ * Enable support for DTLS (all available versions).
+ *
+ * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0,
+ * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2.
+ *
+ * Requires: MBEDTLS_SSL_PROTO_TLS1_1
+ *        or MBEDTLS_SSL_PROTO_TLS1_2
+ *
+ * Comment this macro to disable support for DTLS
+ */
+#define MBEDTLS_SSL_PROTO_DTLS
+
+/**
+ * \def MBEDTLS_SSL_ALPN
+ *
+ * Enable support for RFC 7301 Application Layer Protocol Negotiation.
+ *
+ * Comment this macro to disable support for ALPN.
+ */
+#define MBEDTLS_SSL_ALPN
+
+/**
+ * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY
+ *
+ * Enable support for the anti-replay mechanism in DTLS.
+ *
+ * Requires: MBEDTLS_SSL_TLS_C
+ *           MBEDTLS_SSL_PROTO_DTLS
+ *
+ * \warning Disabling this is often a security risk!
+ * See mbedtls_ssl_conf_dtls_anti_replay() for details.
+ *
+ * Comment this to disable anti-replay in DTLS.
+ */
+#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+
+/**
+ * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY
+ *
+ * Enable support for HelloVerifyRequest on DTLS servers.
+ *
+ * This feature is highly recommended to prevent DTLS servers being used as
+ * amplifiers in DoS attacks against other hosts. It should always be enabled
+ * unless you know for sure amplification cannot be a problem in the
+ * environment in which your server operates.
+ *
+ * \warning Disabling this can ba a security risk! (see above)
+ *
+ * Requires: MBEDTLS_SSL_PROTO_DTLS
+ *
+ * Comment this to disable support for HelloVerifyRequest.
+ */
+#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+
+/**
+ * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
+ *
+ * Enable server-side support for clients that reconnect from the same port.
+ *
+ * Some clients unexpectedly close the connection and try to reconnect using the
+ * same source port. This needs special support from the server to handle the
+ * new connection securely, as described in section 4.2.8 of RFC 6347. This
+ * flag enables that support.
+ *
+ * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY
+ *
+ * Comment this to disable support for clients reusing the source port.
+ */
+#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
+
+/**
+ * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT
+ *
+ * Enable support for a limit of records with bad MAC.
+ *
+ * See mbedtls_ssl_conf_dtls_badmac_limit().
+ *
+ * Requires: MBEDTLS_SSL_PROTO_DTLS
+ */
+#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT
+
+/**
+ * \def MBEDTLS_SSL_SESSION_TICKETS
+ *
+ * Enable support for RFC 5077 session tickets in SSL.
+ * Client-side, provides full support for session tickets (maintainance of a
+ * session store remains the responsibility of the application, though).
+ * Server-side, you also need to provide callbacks for writing and parsing
+ * tickets, including authenticated encryption and key management. Example
+ * callbacks are provided by MBEDTLS_SSL_TICKET_C.
+ *
+ * Comment this macro to disable support for SSL session tickets
+ */
+#define MBEDTLS_SSL_SESSION_TICKETS
+
+/**
+ * \def MBEDTLS_SSL_EXPORT_KEYS
+ *
+ * Enable support for exporting key block and master secret.
+ * This is required for certain users of TLS, e.g. EAP-TLS.
+ *
+ * Comment this macro to disable support for key export
+ */
+#define MBEDTLS_SSL_EXPORT_KEYS
+
+/**
+ * \def MBEDTLS_SSL_SERVER_NAME_INDICATION
+ *
+ * Enable support for RFC 6066 server name indication (SNI) in SSL.
+ *
+ * Requires: MBEDTLS_X509_CRT_PARSE_C
+ *
+ * Comment this macro to disable support for server name indication in SSL
+ */
+#define MBEDTLS_SSL_SERVER_NAME_INDICATION
+/**   s
+ * \def MBEDTLS_SSL_TRUNCATED_HMAC
+ *
+ * Enable support for RFC 6066 truncated HMAC in SSL.
+ *
+ * Comment this macro to disable support for truncated HMAC in SSL
+ */
+//#define MBEDTLS_SSL_TRUNCATED_HMAC
+
+/**
+ * \def MBEDTLS_THREADING_ALT
+ *
+ * Provide your own alternate threading implementation.
+ *
+ * Requires: MBEDTLS_THREADING_C
+ *
+ * Uncomment this to allow your own alternate threading implementation.
+ */
+//#define MBEDTLS_THREADING_ALT
+
+/**
+ * \def MBEDTLS_THREADING_PTHREAD
+ *
+ * Enable the pthread wrapper layer for the threading layer.
+ *
+ * Requires: MBEDTLS_THREADING_C
+ *
+ * Uncomment this to enable pthread mutexes.
+ */
+//#define MBEDTLS_THREADING_PTHREAD
+
+/**
+ * \def MBEDTLS_VERSION_FEATURES
+ *
+ * Allow run-time checking of compile-time enabled features. Thus allowing users
+ * to check at run-time if the library is for instance compiled with threading
+ * support via mbedtls_version_check_feature().
+ *
+ * Requires: MBEDTLS_VERSION_C
+ *
+ * Comment this to disable run-time checking and save ROM space
+ */
+//#define MBEDTLS_VERSION_FEATURES
+/**
+ * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an extension in a v1 or v2 certificate.
+ *
+ * Uncomment to prevent an error.
+ */
+//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3
+
+/**
+ * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+ *
+ * If set, the X509 parser will not break-off when parsing an X509 certificate
+ * and encountering an unknown critical extension.
+ *
+ * \warning Depending on your PKI use, enabling this can be a security risk!
+ *
+ * Uncomment to prevent an error.
+ */
+//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
+
+/**
+ * \def MBEDTLS_X509_CHECK_KEY_USAGE
+ *
+ * Enable verification of the keyUsage extension (CA and leaf certificates).
+ *
+ * Disabling this avoids problems with mis-issued and/or misused
+ * (intermediate) CA and leaf certificates.
+ *
+ * \warning Depending on your PKI use, disabling this can be a security risk!
+ *
+ * Comment to skip keyUsage checking for both CA and leaf certificates.
+ */
+#define MBEDTLS_X509_CHECK_KEY_USAGE
+
+/**
+ * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+ *
+ * Enable verification of the extendedKeyUsage extension (leaf certificates).
+ *
+ * Disabling this avoids problems with mis-issued and/or misused certificates.
+ *
+ * \warning Depending on your PKI use, disabling this can be a security risk!
+ *
+ * Comment to skip extendedKeyUsage checking for certificates.
+ */
+#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE
+
+/**
+ * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT
+ *
+ * Enable parsing and verification of X.509 certificates, CRLs and CSRS
+ * signed with RSASSA-PSS (aka PKCS#1 v2.1).
+ *
+ * Comment this macro to disallow using RSASSA-PSS in certificates.
+ */
+//#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
+/**
+ * \def MBEDTLS_ZLIB_SUPPORT
+ *
+ * If set, the SSL/TLS module uses ZLIB to support compression and
+ * decompression of packet data.
+ *
+ * \warning TLS-level compression MAY REDUCE SECURITY! See for example the
+ * CRIME attack. Before enabling this option, you should examine with care if
+ * CRIME or similar exploits may be a applicable to your use case.
+ *
+ * \note Currently compression can't be used with DTLS.
+ *
+ * Used in: library/ssl_tls.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This feature requires zlib library and headers to be present.
+ *
+ * Uncomment to enable use of ZLIB
+ */
+//#define MBEDTLS_ZLIB_SUPPORT
+/* \} name SECTION: mbed TLS feature support */
+
+/**
+ * \name SECTION: mbed TLS modules
+ *
+ * This section enables or disables entire modules in mbed TLS
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_AESNI_C
+ *
+ * Enable AES-NI support on x86-64.
+ *
+ * Module:  library/aesni.c
+ * Caller:  library/aes.c
+ *
+ * Requires: MBEDTLS_HAVE_ASM
+ *
+ * This modules adds support for the AES-NI instructions on x86-64
+ */
+//#define MBEDTLS_AESNI_C
+
+/**
+ * \def MBEDTLS_AES_C
+ *
+ * Enable the AES block cipher.
+ *
+ * Module:  library/aes.c
+ * Caller:  library/ssl_tls.c
+ *          library/pem.c
+ *          library/ctr_drbg.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA
+ *
+ * PEM_PARSE uses AES for decrypting encrypted keys.
+ */
+#define MBEDTLS_AES_C
+
+/**
+ * \def MBEDTLS_ARC4_C
+ *
+ * Enable the ARCFOUR stream cipher.
+ *
+ * Module:  library/arc4.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_RSA_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_RSA_WITH_RC4_128_MD5
+ *      MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA
+ *      MBEDTLS_TLS_PSK_WITH_RC4_128_SHA
+ */
+//#define MBEDTLS_ARC4_C
+
+/**
+ * \def MBEDTLS_ASN1_PARSE_C
+ *
+ * Enable the generic ASN1 parser.
+ *
+ * Module:  library/asn1.c
+ * Caller:  library/x509.c
+ *          library/dhm.c
+ *          library/pkcs12.c
+ *          library/pkcs5.c
+ *          library/pkparse.c
+ */
+#define MBEDTLS_ASN1_PARSE_C
+
+/**
+ * \def MBEDTLS_ASN1_WRITE_C
+ *
+ * Enable the generic ASN1 writer.
+ *
+ * Module:  library/asn1write.c
+ * Caller:  library/ecdsa.c
+ *          library/pkwrite.c
+ *          library/x509_create.c
+ *          library/x509write_crt.c
+ *          library/x509write_csr.c
+ */
+#define MBEDTLS_ASN1_WRITE_C
+
+/**
+ * \def MBEDTLS_BASE64_C
+ *
+ * Enable the Base64 module.
+ *
+ * Module:  library/base64.c
+ * Caller:  library/pem.c
+ *
+ * This module is required for PEM support (required by X.509).
+ */
+// needed for Base64 encoding Opaque data for
+// registration payload, adds 500 bytes to flash.
+#define MBEDTLS_BASE64_C
+
+/**
+ * \def MBEDTLS_BIGNUM_C
+ *
+ * Enable the multi-precision integer library.
+ *
+ * Module:  library/bignum.c
+ * Caller:  library/dhm.c
+ *          library/ecp.c
+ *          library/ecdsa.c
+ *          library/rsa.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support.
+ */
+#define MBEDTLS_BIGNUM_C
+
+/**
+ * \def MBEDTLS_BLOWFISH_C
+ *
+ * Enable the Blowfish block cipher.
+ *
+ * Module:  library/blowfish.c
+ */
+//#define MBEDTLS_BLOWFISH_C
+
+/**
+ * \def MBEDTLS_CAMELLIA_C
+ *
+ * Enable the Camellia block cipher.
+ *
+ * Module:  library/camellia.c
+ * Caller:  library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256
+ *      MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256
+ */
+//#define MBEDTLS_CAMELLIA_C
+
+/**
+ * \def MBEDTLS_CCM_C
+ *
+ * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher.
+ *
+ * Module:  library/ccm.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C
+ *
+ * This module enables the AES-CCM ciphersuites, if other requisites are
+ * enabled as well.
+ */
+#define MBEDTLS_CCM_C
+
+/**
+ * \def MBEDTLS_CERTS_C
+ *
+ * Enable the test certificates.
+ *
+ * Module:  library/certs.c
+ * Caller:
+ *
+ * This module is used for testing (ssl_client/server).
+ */
+//#define MBEDTLS_CERTS_C
+
+/**
+ * \def MBEDTLS_CIPHER_C
+ *
+ * Enable the generic cipher layer.
+ *
+ * Module:  library/cipher.c
+ * Caller:  library/ssl_tls.c
+ *
+ * Uncomment to enable generic cipher wrappers.
+ */
+#define MBEDTLS_CIPHER_C
+
+/**
+ * \def MBEDTLS_CMAC_C
+ *
+ * Enable the CMAC (Cipher-based Message Authentication Code) mode for block
+ * ciphers.
+ *
+ * Module:  library/cmac.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C
+ *
+ */
+#define MBEDTLS_CMAC_C
+
+/**
+ * \def MBEDTLS_CTR_DRBG_C
+ *
+ * Enable the CTR_DRBG AES-256-based random generator.
+ *
+ * Module:  library/ctr_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_AES_C
+ *
+ * This module provides the CTR_DRBG AES-256 random number generator.
+ */
+#define MBEDTLS_CTR_DRBG_C
+
+/**
+ * \def MBEDTLS_DEBUG_C
+ *
+ * Enable the debug functions.
+ *
+ * Module:  library/debug.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module provides debugging functions.
+ */
+//#define MBEDTLS_DEBUG_C
+
+/**
+ * \def MBEDTLS_DES_C
+ *
+ * Enable the DES block cipher.
+ *
+ * Module:  library/des.c
+ * Caller:  library/pem.c
+ *          library/ssl_tls.c
+ *
+ * This module enables the following ciphersuites (if other requisites are
+ * enabled as well):
+ *      MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA
+ *      MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA
+ *
+ * PEM_PARSE uses DES/3DES for decrypting encrypted keys.
+ */
+//#define MBEDTLS_DES_C
+
+/**
+ * \def MBEDTLS_DHM_C
+ *
+ * Enable the Diffie-Hellman-Merkle module.
+ *
+ * Module:  library/dhm.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module is used by the following key exchanges:
+ *      DHE-RSA, DHE-PSK
+ */
+//#define MBEDTLS_DHM_C
+
+/**
+ * \def MBEDTLS_ECDH_C
+ *
+ * Enable the elliptic curve Diffie-Hellman library.
+ *
+ * Module:  library/ecdh.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module is used by the following key exchanges:
+ *      ECDHE-ECDSA, ECDHE-RSA, DHE-PSK
+ *
+ * Requires: MBEDTLS_ECP_C
+ */
+#define MBEDTLS_ECDH_C
+
+/**
+ * \def MBEDTLS_ECDSA_C
+ *
+ * Enable the elliptic curve DSA library.
+ *
+ * Module:  library/ecdsa.c
+ * Caller:
+ *
+ * This module is used by the following key exchanges:
+ *      ECDHE-ECDSA
+ *
+ * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C
+ */
+#define MBEDTLS_ECDSA_C
+
+/**
+ * \def MBEDTLS_ECJPAKE_C
+ *
+ * Enable the elliptic curve J-PAKE library.
+ *
+ * \warning This is currently experimental. EC J-PAKE support is based on the
+ * Thread v1.0.0 specification; incompatible changes to the specification
+ * might still happen. For this reason, this is disabled by default.
+ *
+ * Module:  library/ecjpake.c
+ * Caller:
+ *
+ * This module is used by the following key exchanges:
+ *      ECJPAKE
+ *
+ * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C
+ */
+//#define MBEDTLS_ECJPAKE_C
+
+/**
+ * \def MBEDTLS_ECP_C
+ *
+ * Enable the elliptic curve over GF(p) library.
+ *
+ * Module:  library/ecp.c
+ * Caller:  library/ecdh.c
+ *          library/ecdsa.c
+ *          library/ecjpake.c
+ *
+ * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED
+ */
+#define MBEDTLS_ECP_C
+
+/**
+ * \def MBEDTLS_ENTROPY_C
+ *
+ * Enable the platform-specific entropy code.
+ *
+ * Module:  library/entropy.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C
+ *
+ * This module provides a generic entropy pool
+ */
+#define MBEDTLS_ENTROPY_C
+
+/**
+ * \def MBEDTLS_ERROR_C
+ *
+ * Enable error code to error string conversion.
+ *
+ * Module:  library/error.c
+ * Caller:
+ *
+ * This module enables mbedtls_strerror().
+ */
+//#define MBEDTLS_ERROR_C
+
+/**
+ * \def MBEDTLS_GCM_C
+ *
+ * Enable the Galois/Counter Mode (GCM) for AES.
+ *
+ * Module:  library/gcm.c
+ *
+ * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C
+ *
+ * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other
+ * requisites are enabled as well.
+ */
+#define MBEDTLS_GCM_C
+
+/**
+ * \def MBEDTLS_HAVEGE_C
+ *
+ * Enable the HAVEGE random generator.
+ *
+ * Warning: the HAVEGE random generator is not suitable for virtualized
+ *          environments
+ *
+ * Warning: the HAVEGE random generator is dependent on timing and specific
+ *          processor traits. It is therefore not advised to use HAVEGE as
+ *          your applications primary random generator or primary entropy pool
+ *          input. As a secondary input to your entropy pool, it IS able add
+ *          the (limited) extra entropy it provides.
+ *
+ * Module:  library/havege.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_TIMING_C
+ *
+ * Uncomment to enable the HAVEGE random generator.
+ */
+//#define MBEDTLS_HAVEGE_C
+
+/**
+ * \def MBEDTLS_HMAC_DRBG_C
+ *
+ * Enable the HMAC_DRBG random generator.
+ *
+ * Module:  library/hmac_drbg.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * Uncomment to enable the HMAC_DRBG random number geerator.
+ */
+#define MBEDTLS_HMAC_DRBG_C
+
+/**
+ * \def MBEDTLS_MD_C
+ *
+ * Enable the generic message digest layer.
+ *
+ * Module:  library/md.c
+ * Caller:
+ *
+ * Uncomment to enable generic message digest wrappers.
+ */
+#define MBEDTLS_MD_C
+
+/**
+ * \def MBEDTLS_MD2_C
+ *
+ * Enable the MD2 hash algorithm.
+ *
+ * Module:  library/md2.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD2-signed X.509 certs.
+ */
+//#define MBEDTLS_MD2_C
+
+/**
+ * \def MBEDTLS_MD4_C
+ *
+ * Enable the MD4 hash algorithm.
+ *
+ * Module:  library/md4.c
+ * Caller:
+ *
+ * Uncomment to enable support for (rare) MD4-signed X.509 certs.
+ */
+//#define MBEDTLS_MD4_C
+
+/**
+ * \def MBEDTLS_MD5_C
+ *
+ * Enable the MD5 hash algorithm.
+ *
+ * Module:  library/md5.c
+ * Caller:  library/md.c
+ *          library/pem.c
+ *          library/ssl_tls.c
+ *
+ * This module is required for SSL/TLS and X.509.
+ * PEM_PARSE uses MD5 for decrypting encrypted keys.
+ */
+//#define MBEDTLS_MD5_C
+
+/**
+ * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ *
+ * Enable the buffer allocator implementation that makes use of a (stack)
+ * based buffer to 'allocate' dynamic memory. (replaces calloc() and free()
+ * calls)
+ *
+ * Module:  library/memory_buffer_alloc.c
+ *
+ * Requires: MBEDTLS_PLATFORM_C
+ *           MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS)
+ *
+ * Enable this module to enable the buffer memory allocator.
+ */
+//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C
+
+/**
+ * \def MBEDTLS_NET_C
+ *
+ * Enable the TCP and UDP over IPv6/IPv4 networking routines.
+ *
+ * \note This module only works on POSIX/Unix (including Linux, BSD and OS X)
+ * and Windows. For other platforms, you'll want to disable it, and write your
+ * own networking callbacks to be passed to \c mbedtls_ssl_set_bio().
+ *
+ * \note See also our Knowledge Base article about porting to a new
+ * environment:
+ * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
+ *
+ * Module:  library/net_sockets.c
+ *
+ * This module provides networking routines.
+ */
+//#define MBEDTLS_NET_C
+
+/**
+ * \def MBEDTLS_OID_C
+ *
+ * Enable the OID database.
+ *
+ * Module:  library/oid.c
+ * Caller:  library/asn1write.c
+ *          library/pkcs5.c
+ *          library/pkparse.c
+ *          library/pkwrite.c
+ *          library/rsa.c
+ *          library/x509.c
+ *          library/x509_create.c
+ *          library/x509_crl.c
+ *          library/x509_crt.c
+ *          library/x509_csr.c
+ *          library/x509write_crt.c
+ *          library/x509write_csr.c
+ *
+ * This modules translates between OIDs and internal values.
+ */
+#define MBEDTLS_OID_C
+
+/**
+ * \def MBEDTLS_PADLOCK_C
+ *
+ * Enable VIA Padlock support on x86.
+ *
+ * Module:  library/padlock.c
+ * Caller:  library/aes.c
+ *
+ * Requires: MBEDTLS_HAVE_ASM
+ *
+ * This modules adds support for the VIA PadLock on x86.
+ */
+//#define MBEDTLS_PADLOCK_C
+
+/**
+ * \def MBEDTLS_PEM_PARSE_C
+ *
+ * Enable PEM decoding / parsing.
+ *
+ * Module:  library/pem.c
+ * Caller:  library/dhm.c
+ *          library/pkparse.c
+ *          library/x509_crl.c
+ *          library/x509_crt.c
+ *          library/x509_csr.c
+ *
+ * Requires: MBEDTLS_BASE64_C
+ *
+ * This modules adds support for decoding / parsing PEM files.
+ */
+//#define MBEDTLS_PEM_PARSE_C
+
+/**
+ * \def MBEDTLS_PEM_WRITE_C
+ *
+ * Enable PEM encoding / writing.
+ *
+ * Module:  library/pem.c
+ * Caller:  library/pkwrite.c
+ *          library/x509write_crt.c
+ *          library/x509write_csr.c
+ *
+ * Requires: MBEDTLS_BASE64_C
+ *
+ * This modules adds support for encoding / writing PEM files.
+ */
+//#define MBEDTLS_PEM_WRITE_C
+
+/**
+ * \def MBEDTLS_PK_C
+ *
+ * Enable the generic public (asymetric) key layer.
+ *
+ * Module:  library/pk.c
+ * Caller:  library/ssl_tls.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C
+ *
+ * Uncomment to enable generic public key wrappers.
+ */
+#define MBEDTLS_PK_C
+
+/**
+ * \def MBEDTLS_PK_PARSE_C
+ *
+ * Enable the generic public (asymetric) key parser.
+ *
+ * Module:  library/pkparse.c
+ * Caller:  library/x509_crt.c
+ *          library/x509_csr.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * Uncomment to enable generic public key parse functions.
+ */
+#define MBEDTLS_PK_PARSE_C
+
+/**
+ * \def MBEDTLS_PK_WRITE_C
+ *
+ * Enable the generic public (asymetric) key writer.
+ *
+ * Module:  library/pkwrite.c
+ * Caller:  library/x509write.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * Uncomment to enable generic public key write functions.
+ */
+#define MBEDTLS_PK_WRITE_C
+
+/**
+ * \def MBEDTLS_PKCS5_C
+ *
+ * Enable PKCS#5 functions.
+ *
+ * Module:  library/pkcs5.c
+ *
+ * Requires: MBEDTLS_MD_C
+ *
+ * This module adds support for the PKCS#5 functions.
+ */
+//#define MBEDTLS_PKCS5_C
+
+/**
+ * \def MBEDTLS_PKCS11_C
+ *
+ * Enable wrapper for PKCS#11 smartcard support.
+ *
+ * Module:  library/pkcs11.c
+ * Caller:  library/pk.c
+ *
+ * Requires: MBEDTLS_PK_C
+ *
+ * This module enables SSL/TLS PKCS #11 smartcard support.
+ * Requires the presence of the PKCS#11 helper library (libpkcs11-helper)
+ */
+//#define MBEDTLS_PKCS11_C
+
+/**
+ * \def MBEDTLS_PKCS12_C
+ *
+ * Enable PKCS#12 PBE functions.
+ * Adds algorithms for parsing PKCS#8 encrypted private keys
+ *
+ * Module:  library/pkcs12.c
+ * Caller:  library/pkparse.c
+ *
+ * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C
+ * Can use:  MBEDTLS_ARC4_C
+ *
+ * This module enables PKCS#12 functions.
+ */
+//#define MBEDTLS_PKCS12_C
+
+/**
+ * \def MBEDTLS_PLATFORM_C
+ *
+ * Enable the platform abstraction layer that allows you to re-assign
+ * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit().
+ *
+ * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT
+ * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned
+ * above to be specified at runtime or compile time respectively.
+ *
+ * \note This abstraction layer must be enabled on Windows (including MSYS2)
+ * as other module rely on it for a fixed snprintf implementation.
+ *
+ * Module:  library/platform.c
+ * Caller:  Most other .c files
+ *
+ * This module enables abstraction of common (libc) functions.
+ */
+#define MBEDTLS_PLATFORM_C
+
+/**
+ * \def MBEDTLS_RIPEMD160_C
+ *
+ * Enable the RIPEMD-160 hash algorithm.
+ *
+ * Module:  library/ripemd160.c
+ * Caller:  library/md.c
+ *
+ */
+//#define MBEDTLS_RIPEMD160_C
+
+/**
+ * \def MBEDTLS_RSA_C
+ *
+ * Enable the RSA public-key cryptosystem.
+ *
+ * Module:  library/rsa.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509.c
+ *
+ * This module is used by the following key exchanges:
+ *      RSA, DHE-RSA, ECDHE-RSA, RSA-PSK
+ *
+ * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C
+ */
+//#define MBEDTLS_RSA_C
+
+/**
+ * \def MBEDTLS_SHA1_C
+ *
+ * Enable the SHA1 cryptographic hash algorithm.
+ *
+ * Module:  library/sha1.c
+ * Caller:  library/md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *          library/x509write_crt.c
+ *
+ * This module is required for SSL/TLS and SHA1-signed certificates.
+ */
+//#define MBEDTLS_SHA1_C
+
+/**
+ * \def MBEDTLS_SHA256_C
+ *
+ * Enable the SHA-224 and SHA-256 cryptographic hash algorithms.
+ *
+ * Module:  library/sha256.c
+ * Caller:  library/entropy.c
+ *          library/md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * This module adds support for SHA-224 and SHA-256.
+ * This module is required for the SSL/TLS 1.2 PRF function.
+ */
+#define MBEDTLS_SHA256_C
+
+/**
+ * \def MBEDTLS_SHA512_C
+ *
+ * Enable the SHA-384 and SHA-512 cryptographic hash algorithms.
+ *
+ * Module:  library/sha512.c
+ * Caller:  library/entropy.c
+ *          library/md.c
+ *          library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * This module adds support for SHA-384 and SHA-512.
+ */
+//#define MBEDTLS_SHA512_C
+
+/**
+ * \def MBEDTLS_SSL_CACHE_C
+ *
+ * Enable simple SSL cache implementation.
+ *
+ * Module:  library/ssl_cache.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SSL_CACHE_C
+ */
+#define MBEDTLS_SSL_CACHE_C
+
+/**
+ * \def MBEDTLS_SSL_COOKIE_C
+ *
+ * Enable basic implementation of DTLS cookies for hello verification.
+ *
+ * Module:  library/ssl_cookie.c
+ * Caller:
+ */
+#define MBEDTLS_SSL_COOKIE_C
+
+/**
+ * \def MBEDTLS_SSL_TICKET_C
+ *
+ * Enable an implementation of TLS server-side callbacks for session tickets.
+ *
+ * Module:  library/ssl_ticket.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_CIPHER_C
+ */
+#define MBEDTLS_SSL_TICKET_C
+
+/**
+ * \def MBEDTLS_SSL_CLI_C
+ *
+ * Enable the SSL/TLS client code.
+ *
+ * Module:  library/ssl_cli.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS client support.
+ */
+#define MBEDTLS_SSL_CLI_C
+
+/**
+ * \def MBEDTLS_SSL_SRV_C
+ *
+ * Enable the SSL/TLS server code.
+ *
+ * Module:  library/ssl_srv.c
+ * Caller:
+ *
+ * Requires: MBEDTLS_SSL_TLS_C
+ *
+ * This module is required for SSL/TLS server support.
+ */
+//#define MBEDTLS_SSL_SRV_C
+
+/**
+ * \def MBEDTLS_SSL_TLS_C
+ *
+ * Enable the generic SSL/TLS code.
+ *
+ * Module:  library/ssl_tls.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *
+ * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C
+ *           and at least one of the MBEDTLS_SSL_PROTO_XXX defines
+ *
+ * This module is required for SSL/TLS.
+ */
+#define MBEDTLS_SSL_TLS_C
+
+/**
+ * \def MBEDTLS_THREADING_C
+ *
+ * Enable the threading abstraction layer.
+ * By default mbed TLS assumes it is used in a non-threaded environment or that
+ * contexts are not shared between threads. If you do intend to use contexts
+ * between threads, you will need to enable this layer to prevent race
+ * conditions. See also our Knowledge Base article about threading:
+ * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading
+ *
+ * Module:  library/threading.c
+ *
+ * This allows different threading implementations (self-implemented or
+ * provided).
+ *
+ * You will have to enable either MBEDTLS_THREADING_ALT or
+ * MBEDTLS_THREADING_PTHREAD.
+ *
+ * Enable this layer to allow use of mutexes within mbed TLS
+ */
+//#define MBEDTLS_THREADING_C
+
+/**
+ * \def MBEDTLS_TIMING_C
+ *
+ * Enable the semi-portable timing interface.
+ *
+ * \note The provided implementation only works on POSIX/Unix (including Linux,
+ * BSD and OS X) and Windows. On other platforms, you can either disable that
+ * module and provide your own implementations of the callbacks needed by
+ * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide
+ * your own implementation of the whole module by setting
+ * \c MBEDTLS_TIMING_ALT in the current file.
+ *
+ * \note See also our Knowledge Base article about porting to a new
+ * environment:
+ * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
+ *
+ * Module:  library/timing.c
+ * Caller:  library/havege.c
+ *
+ * This module is used by the HAVEGE random number generator.
+ */
+//#define MBEDTLS_TIMING_C
+
+/**
+ * \def MBEDTLS_VERSION_C
+ *
+ * Enable run-time version information.
+ *
+ * Module:  library/version.c
+ *
+ * This module provides run-time version information.
+ */
+#define MBEDTLS_VERSION_C
+/**
+ * \def MBEDTLS_X509_USE_C
+ *
+ * Enable X.509 core for using certificates.
+ *
+ * Module:  library/x509.c
+ * Caller:  library/x509_crl.c
+ *          library/x509_crt.c
+ *          library/x509_csr.c
+ *
+ * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C,
+ *           MBEDTLS_PK_PARSE_C
+ *
+ * This module is required for the X.509 parsing modules.
+ */
+#define MBEDTLS_X509_USE_C
+
+/**
+ * \def MBEDTLS_X509_CRT_PARSE_C
+ *
+ * Enable X.509 certificate parsing.
+ *
+ * Module:  library/x509_crt.c
+ * Caller:  library/ssl_cli.c
+ *          library/ssl_srv.c
+ *          library/ssl_tls.c
+ *
+ * Requires: MBEDTLS_X509_USE_C
+ *
+ * This module is required for X.509 certificate parsing.
+ */
+#define MBEDTLS_X509_CRT_PARSE_C
+
+/**
+ * \def MBEDTLS_X509_CRL_PARSE_C
+ *
+ * Enable X.509 CRL parsing.
+ *
+ * Module:  library/x509_crl.c
+ * Caller:  library/x509_crt.c
+ *
+ * Requires: MBEDTLS_X509_USE_C
+ *
+ * This module is required for X.509 CRL parsing.
+ */
+#define MBEDTLS_X509_CRL_PARSE_C
+
+/**
+ * \def MBEDTLS_X509_CSR_PARSE_C
+ *
+ * Enable X.509 Certificate Signing Request (CSR) parsing.
+ *
+ * Module:  library/x509_csr.c
+ * Caller:  library/x509_crt_write.c
+ *
+ * Requires: MBEDTLS_X509_USE_C
+ *
+ * This module is used for reading X.509 certificate request.
+ */
+#define MBEDTLS_X509_CSR_PARSE_C
+
+/**
+ * \def MBEDTLS_X509_CREATE_C
+ *
+ * Enable X.509 core for creating certificates.
+ *
+ * Module:  library/x509_create.c
+ *
+ * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C
+ *
+ * This module is the basis for creating X.509 certificates and CSRs.
+ */
+#define MBEDTLS_X509_CREATE_C
+
+/**
+ * \def MBEDTLS_X509_CRT_WRITE_C
+ *
+ * Enable creating X.509 certificates.
+ *
+ * Module:  library/x509_crt_write.c
+ *
+ * Requires: MBEDTLS_X509_CREATE_C
+ *
+ * This module is required for X.509 certificate creation.
+ */
+//#define MBEDTLS_X509_CRT_WRITE_C
+
+/**
+ * \def MBEDTLS_X509_CSR_WRITE_C
+ *
+ * Enable creating X.509 Certificate Signing Requests (CSR).
+ *
+ * Module:  library/x509_csr_write.c
+ *
+ * Requires: MBEDTLS_X509_CREATE_C
+ *
+ * This module is required for X.509 certificate request writing.
+ */
+#define MBEDTLS_X509_CSR_WRITE_C
+/**
+ * \def MBEDTLS_XTEA_C
+ *
+ * Enable the XTEA block cipher.
+ *
+ * Module:  library/xtea.c
+ * Caller:
+ */
+//#define MBEDTLS_XTEA_C
+
+/* \} name SECTION: mbed TLS modules */
+
+/**
+ * \name SECTION: Module configuration options
+ *
+ * This section allows for the setting of module specific sizes and
+ * configuration options. The default values are already present in the
+ * relevant header files and should suffice for the regular use cases.
+ *
+ * Our advice is to enable options and change their values here
+ * only if you have a good reason and know the consequences.
+ *
+ * Please check the respective header file for documentation on these
+ * parameters (to prevent duplicate documentation).
+ * \{
+ */
+
+/* MPI / BIGNUM options */
+//#define MBEDTLS_MPI_WINDOW_SIZE            6 /**< Maximum windows size used. */
+//#define MBEDTLS_MPI_MAX_SIZE            1024 /**< Maximum number of bytes for usable MPIs. */
+
+/* CTR_DRBG options */
+//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN               48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */
+//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL        10000 /**< Interval before reseed is performed by default */
+//#define MBEDTLS_CTR_DRBG_MAX_INPUT                256 /**< Maximum number of additional input bytes */
+//#define MBEDTLS_CTR_DRBG_MAX_REQUEST             1024 /**< Maximum number of requested bytes per call */
+//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT           384 /**< Maximum size of (re)seed buffer */
+
+/* HMAC_DRBG options */
+//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL   10000 /**< Interval before reseed is performed by default */
+//#define MBEDTLS_HMAC_DRBG_MAX_INPUT           256 /**< Maximum number of additional input bytes */
+//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST        1024 /**< Maximum number of requested bytes per call */
+//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT      384 /**< Maximum size of (re)seed buffer */
+
+/* ECP options */
+//#define MBEDTLS_ECP_MAX_BITS             521 /**< Maximum bit size of groups */
+//#define MBEDTLS_ECP_WINDOW_SIZE            6 /**< Maximum window size used */
+//#define MBEDTLS_ECP_FIXED_POINT_OPTIM      1 /**< Enable fixed-point speed-up */
+
+/* Entropy options */
+//#define MBEDTLS_ENTROPY_MAX_SOURCES                20 /**< Maximum number of sources supported */
+//#define MBEDTLS_ENTROPY_MAX_GATHER                128 /**< Maximum amount requested from entropy sources */
+//#define MBEDTLS_ENTROPY_MIN_HARDWARE               32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */
+
+/* Memory buffer allocator options */
+//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE      4 /**< Align on multiples of this value */
+
+/* Platform options */
+//#define MBEDTLS_PLATFORM_STD_MEM_HDR   <stdlib.h> /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */
+//#define MBEDTLS_PLATFORM_STD_CALLOC        calloc /**< Default allocator to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_FREE            free /**< Default free to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_EXIT            exit /**< Default exit to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_TIME            time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
+//#define MBEDTLS_PLATFORM_STD_FPRINTF      fprintf /**< Default fprintf to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_PRINTF        printf /**< Default printf to use, can be undefined */
+/* Note: your snprintf must correclty zero-terminate the buffer! */
+//#define MBEDTLS_PLATFORM_STD_SNPRINTF    snprintf /**< Default snprintf to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS       0 /**< Default exit value to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE       1 /**< Default exit value to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ   mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE  mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE  "seedfile" /**< Seed file to read/write with default implementation */
+
+/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */
+/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */
+//#define MBEDTLS_PLATFORM_CALLOC_MACRO        calloc /**< Default allocator macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_FREE_MACRO            free /**< Default free macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_EXIT_MACRO            exit /**< Default exit macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_TIME_MACRO            time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
+//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO       time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */
+//#define MBEDTLS_PLATFORM_FPRINTF_MACRO      fprintf /**< Default fprintf macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_PRINTF_MACRO        printf /**< Default printf macro to use, can be undefined */
+/* Note: your snprintf must correclty zero-terminate the buffer! */
+//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO    snprintf /**< Default snprintf macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO   mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
+//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO  mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
+
+/* SSL Cache options */
+//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT       86400 /**< 1 day  */
+//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES      50 /**< Maximum entries in cache */
+
+/* SSL options */
+#define MBEDTLS_SSL_MAX_CONTENT_LEN             4096 /**< Maxium fragment length in bytes, determines the size of each of the two internal I/O buffers */
+//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME     86400 /**< Lifetime of session tickets (if enabled) */
+//#define MBEDTLS_PSK_MAX_LEN               32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */
+//#define MBEDTLS_SSL_COOKIE_TIMEOUT        60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
+
+/**
+ * Enable ARIA ciphersuites.
+ */
+
+#define MBEDTLS_ARIA_C
+
+/**
+ * Complete list of ciphersuites to use, in order of preference.
+ *
+ * \warning No dependency checking is done on that field! This option can only
+ * be used to restrict the set of available ciphersuites. It is your
+ * responsibility to make sure the needed modules are active.
+ *
+ * Use this to save a few hundred bytes of ROM (default ordering of all
+ * available ciphersuites) and a few to a few hundred bytes of RAM.
+ *
+ * The value below is only an example, not the default.
+ */
+#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, \
+                                 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \
+                                 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \
+                                 MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, \
+                                 MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, \
+                                 MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, \
+                                 MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, \
+                                 MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256
+/* X509 options */
+//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA   8   /**< Maximum number of intermediate CAs in a verification chain. */
+//#define MBEDTLS_X509_MAX_FILE_PATH_LEN     512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */
+
+/* \} name SECTION: Customisation configuration options */
+
+/* Target and application specific configurations */
+//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "mbedtls/target_config.h"
+
+#if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE)
+#include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE
+#endif
+
+
+#include "check_config.h"
+
+#if defined(MBEDTLS_TEST_NULL_ENTROPY)
+#warning "MBEDTLS_TEST_NULL_ENTROPY has been enabled. This " \
+    "configuration is not secure and is not suitable for production use"
+#endif
+
+#endif /* MBEDTLS_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_mbedOS.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,270 @@
+//----------------------------------------------------------------------------
+// The confidential and proprietary information contained in this file may
+// only be used by a person authorised under and to the extent permitted
+// by a subsisting licensing agreement from ARM Limited or its affiliates.
+//
+// (C) COPYRIGHT 2016 ARM Limited or its affiliates.
+// ALL RIGHTS RESERVED
+//
+// This entire notice must be reproduced on all copies of this file
+// and copies of this file may only be made by a person if such person is
+// permitted to do so under the terms of a subsisting license agreement
+// from ARM Limited or its affiliates.
+//----------------------------------------------------------------------------
+
+#ifndef PAL_MBEDTLS_USER_CONFIG_H
+#define PAL_MBEDTLS_USER_CONFIG_H
+
+
+/*! All of the following definitions are mandatory requirements for correct 
+*   fucntionality of PAL TLS and Crypto components.
+*   Please do not disable them.
+*/
+
+/* Platform has time function to provide time for certificates verifications */
+#if 1 //Please set to 1 if you are using secure time
+#ifndef MBEDTLS_HAVE_TIME
+    #define MBEDTLS_HAVE_TIME
+#endif //MBEDTLS_HAVE_TIME
+
+#ifndef MBEDTLS_HAVE_TIME_DATE
+    #define MBEDTLS_HAVE_TIME_DATE
+#endif //MBEDTLS_HAVE_TIME_DATE
+
+#ifndef MBEDTLS_PLATFORM_TIME_ALT
+    #define MBEDTLS_PLATFORM_TIME_ALT
+#endif //MBEDTLS_PLATFORM_TIME_ALT
+
+/* System support */
+#ifndef MBEDTLS_HAVE_ASM
+    #define MBEDTLS_HAVE_ASM
+#endif //MBEDTLS_HAVE_ASM
+#endif
+/* mbed TLS feature support */
+#ifndef MBEDTLS_ECP_DP_SECP256R1_ENABLED
+    #define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#endif //MBEDTLS_ECP_DP_SECP256R1_ENABLED
+
+#ifndef MBEDTLS_ECP_NIST_OPTIM
+    #define MBEDTLS_ECP_NIST_OPTIM
+#endif //MBEDTLS_ECP_NIST_OPTIM
+
+#ifndef MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+    #define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+#endif //MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+
+#ifndef MBEDTLS_SSL_PROTO_TLS1_2
+    #define MBEDTLS_SSL_PROTO_TLS1_2
+#endif //MBEDTLS_SSL_PROTO_TLS1_2
+
+#ifndef MBEDTLS_SSL_PROTO_DTLS
+    #define MBEDTLS_SSL_PROTO_DTLS
+#endif //MBEDTLS_SSL_PROTO_DTLS
+
+#ifndef MBEDTLS_SSL_DTLS_ANTI_REPLAY
+    #define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#endif //MBEDTLS_SSL_DTLS_ANTI_REPLAY
+
+#ifndef MBEDTLS_SSL_DTLS_HELLO_VERIFY
+    #define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+#endif //MBEDTLS_SSL_DTLS_HELLO_VERIFY
+
+#ifndef MBEDTLS_SSL_EXPORT_KEYS
+    #define MBEDTLS_SSL_EXPORT_KEYS
+#endif //MBEDTLS_SSL_EXPORT_KEYS
+
+/* mbed TLS modules */
+#ifndef MBEDTLS_AES_C
+    #define MBEDTLS_AES_C
+#endif //MBEDTLS_AES_C
+
+#ifndef MBEDTLS_ASN1_PARSE_C
+    #define MBEDTLS_ASN1_PARSE_C
+#endif //MBEDTLS_ASN1_PARSE_C
+
+#ifndef MBEDTLS_ASN1_WRITE_C
+    #define MBEDTLS_ASN1_WRITE_C
+#endif //MBEDTLS_ASN1_WRITE_C
+
+#ifndef MBEDTLS_BIGNUM_C
+    #define MBEDTLS_BIGNUM_C
+#endif //MBEDTLS_BIGNUM_C
+
+#ifndef MBEDTLS_CIPHER_C
+    #define MBEDTLS_CIPHER_C
+#endif //MBEDTLS_CIPHER_C
+
+#ifndef MBEDTLS_CTR_DRBG_C
+    #define MBEDTLS_CTR_DRBG_C
+#endif //MBEDTLS_CTR_DRBG_C
+
+#ifndef MBEDTLS_ECP_C
+    #define MBEDTLS_ECP_C
+#endif //MBEDTLS_ECP_C
+
+#ifndef MBEDTLS_ENTROPY_C
+    #define MBEDTLS_ENTROPY_C
+#endif //MBEDTLS_ENTROPY_C
+
+#ifndef MBEDTLS_MD_C
+    #define MBEDTLS_MD_C
+#endif //MBEDTLS_MD_C
+
+#ifndef MBEDTLS_OID_C
+    #define MBEDTLS_OID_C
+#endif //MBEDTLS_OID_C
+
+#ifndef MBEDTLS_PK_C
+    #define MBEDTLS_PK_C
+#endif //MBEDTLS_PK_C
+
+#ifndef MBEDTLS_PK_PARSE_C
+    #define MBEDTLS_PK_PARSE_C
+#endif //MBEDTLS_PK_PARSE_C
+
+#ifndef MBEDTLS_SHA256_C
+    #define MBEDTLS_SHA256_C
+#endif //MBEDTLS_SHA256_C
+
+#ifndef MBEDTLS_SSL_COOKIE_C
+    #define MBEDTLS_SSL_COOKIE_C
+#endif //MBEDTLS_SSL_COOKIE_C
+
+#ifndef MBEDTLS_SSL_CLI_C
+    #define MBEDTLS_SSL_CLI_C
+#endif //MBEDTLS_SSL_CLI_C
+
+#ifndef MBEDTLS_SSL_TLS_C
+    #define MBEDTLS_SSL_TLS_C
+#endif //MBEDTLS_SSL_TLS_C
+// XXX mbedclient needs these: mbedtls_x509_crt_free, mbedtls_x509_crt_init, mbedtls_x509_crt_parse
+#ifndef MBEDTLS_X509_USE_C
+    #define MBEDTLS_X509_USE_C
+#endif //MBEDTLS_X509_USE_C
+
+#ifndef MBEDTLS_X509_CRT_PARSE_C
+    #define MBEDTLS_X509_CRT_PARSE_C
+#endif //MBEDTLS_X509_CRT_PARSE_C
+// a bit wrong way to get mbedtls_ssl_conf_psk:
+#ifndef MBEDTLS_CMAC_C
+    #define MBEDTLS_CMAC_C
+#endif //MBEDTLS_CMAC_C
+
+#ifndef MBEDTLS_ECDH_C
+    #define MBEDTLS_ECDH_C
+#endif //MBEDTLS_ECDH_C
+
+#ifndef MBEDTLS_ECDSA_C
+    #define MBEDTLS_ECDSA_C
+#endif //MBEDTLS_ECDSA_C
+
+#ifndef MBEDTLS_GCM_C
+    #define MBEDTLS_GCM_C
+#endif //MBEDTLS_GCM_C
+
+#ifndef MBEDTLS_X509_CRT_PARSE_C
+    #define MBEDTLS_X509_CRT_PARSE_C
+#endif //MBEDTLS_X509_CRT_PARSE_C
+
+#ifndef MBEDTLS_X509_CSR_PARSE_C
+    #define MBEDTLS_X509_CSR_PARSE_C
+#endif //MBEDTLS_X509_CSR_PARSE_C
+
+#ifndef MBEDTLS_X509_CREATE_C
+    #define MBEDTLS_X509_CREATE_C
+#endif //MBEDTLS_X509_CREATE_C
+
+#ifndef MBEDTLS_X509_CSR_WRITE_C
+    #define MBEDTLS_X509_CSR_WRITE_C
+#endif //MBEDTLS_X509_CSR_WRITE_C
+
+#ifndef MBEDTLS_CTR_DRBG_MAX_REQUEST
+    #define MBEDTLS_CTR_DRBG_MAX_REQUEST 2048
+#endif //MBEDTLS_CTR_DRBG_MAX_REQUEST
+
+// Needed by update
+#ifndef MBEDTLS_CIPHER_MODE_CTR
+    #define MBEDTLS_CIPHER_MODE_CTR
+#endif //MBEDTLS_CIPHER_MODE_CTR
+
+// Save ROM and a few bytes of RAM by specifying our own ciphersuite list
+#ifndef MBEDTLS_SSL_CIPHERSUITES
+    #define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, \
+                                     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \
+                                     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \
+                                     MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, \
+                                     MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, \
+                                     MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
+#endif //MBEDTLS_SSL_CIPHERSUITES
+
+/*! All of the following definitions are optimizations (reduce mbedTLS memory usage and size),
+*   changing them is on the user responsibility since they can enlarge
+*   the binary footprint and the memory usage
+*/
+
+// define to save 8KB RAM at the expense of ROM
+#ifndef MBEDTLS_AES_ROM_TABLES
+    #define MBEDTLS_AES_ROM_TABLES
+#endif //MBEDTLS_AES_ROM_TABLES
+
+// Reduce IO buffer to save RAM, default is 16KB
+#ifndef MBEDTLS_SSL_MAX_CONTENT_LEN
+    #define MBEDTLS_SSL_MAX_CONTENT_LEN 4096
+#endif //MBEDTLS_SSL_MAX_CONTENT_LEN
+
+// needed for Base64 encoding Opaque data for
+// registration payload, adds 500 bytes to flash.
+#ifndef MBEDTLS_BASE64_C
+    #define MBEDTLS_BASE64_C
+#endif // MBEDTLS_BASE64_C
+
+// Needed by provisioning
+#undef MBEDTLS_PEM_WRITE_C
+
+// Remove RSA, save 20KB at total
+#if !MBED_CONF_MBED_CLIENT_PAL_RSA_REQUIRED
+    #undef MBEDTLS_RSA_C
+    #undef MBEDTLS_PK_RSA_ALT_SUPPORT
+    #undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+    #undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+    #undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+#endif // MBED_CONF_MBED_CLIENT_PAL_RSA_REQUIRED
+
+// Remove error messages, save 10KB of ROM
+#undef MBEDTLS_ERROR_C
+
+// Remove selftesting and save 11KB of ROM
+#undef MBEDTLS_SELF_TEST
+
+#undef MBEDTLS_CERTS_C
+
+// Reduces ROM size by 30 kB
+#undef MBEDTLS_ERROR_STRERROR_DUMMY
+
+#undef MBEDTLS_VERSION_FEATURES
+
+#undef MBEDTLS_DEBUG_C
+
+// needed for parsing the certificates
+#undef MBEDTLS_PEM_PARSE_C
+
+#undef MBEDTLS_SHA512_C
+
+#undef MBEDTLS_SSL_SRV_C
+
+#undef MBEDTLS_ECP_DP_SECP192R1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP224R1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP521R1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP192K1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP224K1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP256K1_ENABLED
+#undef MBEDTLS_ECP_DP_BP256R1_ENABLED
+#undef MBEDTLS_ECP_DP_BP384R1_ENABLED
+#undef MBEDTLS_ECP_DP_BP512R1_ENABLED
+#undef MBEDTLS_ECP_DP_CURVE25519_ENABLED
+
+
+#include "mbedtls/check_config.h"
+
+#endif /* PAL_MBEDTLS_USER_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/mbedTLS/mbedTLSConfig_mbedOS_SW_TRNG.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,284 @@
+//----------------------------------------------------------------------------
+// The confidential and proprietary information contained in this file may
+// only be used by a person authorised under and to the extent permitted
+// by a subsisting licensing agreement from ARM Limited or its affiliates.
+//
+// (C) COPYRIGHT 2018 ARM Limited or its affiliates.
+// ALL RIGHTS RESERVED
+//
+// This entire notice must be reproduced on all copies of this file
+// and copies of this file may only be made by a person if such person is
+// permitted to do so under the terms of a subsisting license agreement
+// from ARM Limited or its affiliates.
+//----------------------------------------------------------------------------
+
+#ifndef PAL_MBEDTLS_USER_CONFIG_H
+#define PAL_MBEDTLS_USER_CONFIG_H
+
+
+/*! All of the following definitions are mandatory requirements for correct 
+*   functionality of PAL TLS and Crypto components.
+*   Please do not disable them.
+*/
+
+/* Platform has time function to provide time for certificates verifications */
+#ifndef MBEDTLS_HAVE_TIME
+    #define MBEDTLS_HAVE_TIME
+#endif //MBEDTLS_HAVE_TIME
+
+#ifndef MBEDTLS_HAVE_TIME_DATE
+    #define MBEDTLS_HAVE_TIME_DATE
+#endif //MBEDTLS_HAVE_TIME_DATE
+
+#ifndef MBEDTLS_PLATFORM_TIME_ALT
+    #define MBEDTLS_PLATFORM_TIME_ALT
+#endif //MBEDTLS_PLATFORM_TIME_ALT
+
+/* System support */
+#ifndef MBEDTLS_HAVE_ASM
+    #define MBEDTLS_HAVE_ASM
+#endif //MBEDTLS_HAVE_ASM
+
+/* mbed TLS feature support */
+#ifndef MBEDTLS_ECP_DP_SECP256R1_ENABLED
+    #define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#endif //MBEDTLS_ECP_DP_SECP256R1_ENABLED
+
+#ifndef MBEDTLS_ECP_NIST_OPTIM
+    #define MBEDTLS_ECP_NIST_OPTIM
+#endif //MBEDTLS_ECP_NIST_OPTIM
+
+#ifndef MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+    #define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+#endif //MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+
+#ifndef MBEDTLS_SSL_PROTO_TLS1_2
+    #define MBEDTLS_SSL_PROTO_TLS1_2
+#endif //MBEDTLS_SSL_PROTO_TLS1_2
+
+#ifndef MBEDTLS_SSL_PROTO_DTLS
+    #define MBEDTLS_SSL_PROTO_DTLS
+#endif //MBEDTLS_SSL_PROTO_DTLS
+
+#ifndef MBEDTLS_SSL_DTLS_ANTI_REPLAY
+    #define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#endif //MBEDTLS_SSL_DTLS_ANTI_REPLAY
+
+#ifndef MBEDTLS_SSL_DTLS_HELLO_VERIFY
+    #define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+#endif //MBEDTLS_SSL_DTLS_HELLO_VERIFY
+
+#ifndef MBEDTLS_SSL_EXPORT_KEYS
+    #define MBEDTLS_SSL_EXPORT_KEYS
+#endif //MBEDTLS_SSL_EXPORT_KEYS
+
+/* mbed TLS modules */
+#ifndef MBEDTLS_AES_C
+    #define MBEDTLS_AES_C
+#endif //MBEDTLS_AES_C
+
+#ifndef MBEDTLS_ASN1_PARSE_C
+    #define MBEDTLS_ASN1_PARSE_C
+#endif //MBEDTLS_ASN1_PARSE_C
+
+#ifndef MBEDTLS_ASN1_WRITE_C
+    #define MBEDTLS_ASN1_WRITE_C
+#endif //MBEDTLS_ASN1_WRITE_C
+
+#ifndef MBEDTLS_BIGNUM_C
+    #define MBEDTLS_BIGNUM_C
+#endif //MBEDTLS_BIGNUM_C
+
+#ifndef MBEDTLS_CIPHER_C
+    #define MBEDTLS_CIPHER_C
+#endif //MBEDTLS_CIPHER_C
+
+#ifndef MBEDTLS_CTR_DRBG_C
+    #define MBEDTLS_CTR_DRBG_C
+#endif //MBEDTLS_CTR_DRBG_C
+
+#ifndef MBEDTLS_ECP_C
+    #define MBEDTLS_ECP_C
+#endif //MBEDTLS_ECP_C
+
+#ifndef MBEDTLS_ENTROPY_NV_SEED
+    #define MBEDTLS_ENTROPY_NV_SEED
+#endif //MBEDTLS_ENTROPY_NV_SEED
+
+#ifndef MBEDTLS_NO_PLATFORM_ENTROPY
+    #define MBEDTLS_NO_PLATFORM_ENTROPY
+#endif //MBEDTLS_NO_PLATFORM_ENTROPY
+
+#ifndef MBEDTLS_ENTROPY_C
+    #define MBEDTLS_ENTROPY_C
+#endif //MBEDTLS_ENTROPY_C
+
+#ifndef MBEDTLS_MD_C
+    #define MBEDTLS_MD_C
+#endif //MBEDTLS_MD_C
+
+#ifndef MBEDTLS_OID_C
+    #define MBEDTLS_OID_C
+#endif //MBEDTLS_OID_C
+
+#ifndef MBEDTLS_PK_C
+    #define MBEDTLS_PK_C
+#endif //MBEDTLS_PK_C
+
+#ifndef MBEDTLS_PK_PARSE_C
+    #define MBEDTLS_PK_PARSE_C
+#endif //MBEDTLS_PK_PARSE_C
+
+#ifndef MBEDTLS_SHA256_C
+    #define MBEDTLS_SHA256_C
+#endif //MBEDTLS_SHA256_C
+
+#ifndef MBEDTLS_SSL_COOKIE_C
+    #define MBEDTLS_SSL_COOKIE_C
+#endif //MBEDTLS_SSL_COOKIE_C
+
+#ifndef MBEDTLS_SSL_CLI_C
+    #define MBEDTLS_SSL_CLI_C
+#endif //MBEDTLS_SSL_CLI_C
+
+#ifndef MBEDTLS_SSL_TLS_C
+    #define MBEDTLS_SSL_TLS_C
+#endif //MBEDTLS_SSL_TLS_C
+// XXX mbedclient needs these: mbedtls_x509_crt_free, mbedtls_x509_crt_init, mbedtls_x509_crt_parse
+#ifndef MBEDTLS_X509_USE_C
+    #define MBEDTLS_X509_USE_C
+#endif //MBEDTLS_X509_USE_C
+
+#ifndef MBEDTLS_X509_CRT_PARSE_C
+    #define MBEDTLS_X509_CRT_PARSE_C
+#endif //MBEDTLS_X509_CRT_PARSE_C
+// a bit wrong way to get mbedtls_ssl_conf_psk:
+#ifndef MBEDTLS_CMAC_C
+    #define MBEDTLS_CMAC_C
+#endif //MBEDTLS_CMAC_C
+
+#ifndef MBEDTLS_ECDH_C
+    #define MBEDTLS_ECDH_C
+#endif //MBEDTLS_ECDH_C
+
+#ifndef MBEDTLS_ECDSA_C
+    #define MBEDTLS_ECDSA_C
+#endif //MBEDTLS_ECDSA_C
+
+#ifndef MBEDTLS_GCM_C
+    #define MBEDTLS_GCM_C
+#endif //MBEDTLS_GCM_C
+
+#ifndef MBEDTLS_X509_CRT_PARSE_C
+    #define MBEDTLS_X509_CRT_PARSE_C
+#endif //MBEDTLS_X509_CRT_PARSE_C
+
+#ifndef MBEDTLS_X509_CSR_PARSE_C
+    #define MBEDTLS_X509_CSR_PARSE_C
+#endif //MBEDTLS_X509_CSR_PARSE_C
+
+#ifndef MBEDTLS_X509_CREATE_C
+    #define MBEDTLS_X509_CREATE_C
+#endif //MBEDTLS_X509_CREATE_C
+
+#ifndef MBEDTLS_X509_CSR_WRITE_C
+    #define MBEDTLS_X509_CSR_WRITE_C
+#endif //MBEDTLS_X509_CSR_WRITE_C
+
+#ifndef MBEDTLS_CTR_DRBG_MAX_REQUEST
+    #define MBEDTLS_CTR_DRBG_MAX_REQUEST 2048
+#endif //MBEDTLS_CTR_DRBG_MAX_REQUEST
+
+// Needed by update
+#ifndef MBEDTLS_CIPHER_MODE_CTR
+    #define MBEDTLS_CIPHER_MODE_CTR
+#endif //MBEDTLS_CIPHER_MODE_CTR
+
+// Save ROM and a few bytes of RAM by specifying our own ciphersuite list
+#ifndef MBEDTLS_SSL_CIPHERSUITES
+    #define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, \
+                                     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \
+                                     MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \
+                                     MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, \
+                                     MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, \
+                                     MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256
+#endif //MBEDTLS_SSL_CIPHERSUITES
+
+/*! All of the following definitions are optimizations (reduce mbedTLS memory usage and size),
+*   changing them is on the user responsibility since they can enlarge
+*   the binary footprint and the memory usage
+*/
+
+// define to save 8KB RAM at the expense of ROM
+#ifndef MBEDTLS_AES_ROM_TABLES
+    #define MBEDTLS_AES_ROM_TABLES
+#endif //MBEDTLS_AES_ROM_TABLES
+
+// Reduce IO buffer to save RAM, default is 16KB
+#ifndef MBEDTLS_SSL_MAX_CONTENT_LEN
+    #define MBEDTLS_SSL_MAX_CONTENT_LEN 4096
+#endif //MBEDTLS_SSL_MAX_CONTENT_LEN
+
+// Needed by provisioning
+#undef MBEDTLS_PEM_WRITE_C
+
+// Remove RSA, save 20KB at total
+#undef MBEDTLS_RSA_C
+
+#undef MBEDTLS_PK_RSA_ALT_SUPPORT
+
+#undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+
+#undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+
+#undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+
+//#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+   
+// Remove error messages, save 10KB of ROM
+#undef MBEDTLS_ERROR_C
+
+// Remove selftesting and save 11KB of ROM
+#undef MBEDTLS_SELF_TEST
+
+#undef MBEDTLS_CERTS_C
+
+// Reduces ROM size by 30 kB
+#undef MBEDTLS_ERROR_STRERROR_DUMMY
+
+#undef MBEDTLS_VERSION_FEATURES
+
+#undef MBEDTLS_DEBUG_C
+
+// needed for parsing the certificates
+#undef MBEDTLS_PEM_PARSE_C
+
+
+// dep of the previous
+#undef MBEDTLS_BASE64_C
+
+#undef MBEDTLS_SHA512_C
+
+#undef MBEDTLS_SSL_SRV_C
+
+#undef MBEDTLS_ECP_DP_SECP192R1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP224R1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP521R1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP192K1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP224K1_ENABLED
+#undef MBEDTLS_ECP_DP_SECP256K1_ENABLED
+#undef MBEDTLS_ECP_DP_BP256R1_ENABLED
+#undef MBEDTLS_ECP_DP_BP384R1_ENABLED
+#undef MBEDTLS_ECP_DP_BP512R1_ENABLED
+#undef MBEDTLS_ECP_DP_CURVE25519_ENABLED
+
+#define MBEDTLS_PLATFORM_TIME_ALT
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_SSL_RENEGOTIATION
+
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+
+#include "mbedtls/check_config.h"
+
+#endif /* PAL_MBEDTLS_USER_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+Linux/*
+FreeRTOS/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/FreeRTOS/FreeRTOS_HW_RoT_HW_RTC_NOFLASH_2Partitions.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef PAL_USE_HW_ROT 
+    #define PAL_USE_HW_ROT     1
+#endif
+
+#ifndef PAL_USE_HW_RTC
+    #define PAL_USE_HW_RTC    1
+#endif
+
+#ifndef PAL_USE_INTERNAL_FLASH 
+    #define PAL_USE_INTERNAL_FLASH  0
+#endif
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+    #define PAL_INT_FLASH_NUM_SECTIONS 0
+#endif
+
+#ifndef PAL_NUMBER_OF_PARTITIONS
+    #define PAL_NUMBER_OF_PARTITIONS 2
+#endif 
+
+#define PAL_SKIP_TEST_MODULE_RTOS
+#define PAL_SKIP_TEST_MODULE_NETWORK
+#define PAL_SKIP_TEST_MODULE_CRYPTO
+#define PAL_SKIP_TEST_MODULE_UPDATE
+#define PAL_SKIP_TEST_MODULE_TLS
+#define PAL_SKIP_TEST_MODULE_INTERNALFLASH
+
+#include "FreeRTOS_default.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/FreeRTOS/FreeRTOS_SW_RoT_SW_RTC_2FLASH.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef PAL_USE_HW_ROT 
+    #define PAL_USE_HW_ROT     0
+#endif
+
+#ifndef PAL_USE_HW_RTC
+    #define PAL_USE_HW_RTC    0
+#endif
+
+#ifndef PAL_USE_INTERNAL_FLASH 
+    #define PAL_USE_INTERNAL_FLASH  1
+#endif
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+    #define PAL_INT_FLASH_NUM_SECTIONS 2
+#endif
+
+#define PAL_SKIP_TEST_MODULE_RTOS
+#define PAL_SKIP_TEST_MODULE_NETWORK
+#define PAL_SKIP_TEST_MODULE_CRYPTO
+#define PAL_SKIP_TEST_MODULE_FILESYSTEM
+#define PAL_SKIP_TEST_MODULE_UPDATE
+#define PAL_SKIP_TEST_MODULE_TLS
+#define PAL_SKIP_TEST_MODULE_INTERNALFLASH
+
+#include "FreeRTOS_default.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/FreeRTOS/FreeRTOS_crypto_only.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright 2016, 2018 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef PAL_FREERTOS_CONFIGURATION_H_
+/*! \brief This file sets configuration for PAL porting on FreeRTOS.
+    \note All configurations that are configured in this file overwrite their defaults values
+    \note Default Values can be found at Sources/PAL-impl/Services-API/pal_configuration.h
+    \note
+  */
+
+
+//!< Number partitions on SD card used by PAL File System;
+#ifndef PAL_NUMBER_OF_PARTITIONS
+    #define PAL_NUMBER_OF_PARTITIONS 1
+#endif
+
+//!< Mount point for primary file system partition
+#ifndef PAL_FS_MOUNT_POINT_PRIMARY
+    #if (PAL_NUMBER_OF_PARTITIONS == 0)
+        #define PAL_FS_MOUNT_POINT_PRIMARY    "2:"                                                       //!< User should change this for the his working folder
+    #elif (PAL_NUMBER_OF_PARTITIONS == 1)
+        #define PAL_FS_MOUNT_POINT_PRIMARY    "0:"
+    #else
+        #define PAL_FS_MOUNT_POINT_PRIMARY    "0:"
+    #endif
+#endif
+
+//!< Mount point for secondary file system partition
+#ifndef PAL_FS_MOUNT_POINT_SECONDARY
+    #if (PAL_NUMBER_OF_PARTITIONS == 0)
+        #define PAL_FS_MOUNT_POINT_SECONDARY    "2:"
+    #elif (PAL_NUMBER_OF_PARTITIONS == 1)
+        #define PAL_FS_MOUNT_POINT_SECONDARY    "0:"
+    #else
+        #define PAL_FS_MOUNT_POINT_SECONDARY    "1:"                                                    //!< User should change this for the his working folder
+    #endif
+#endif
+
+ //!< Max number of allowed timer
+#ifndef PAL_MAX_NUM_OF_TIMERS
+    #define PAL_MAX_NUM_OF_TIMERS 5
+#endif
+
+//!< Max given token for a semaphore
+#ifndef PAL_SEMAPHORE_MAX_COUNT
+    #define PAL_SEMAPHORE_MAX_COUNT 255
+#endif
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+    #define PAL_INT_FLASH_NUM_SECTIONS 2
+#endif
+
+ /*\brief  Starting Address for section 1 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_ADDRESS
+    #define PAL_INTERNAL_FLASH_SECTION_1_ADDRESS    0xFE000
+#endif
+
+/*\brief  Starting Address for section 2 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_ADDRESS
+    #define PAL_INTERNAL_FLASH_SECTION_2_ADDRESS    0xFF000
+#endif
+
+/*\brief  Size for section 1*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_SIZE
+    #define PAL_INTERNAL_FLASH_SECTION_1_SIZE       0x1000
+#endif
+
+/*\brief  Size for section 2*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_SIZE
+    #define PAL_INTERNAL_FLASH_SECTION_2_SIZE       0x1000
+#endif
+
+#ifndef PAL_USE_INTERNAL_FLASH 
+    #define PAL_USE_INTERNAL_FLASH  1
+#endif
+
+#ifndef PAL_USE_HW_ROT
+    #define PAL_USE_HW_ROT     0
+#endif
+
+#ifndef PAL_USE_HW_RTC
+    #define PAL_USE_HW_RTC    0
+#endif
+
+#define PAL_SKIP_TEST_MODULE_TLS
+#define PAL_SKIP_TEST_MODULE_SOTP
+#define PAL_SKIP_TEST_MODULE_RTOS
+#define PAL_SKIP_TEST_MODULE_NETWORK
+#define PAL_SKIP_TEST_MODULE_FILESYSTEM
+#define PAL_SKIP_TEST_MODULE_UPDATE
+#define PAL_SKIP_TEST_MODULE_INTERNALFLASH
+
+#endif /* PAL_FREERTOS_CONFIGURATION_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/FreeRTOS/FreeRTOS_default.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef PAL_FREERTOS_CONFIGURATION_H_
+/*! \brief This file sets configuration for PAL porting on FreeRTOS.
+    \note All configurations that are configured in this file overwrite their defaults values
+    \note Default Values can be found at Sources/PAL-impl/Services-API/pal_configuration.h
+    \note
+  */
+
+
+//!< Number partitions on SD card used by PAL File System;
+#ifndef PAL_NUMBER_OF_PARTITIONS
+    #define PAL_NUMBER_OF_PARTITIONS 1
+#endif
+
+//!< Mount point for primary file system partition
+#ifndef PAL_FS_MOUNT_POINT_PRIMARY
+    #if (PAL_NUMBER_OF_PARTITIONS == 0)
+        #define PAL_FS_MOUNT_POINT_PRIMARY    "2:"                                                       //!< User should change this for the his working folder
+    #elif (PAL_NUMBER_OF_PARTITIONS == 1)
+        #define PAL_FS_MOUNT_POINT_PRIMARY    "0:"
+    #else
+        #define PAL_FS_MOUNT_POINT_PRIMARY    "0:"
+    #endif
+#endif
+
+//!< Mount point for secondary file system partition
+#ifndef PAL_FS_MOUNT_POINT_SECONDARY
+    #if (PAL_NUMBER_OF_PARTITIONS == 0)
+        #define PAL_FS_MOUNT_POINT_SECONDARY    "2:"
+    #elif (PAL_NUMBER_OF_PARTITIONS == 1)
+        #define PAL_FS_MOUNT_POINT_SECONDARY    "0:"
+    #else
+        #define PAL_FS_MOUNT_POINT_SECONDARY    "1:"                                                    //!< User should change this for the his working folder
+    #endif
+#endif
+
+ //!< Max number of allowed timer
+#ifndef PAL_MAX_NUM_OF_TIMERS
+    #define PAL_MAX_NUM_OF_TIMERS 5
+#endif
+
+//!< Max given token for a semaphore
+#ifndef PAL_SEMAPHORE_MAX_COUNT
+    #define PAL_SEMAPHORE_MAX_COUNT 255
+#endif
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+    #define PAL_INT_FLASH_NUM_SECTIONS 2
+#endif
+
+ /*\brief  Starting Address for section 1 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_ADDRESS
+    #define PAL_INTERNAL_FLASH_SECTION_1_ADDRESS    0xFE000
+#endif
+
+/*\brief  Starting Address for section 2 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_ADDRESS
+    #define PAL_INTERNAL_FLASH_SECTION_2_ADDRESS    0xFF000
+#endif
+
+/*\brief  Size for section 1*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_SIZE
+    #define PAL_INTERNAL_FLASH_SECTION_1_SIZE       0x1000
+#endif
+
+/*\brief  Size for section 2*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_SIZE
+    #define PAL_INTERNAL_FLASH_SECTION_2_SIZE       0x1000
+#endif
+
+#ifndef PAL_USE_INTERNAL_FLASH 
+    #define PAL_USE_INTERNAL_FLASH  1
+#endif
+
+#ifndef PAL_USE_HW_ROT
+    #define PAL_USE_HW_ROT     0
+#endif
+
+#ifndef PAL_USE_HW_RTC
+    #define PAL_USE_HW_RTC    0
+#endif
+#endif /* PAL_FREERTOS_CONFIGURATION_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/Linux/Linux_HW_RoT_HW_RTC_NOFLASH_2Partitions.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef PAL_USE_HW_ROT 
+    #define PAL_USE_HW_ROT     1
+#endif
+
+#ifndef PAL_USE_HW_RTC
+    #define PAL_USE_HW_RTC    1
+#endif
+
+#ifndef PAL_USE_INTERNAL_FLASH 
+    #define PAL_USE_INTERNAL_FLASH  0
+#endif
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+    #define PAL_INT_FLASH_NUM_SECTIONS 0
+#endif
+
+#ifndef PAL_NUMBER_OF_PARTITIONS
+    #define PAL_NUMBER_OF_PARTITIONS 2
+#endif 
+
+#define PAL_SKIP_TEST_MODULE_RTOS
+#define PAL_SKIP_TEST_MODULE_NETWORK
+#define PAL_SKIP_TEST_MODULE_CRYPTO
+#define PAL_SKIP_TEST_MODULE_UPDATE
+#define PAL_SKIP_TEST_MODULE_TLS
+#define PAL_SKIP_TEST_MODULE_INTERNALFLASH
+
+
+
+#include "Linux_default.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/Linux/Linux_PSK.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef PAL_ENABLE_PSK
+	#define PAL_ENABLE_PSK 1
+#endif
+
+#ifndef PAL_ENABLE_X509
+	#define PAL_ENABLE_X509 0
+#endif
+
+
+#undef PAL_USE_SECURE_TIME
+#define PAL_USE_SECURE_TIME 0
+
+
+#define PAL_SKIP_TEST_MODULE_SOTP
+#define PAL_SKIP_TEST_MODULE_RTOS
+#define PAL_SKIP_TEST_MODULE_NETWORK
+#define PAL_SKIP_TEST_MODULE_FILESYSTEM
+#define PAL_SKIP_TEST_MODULE_UPDATE
+#define PAL_SKIP_TEST_MODULE_INTERNALFLASH
+
+
+
+#include "Linux_default.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/Linux/Linux_SW_RoT_SW_RTC_2FLASH.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef PAL_USE_HW_ROT 
+    #define PAL_USE_HW_ROT     0
+#endif
+
+#ifndef PAL_USE_HW_RTC
+    #define PAL_USE_HW_RTC    0
+#endif
+
+#ifndef PAL_USE_INTERNAL_FLASH 
+    #define PAL_USE_INTERNAL_FLASH  1
+#endif
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+    #define PAL_INT_FLASH_NUM_SECTIONS 2
+#endif
+
+#define PAL_SKIP_TEST_MODULE_RTOS
+#define PAL_SKIP_TEST_MODULE_NETWORK
+#define PAL_SKIP_TEST_MODULE_CRYPTO
+#define PAL_SKIP_TEST_MODULE_FILESYSTEM
+#define PAL_SKIP_TEST_MODULE_UPDATE
+#define PAL_SKIP_TEST_MODULE_TLS
+#define PAL_SKIP_TEST_MODULE_INTERNALFLASH
+
+#include "Linux_default.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/Linux/Linux_crypto_only.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2016, 2018 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef PAL_ENABLE_PSK
+	#define PAL_ENABLE_PSK 0
+#endif
+
+#ifndef PAL_ENABLE_X509
+	#define PAL_ENABLE_X509 1
+#endif
+
+
+#undef PAL_USE_SECURE_TIME
+#define PAL_USE_SECURE_TIME 1
+
+#define PAL_SKIP_TEST_MODULE_TLS
+#define PAL_SKIP_TEST_MODULE_SOTP
+#define PAL_SKIP_TEST_MODULE_RTOS
+#define PAL_SKIP_TEST_MODULE_NETWORK
+#define PAL_SKIP_TEST_MODULE_FILESYSTEM
+#define PAL_SKIP_TEST_MODULE_UPDATE
+#define PAL_SKIP_TEST_MODULE_INTERNALFLASH
+
+
+
+#include "Linux_default.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/Linux/Linux_default.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef PAL_DEFAULT_LINUX_CONFIGURATION_H_
+
+
+#ifndef PAL_BOARD_SPECIFIC_CONFIG
+    #if defined(TARGET_X86_X64)
+        #include "x86_x64_default.h"
+    #endif
+#endif
+
+
+#ifndef PAL_NUMBER_OF_PARTITIONS
+    #define PAL_NUMBER_OF_PARTITIONS 1
+#endif
+
+
+#ifndef PAL_FS_MOUNT_POINT_PRIMARY
+    #if (PAL_NUMBER_OF_PARTITIONS == 2)
+        #define PAL_FS_MOUNT_POINT_PRIMARY    "./pal_pri"                                                       //!< User should change this for the his working folder
+    #else
+        #define PAL_FS_MOUNT_POINT_PRIMARY    "./pal"
+    #endif
+#endif
+
+#ifndef PAL_FS_MOUNT_POINT_SECONDARY
+    #if (PAL_NUMBER_OF_PARTITIONS == 2)
+        #define PAL_FS_MOUNT_POINT_SECONDARY    "./pal_sec"
+    #else
+        #define PAL_FS_MOUNT_POINT_SECONDARY    "./pal"                                                    //!< User should change this for the his working folder
+    #endif
+#endif
+
+#ifndef PAL_NET_MAX_IF_NAME_LENGTH
+    #define PAL_NET_MAX_IF_NAME_LENGTH   16  //15 + '\0'
+#endif
+
+#ifndef PAL_NET_TEST_MAX_ASYNC_SOCKETS
+    #define PAL_NET_TEST_MAX_ASYNC_SOCKETS 5
+#endif
+
+#ifndef PAL_NET_TEST_ASYNC_SOCKET_MANAGER_THREAD_STACK_SIZE
+    #define PAL_NET_TEST_ASYNC_SOCKET_MANAGER_THREAD_STACK_SIZE (1024 * 16)
+#endif
+
+
+#ifndef PAL_RTOS_HIGH_RES_TIMER_THREAD_STACK_SIZE
+    #define PAL_RTOS_HIGH_RES_TIMER_THREAD_STACK_SIZE (1024 * 16)
+#endif
+
+#ifndef PAL_FORMAT_CMD_MAX_LENGTH
+    #define PAL_FORMAT_CMD_MAX_LENGTH 256
+#endif
+
+#ifndef PAL_DEVICE_NAME_MAX_LENGTH
+    #define PAL_DEVICE_NAME_MAX_LENGTH  128
+#endif
+
+#ifndef PAL_PARTITION_FORMAT_TYPE
+    #define PAL_PARTITION_FORMAT_TYPE "ext4"
+#endif
+
+/*\brief  overwrite format command with remove all file and directory*/
+#ifndef PAL_SIMULATOR_FS_RM_INSTEAD_OF_FORMAT
+    #define PAL_SIMULATOR_FS_RM_INSTEAD_OF_FORMAT 0
+#endif
+
+#ifndef PAL_FS_FORMAT_COMMAND
+    #define PAL_FS_FORMAT_COMMAND "mkfs -F -t %s %s"
+#endif
+
+
+#ifndef PARTITION_FORMAT_ADDITIONAL_PARAMS
+    #define PARTITION_FORMAT_ADDITIONAL_PARAMS NULL
+#endif
+
+ /*\brief  Starting Address for section 1 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_ADDRESS
+    #define PAL_INTERNAL_FLASH_SECTION_1_ADDRESS    0
+#endif
+
+/*\brief  Starting Address for section 2 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_ADDRESS
+    #define PAL_INTERNAL_FLASH_SECTION_2_ADDRESS    0
+#endif
+
+/*\brief  Size for section 1*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_SIZE
+    #define PAL_INTERNAL_FLASH_SECTION_1_SIZE       0
+#endif
+
+/*\brief  Size for section 2*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_SIZE
+    #define PAL_INTERNAL_FLASH_SECTION_2_SIZE       0
+#endif
+
+//!< Stack size for thread created when calling pal_getAddressInfoAsync
+#ifndef PAL_NET_ASYNC_DNS_THREAD_STACK_SIZE
+    #define PAL_NET_ASYNC_DNS_THREAD_STACK_SIZE (1024 * 32)
+#endif
+
+#ifndef PAL_USE_HW_TRNG
+    #define PAL_USE_HW_TRNG    1
+#endif // PAL_USE_HW_TRNG
+
+#if PAL_USE_HW_TRNG
+    //! Stack size for TRNG noise collecting thread
+    #ifndef PAL_NOISE_TRNG_THREAD_STACK_SIZE
+        #define PAL_NOISE_TRNG_THREAD_STACK_SIZE (1024 * 16)
+    #endif
+#endif
+
+#ifndef PAL_TIMER_SIGNAL
+    // Signal number for timer completition signal, a RT signal is needed to get signal queueing
+    #define PAL_TIMER_SIGNAL (SIGRTMIN+0)
+#endif
+
+#endif /* PAL_DEFAULT_LINUX_CONFIGURATION_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/Linux/TARGET_x86_x64/x86_x64_default.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef PAL_SIMULATOR_TEST_ENABLE
+    #define PAL_SIMULATOR_TEST_ENABLE 1
+#endif
+
+#ifndef PAL_USE_HW_ROT
+    #define PAL_USE_HW_ROT     0
+#endif
+
+#ifndef PAL_USE_HW_RTC
+    #define PAL_USE_HW_RTC    0
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/TARGET_MCU_K64F/K64F_default.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+ /*\brief  Starting Address for section 1 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_ADDRESS
+    #define PAL_INTERNAL_FLASH_SECTION_1_ADDRESS    0xFE000
+#endif
+
+/*\brief  Starting Address for section 2 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_ADDRESS
+    #define PAL_INTERNAL_FLASH_SECTION_2_ADDRESS    0xFF000
+#endif
+
+/*\brief  Size for section 1*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_SIZE
+    #define PAL_INTERNAL_FLASH_SECTION_1_SIZE       0x1000
+#endif
+
+/*\brief  Size for section 2*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_SIZE
+    #define PAL_INTERNAL_FLASH_SECTION_2_SIZE       0x1000
+#endif
+
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+    #define PAL_INT_FLASH_NUM_SECTIONS 2
+#endif
+
+#ifndef PAL_USE_INTERNAL_FLASH 
+    #define PAL_USE_INTERNAL_FLASH  1
+#endif
+
+#ifndef PAL_USE_HW_ROT 
+    #define PAL_USE_HW_ROT     0
+#endif
+
+#ifndef PAL_USE_HW_RTC
+    #define PAL_USE_HW_RTC    0
+#endif
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/TARGET_NUCLEO_F429ZI/NUCLEO_default.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+/*\brief  Starting Address for section 1 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_ADDRESS
+#define PAL_INTERNAL_FLASH_SECTION_1_ADDRESS    0x080C0000
+#endif
+
+/*\brief  Starting Address for section 2 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_ADDRESS
+#define PAL_INTERNAL_FLASH_SECTION_2_ADDRESS    0x080E0000
+#endif
+
+/*\brief  Size for section 1*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_SIZE
+#define PAL_INTERNAL_FLASH_SECTION_1_SIZE       0x20000
+#endif
+
+/*\brief  Size for section 2*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_SIZE
+#define PAL_INTERNAL_FLASH_SECTION_2_SIZE       0x20000
+#endif
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+#define PAL_INT_FLASH_NUM_SECTIONS 2
+#endif
+
+#ifndef PAL_USE_INTERNAL_FLASH 
+#define PAL_USE_INTERNAL_FLASH  1
+#endif
+
+#ifndef PAL_USE_HW_ROT 
+#define PAL_USE_HW_ROT     0
+#endif
+
+#ifndef PAL_USE_HW_RTC
+#define PAL_USE_HW_RTC    0
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/TARGET_UBLOX_C030_U201/C030_default.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright 2018 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+/*\brief  Starting Address for section 1 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_ADDRESS
+#define PAL_INTERNAL_FLASH_SECTION_1_ADDRESS    0x080C0000
+#endif
+
+/*\brief  Starting Address for section 2 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_ADDRESS
+#define PAL_INTERNAL_FLASH_SECTION_2_ADDRESS    0x080E0000
+#endif
+
+/*\brief  Size for section 1*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_SIZE
+#define PAL_INTERNAL_FLASH_SECTION_1_SIZE       0x20000
+#endif
+
+/*\brief  Size for section 2*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_SIZE
+#define PAL_INTERNAL_FLASH_SECTION_2_SIZE       0x20000
+#endif
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+#define PAL_INT_FLASH_NUM_SECTIONS 2
+#endif
+
+#ifndef PAL_USE_INTERNAL_FLASH
+#define PAL_USE_INTERNAL_FLASH  1
+#endif
+
+#ifndef PAL_USE_HW_ROT
+#define PAL_USE_HW_ROT     0
+#endif
+
+#ifndef PAL_USE_HW_RTC
+#define PAL_USE_HW_RTC    0
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/TARGET_UBLOX_EVK_ODIN_W2/ODIN_default.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+/*\brief  Starting Address for section 1 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_ADDRESS
+#define PAL_INTERNAL_FLASH_SECTION_1_ADDRESS    0x080C0000
+#endif
+
+/*\brief  Starting Address for section 2 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_ADDRESS
+#define PAL_INTERNAL_FLASH_SECTION_2_ADDRESS    0x080E0000
+#endif
+
+/*\brief  Size for section 1*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_SIZE
+#define PAL_INTERNAL_FLASH_SECTION_1_SIZE       0x20000
+#endif
+
+/*\brief  Size for section 2*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_SIZE
+#define PAL_INTERNAL_FLASH_SECTION_2_SIZE       0x20000
+#endif
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+#define PAL_INT_FLASH_NUM_SECTIONS 2
+#endif
+
+#ifndef PAL_USE_INTERNAL_FLASH 
+#define PAL_USE_INTERNAL_FLASH  1
+#endif
+
+#ifndef PAL_USE_HW_ROT 
+#define PAL_USE_HW_ROT     0
+#endif
+
+#ifndef PAL_USE_HW_RTC
+#define PAL_USE_HW_RTC    0
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_FATFS.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,30 @@
+/*******************************************************************************
+* Copyright 2016, 2017 ARM Ltd.
+*
+* 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.
+*******************************************************************************/
+
+#ifndef PAL_MBEDOS_CONFIGURATION_H_
+
+#include "cmsis_os.h"
+
+/*!
+* \brief This file is for more specific definitions (per board, if needed).
+*        if this file is defined it will be included from pal_configuration.h
+*        if not, the default file will be included - if needed
+*/
+#define PAL_NUMBER_OF_PARTITIONS 2
+
+#include "mbedOS_default.h"
+
+#endif /* PAL_MBEDOS_CONFIGURATION_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_HW_RoT_HW_RTC_NOFLASH_2Partitions.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef PAL_USE_HW_ROT 
+    #define PAL_USE_HW_ROT     1
+#endif
+
+#ifndef PAL_USE_HW_RTC
+    #define PAL_USE_HW_RTC    1
+#endif
+
+#ifndef PAL_USE_INTERNAL_FLASH 
+    #define PAL_USE_INTERNAL_FLASH  0
+#endif
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+    #define PAL_INT_FLASH_NUM_SECTIONS 0
+#endif
+
+#ifndef PAL_NUMBER_OF_PARTITIONS
+    #define PAL_NUMBER_OF_PARTITIONS 2
+#endif 
+
+#define PAL_SKIP_TEST_MODULE_RTOS
+#define PAL_SKIP_TEST_MODULE_NETWORK
+#define PAL_SKIP_TEST_MODULE_CRYPTO
+#define PAL_SKIP_TEST_MODULE_UPDATE
+#define PAL_SKIP_TEST_MODULE_TLS
+#define PAL_SKIP_TEST_MODULE_INTERNALFLASH
+
+#include "mbedOS_default.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_IPV6_ONLY.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef PAL_MBEDOS_IPV6_ONLY_H_
+
+#define PAL_SUPPORT_IP_V4 false
+#define PAL_SUPPORT_IP_V6 true
+
+#include "mbedOS_default.h"
+
+
+#endif /* PAL_MBEDOS_IPV6_ONLY_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_PSK.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef PAL_ENABLE_PSK
+	#define PAL_ENABLE_PSK 1
+#endif
+
+#ifndef PAL_ENABLE_X509
+	#define PAL_ENABLE_X509 0
+#endif
+
+#undef PAL_USE_SECURE_TIME
+#define PAL_USE_SECURE_TIME 0
+
+#define PAL_SKIP_TEST_MODULE_SOTP
+#define PAL_SKIP_TEST_MODULE_RTOS
+#define PAL_SKIP_TEST_MODULE_NETWORK
+#define PAL_SKIP_TEST_MODULE_FILESYSTEM
+#define PAL_SKIP_TEST_MODULE_UPDATE
+#define PAL_SKIP_TEST_MODULE_INTERNALFLASH
+
+
+
+#include "mbedOS_default.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_SW_RoT_SW_RTC_2FLASH.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef PAL_USE_HW_ROT 
+    #define PAL_USE_HW_ROT     0
+#endif
+
+#ifndef PAL_USE_HW_RTC
+    #define PAL_USE_HW_RTC    0
+#endif
+
+#ifndef PAL_USE_INTERNAL_FLASH 
+    #define PAL_USE_INTERNAL_FLASH  1
+#endif
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+    #define PAL_INT_FLASH_NUM_SECTIONS 2
+#endif 
+
+#define PAL_SKIP_TEST_MODULE_RTOS
+#define PAL_SKIP_TEST_MODULE_NETWORK
+#define PAL_SKIP_TEST_MODULE_CRYPTO
+#define PAL_SKIP_TEST_MODULE_FILESYSTEM
+#define PAL_SKIP_TEST_MODULE_UPDATE
+#define PAL_SKIP_TEST_MODULE_TLS
+#define PAL_SKIP_TEST_MODULE_INTERNALFLASH
+
+#include "mbedOS_default.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_crypto_only.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright 2016, 2018 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef PAL_MBEDOS_CONFIGURATION_H_
+
+#include "cmsis_os.h"
+
+#if (defined(MBED_DEBUG) && !defined(DEBUG))
+    #define DEBUG
+#endif
+
+/*!
+ * \brief This file is for more specific definitions (per board, if needed).
+ *        if this file is defined it will be included from pal_configuration.h
+ *        if not, the default file will be included - if needed
+ */
+#ifndef PAL_BOARD_SPECIFIC_CONFIG
+    #if defined(TARGET_K64F)
+        #include "K64F_default.h"
+    #elif defined(TARGET_NUCLEO_F429ZI)
+        #include "NUCLEO_default.h"
+    #elif defined(TARGET_UBLOX_EVK_ODIN_W2)
+        #include "ODIN_default.h"
+    #endif
+#endif
+
+
+#ifndef PAL_RTOS_WAIT_FOREVER
+    #define PAL_RTOS_WAIT_FOREVER osWaitForever
+#endif
+
+#ifndef PAL_NUMBER_OF_PARTITIONS
+    #define PAL_NUMBER_OF_PARTITIONS 1
+#endif
+
+
+#ifndef PAL_FS_MOUNT_POINT_PRIMARY
+    #if (PAL_NUMBER_OF_PARTITIONS == 2)
+        #define PAL_FS_MOUNT_POINT_PRIMARY    "/sd"           //!< User should change this for the his working folder
+    #else
+        #define PAL_FS_MOUNT_POINT_PRIMARY    "/sd"
+    #endif
+#endif
+
+#ifndef PAL_FS_MOUNT_POINT_SECONDARY
+    #if (PAL_NUMBER_OF_PARTITIONS == 2)
+        #define PAL_FS_MOUNT_POINT_SECONDARY    "/sd2"
+    #else
+        #define PAL_FS_MOUNT_POINT_SECONDARY    "/sd"         //!< User should change this for the his working folder
+    #endif
+#endif
+
+#ifndef PAL_NUM_OF_THREAD_INSTANCES
+    #define PAL_NUM_OF_THREAD_INSTANCES 1
+#endif
+
+#ifndef PAL_MAX_SEMAPHORE_COUNT
+    #define PAL_MAX_SEMAPHORE_COUNT 1024
+#endif
+
+#define PAL_SKIP_TEST_MODULE_TLS
+#define PAL_SKIP_TEST_MODULE_SOTP
+#define PAL_SKIP_TEST_MODULE_RTOS
+#define PAL_SKIP_TEST_MODULE_NETWORK
+#define PAL_SKIP_TEST_MODULE_FILESYSTEM
+#define PAL_SKIP_TEST_MODULE_UPDATE
+#define PAL_SKIP_TEST_MODULE_INTERNALFLASH
+
+#endif /* PAL_MBEDOS_CONFIGURATION_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_default.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright 2016-2018 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef PAL_MBEDOS_CONFIGURATION_H_
+
+#include "cmsis_os.h"
+
+#if (defined(MBED_DEBUG) && !defined(DEBUG))
+    #define DEBUG
+#endif
+
+/*!
+ * \brief This file is for more specific definitions (per board, if needed).
+ *        if this file is defined it will be included from pal_configuration.h
+ *        if not, the default file will be included - if needed
+ */
+#ifndef PAL_BOARD_SPECIFIC_CONFIG
+    #if defined(TARGET_K64F)
+        #include "K64F_default.h"
+    #elif defined(TARGET_NUCLEO_F429ZI)
+        #include "NUCLEO_default.h"
+    #elif defined(TARGET_UBLOX_EVK_ODIN_W2)
+        #include "ODIN_default.h"
+    #elif defined(TARGET_UBLOX_C030_U201)
+        #include "C030_default.h"
+    #endif
+#endif
+
+
+#ifndef PAL_RTOS_WAIT_FOREVER
+    #define PAL_RTOS_WAIT_FOREVER osWaitForever
+#endif
+
+#ifndef PAL_NUMBER_OF_PARTITIONS
+    #define PAL_NUMBER_OF_PARTITIONS 1
+#endif
+
+
+#ifndef PAL_FS_MOUNT_POINT_PRIMARY
+    #if (PAL_NUMBER_OF_PARTITIONS == 2)
+        #define PAL_FS_MOUNT_POINT_PRIMARY    "/sd"           //!< User should change this for the his working folder
+    #else
+        #define PAL_FS_MOUNT_POINT_PRIMARY    "/sd"
+    #endif
+#endif
+
+#ifndef PAL_FS_MOUNT_POINT_SECONDARY
+    #if (PAL_NUMBER_OF_PARTITIONS == 2)
+        #define PAL_FS_MOUNT_POINT_SECONDARY    "/sd2"
+    #else
+        #define PAL_FS_MOUNT_POINT_SECONDARY    "/sd"         //!< User should change this for the his working folder
+    #endif
+#endif
+
+#ifndef PAL_NUM_OF_THREAD_INSTANCES
+    #define PAL_NUM_OF_THREAD_INSTANCES 1
+#endif
+
+#ifndef PAL_MAX_SEMAPHORE_COUNT
+    #define PAL_MAX_SEMAPHORE_COUNT 1024
+#endif
+
+
+
+#endif /* PAL_MBEDOS_CONFIGURATION_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/mbedOS/mbedOS_memoryStatistics.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#ifndef PAL_MBEDOS_MEMORY_STATISTICS_H_
+
+#include "mbedOS_default.h"
+
+#ifndef MBED_HEAP_STATS_ENABLED
+    #define MBED_HEAP_STATS_ENABLED 1
+#endif 
+
+#ifndef MBED_STACK_STATS_ENABLED
+    #define MBED_STACK_STATS_ENABLED 1
+#endif 
+
+#ifndef PAL_MEMORY_STATISTICS
+    #define PAL_MEMORY_STATISTICS 1
+#endif 
+
+#endif //PAL_MBEDOS_MEMORY_STATISTICS_H_
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_config/sotp_fs.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,12 @@
+#ifndef PAL_HEADER_SOTP_FS
+#define PAL_HEADER_SOTP_FS
+
+
+#define PAL_USE_HW_ROT 1
+#define PAL_USE_HW_RTC 0
+#define PAL_USE_HW_TRNG 1
+#define PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 1
+#define PAL_USE_SECURE_TIME 1
+
+
+#endif //PAL_HEADER_SOTP_FS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_ext_configs.cmake	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,20 @@
+SET(PAL_BSP_DIR ${NEW_CMAKE_SOURCE_DIR}/mbed-client-pal/Configs/)
+SET(PAL_TLS_BSP_DIR ${PAL_BSP_DIR}/${TLS_LIBRARY})
+SET(PAL_PLATFORM_BSP_DIR ${PAL_BSP_DIR}/pal_config)
+
+#choose the samll test suit of esfs - becasue the latge one does not fit with networking to image size
+add_definitions(-DESFS_INTERACTIVE_TEST)
+add_definitions(-DSOTP_LOG=0)
+
+if (${TLS_LIBRARY} MATCHES mbedTLS)
+	# PAL specific configurations for mbedTLS
+    if (NOT (${OS_BRAND} MATCHES "FreeRTOS"))
+	    add_definitions(-DMBEDTLS_CONFIG_FILE="\\"${PAL_TLS_BSP_DIR}/mbedTLSConfig_${OS_BRAND}.h"\\")
+    else()
+        add_definitions(-DMBEDTLS_CONFIG_FILE=\"${PAL_TLS_BSP_DIR}/mbedTLSConfig_${OS_BRAND}.h\")
+    endif()
+    message("PAL_TLS_BSP_DIR ${PAL_TLS_BSP_DIR}/pal_${OS_BRAND}.h")
+endif()
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Configs/pal_ext_configs_PSK.cmake	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,20 @@
+SET(PAL_BSP_DIR ${NEW_CMAKE_SOURCE_DIR}/mbed-client-pal/Configs/)
+SET(PAL_TLS_BSP_DIR ${PAL_BSP_DIR}/${TLS_LIBRARY})
+SET(PAL_PLATFORM_BSP_DIR ${PAL_BSP_DIR}/pal_config)
+
+#choose the samll test suit of esfs - becasue the latge one does not fit with networking to image size
+add_definitions(-DESFS_INTERACTIVE_TEST)
+add_definitions(-DSOTP_LOG=0)
+
+if (${TLS_LIBRARY} MATCHES mbedTLS)
+	# PAL specific configurations for mbedTLS
+    if (NOT (${OS_BRAND} MATCHES "FreeRTOS"))
+	    add_definitions(-DMBEDTLS_CONFIG_FILE="\\"${PAL_TLS_BSP_DIR}/mbedTLSConfig_${OS_BRAND}_PSK.h"\\")
+    else()
+        add_definitions(-DMBEDTLS_CONFIG_FILE=\"${PAL_TLS_BSP_DIR}/mbedTLSConfig_${OS_BRAND}_PSK.h\")
+    endif()
+    message("PAL_TLS_BSP_DIR ${PAL_TLS_BSP_DIR}/pal_${OS_BRAND}.h")
+endif()
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/DOXYGEN_FRONTPAGE.md	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,16 @@
+Mbed Platform Abstraction Layer (PAL)
+=================
+
+The Mbed Platform Abstraction Layer (PAL) connects Mbed Cloud Client with the underlying platform.
+
+The main purpose of PAL is to enable easy and fast Mbed Cloud Client services portability, allowing them to operate over wide range of ARM Cortex-based platforms running different operating systems with various libraries (networking, for example).
+
+PAL has two layers:
+
+- **Service API layer**: provides the PAL APIs for Mbed Cloud Client code. The APIs are identical for all platforms and operating systems, and you should not modify them.
+- **Platform API layer**: provides a standard set of baseline requirements for the platform. To allow Mbed Cloud Client to run on the target platform, you need to implement all requirements when you port. The implementation may be different for each target operating system or library; PAL provides reference implementations for several operating systems, including Mbed OS.
+
+See the [Files](files.html) section to review documentation for specific APIs.
+
+See the [full documentation and porting guide for PAL](/docs/v1.2/porting/index.html).
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+PlatformBSP/*
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,5 @@
+Yocto_Generic_Linux/*
+MK64F_FreeRTOS/*
+x86_x64_Linux/*
+OpenWRT_Generic_Linux/*
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/Include/PlatIncludes.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#ifndef K64_BSPINCLUDES_H_
+#define K64_BSPINCLUDES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! \brief This function initialized the network interface
+*
+* @param None
+*
+* \return void
+*
+*/
+void networkInit(void *arg);
+
+/*! \brief This function return the interface context
+*
+* @param None
+*
+* \return void *
+*
+*/
+void* palTestGetNetWorkInterfaceContext(void);
+
+
+/*! \brief This function initialized the Board interface
+*
+* @param None
+*
+* \return void
+*
+*/
+void boardInit();
+
+
+/*! \brief This function initialized the FileSystem interface
+*
+* @param None
+*
+* \return void
+*
+*/
+void fileSystemMountDrive(void);
+
+#ifdef PAL_MEMORY_STATISTICS
+void printMemoryStats(void);
+#define PRINT_MEMORY_STATS	printMemoryStats();
+#else //PAL_MEMORY_STATISTICS
+#define PRINT_MEMORY_STATS
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* K64_BSPINCLUDES_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/Include/pal_BSP.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#ifndef MBED_CLIENT_PAL_TEST_MAINTEST_H_
+#define MBED_CLIENT_PAL_TEST_MAINTEST_H_
+
+
+
+#ifdef PAL_LINUX
+#define PAL_TEST_THREAD_STACK_SIZE 16*1024*sizeof(uint32_t)
+#else
+#define PAL_TEST_THREAD_STACK_SIZE 512*sizeof(uint32_t)
+#endif
+#include <stdbool.h>
+
+typedef struct {
+	int argc;
+	char **argv;
+} pal_args_t;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef void (*testMain_t)(pal_args_t *);
+
+typedef enum {
+    //Success Codes are positive
+    BSP_SUCCESS = 0,
+
+    //All errors are Negative
+    // generic errors
+    BSP_GENERIC_FAILURE =  -1,
+    BSP_PARAMETER_FAILURE =  -2,
+    BSP_THREAD_CREATION_FAILURE =  -3,
+    BSP_NETWORK_TIMEOUT =  -4,
+    BSP_FILE_SYSTEM_TIMEOUT =  -5
+} bspStatus_t; /*! errors returned by the pal BSP code */
+
+
+/*! \brief This function initialized the platform (BSP , file system ....)
+*
+* @param[out] outputContext: used to return the network context to be used by the tests. The funciton expects the address of a writable void* in order to return this value (use NULL if not applicable).
+*
+* \return status of platform intialization
+*
+*/
+bspStatus_t initPlatform(void** outputContext);
+
+
+/*! \brief This function is called from the main function
+*			and calls the startup sequence for the board tests
+*
+* @param[in] mainTestFunc - callback function for the main test runner
+* @param[in] args - structure the contains argv and argc received from the main function
+*
+* \return void
+*
+*/
+bool runProgram(testMain_t mainTestFunc, pal_args_t * args);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBED_CLIENT_PAL_TEST_MAINTEST_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/MK64F_FreeRTOS/BoardInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "board.h"
+#include "fsl_device_registers.h"
+#include "pin_mux.h"
+#include "clock_config.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "fsl_rtc.h"
+
+// TRNG Function for K64F device
+#include "fsl_common.h"
+#include "fsl_clock.h"
+
+#include "pal_configuration.h"
+
+
+#define APP_DEBUG_UART_BAUDRATE 115200                 /* Debug console baud rate.           */
+#define APP_DEBUG_UART_CLKSRC_NAME kCLOCK_CoreSysClk /* System clock.       */
+
+//This stack overflow hook can catch stack overflow errors in FreeRTOS.
+//You must enable define of configCHECK_FOR_STACK_OVERFLOW in FreeRTOSConfig.h
+void vApplicationStackOverflowHook( TaskHandle_t xTask,	signed char *pcTaskName )
+{
+	return;
+}
+
+//This MallocFailedHook can catch memory allocation errors in FreeRTOS.
+//You must enable define of configUSE_MALLOC_FAILED_HOOK in FreeRTOSConfig.h
+void vApplicationMallocFailedHook( void )
+{
+	return;
+}
+
+
+static void APP_InitPlatformTRNG()
+{
+    CLOCK_EnableClock(kCLOCK_Rnga0);
+    CLOCK_DisableClock(kCLOCK_Rnga0);
+    CLOCK_EnableClock(kCLOCK_Rnga0);
+}
+
+#if 0
+static void APP_StopPlatformTRNG()
+{
+	CLOCK_DisableClock(kCLOCK_Rnga0);
+}
+
+void StopFreeRtosBoard()
+{
+	APP_StopPlatformTRNG();
+}
+#endif //0
+
+void boardInit()
+{
+	MPU_Type *base = MPU;
+	BOARD_InitPins();
+	BOARD_BootClockRUN();
+	BOARD_InitDebugConsole();
+
+#if (PAL_USE_HW_RTC)
+	rtc_config_t rtcConfig = {0, 0, 0, 0, 0};
+    RTC_GetDefaultConfig(&rtcConfig);
+    rtcConfig.supervisorAccess = true;
+    RTC_Init(RTC, &rtcConfig);
+    /* Enable the RTC 32KHz oscillator */
+    RTC->CR |= RTC_CR_OSCE_MASK;
+    RTC_StartTimer(RTC);
+#endif
+
+	APP_InitPlatformTRNG();
+	/* Disable MPU. */
+	base->CESR &= ~MPU_CESR_VLD_MASK;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/MK64F_FreeRTOS/FileSystemInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,313 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "pal.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "fsl_mpu.h"
+#include "ff.h"
+#include "diskio.h"
+#include "sdhc_config.h"
+#include "fsl_debug_console.h"
+
+
+//uncomment this to create the partitions
+//#define PAL_EXAMPLE_GENERATE_PARTITION 1
+//Uncomment this to allow format
+//#define PAL_EXAMPLE_FORMAT_PARTITION 1
+
+#if (PAL_NUMBER_OF_PARTITIONS > 0)
+
+#ifndef _MULTI_PARTITION
+#error "Please Define _MULTI_PARTITION in ffconf.h"
+#endif
+
+#if ((PAL_NUMBER_OF_PARTITIONS > 2) || (PAL_NUMBER_OF_PARTITIONS < 0))
+#error "Pal partition number is not supported, please set to a number between 0 and 2"
+#endif
+
+PARTITION VolToPart[] = {
+#if (PAL_NUMBER_OF_PARTITIONS > 0)
+		{SDDISK,1}, /* 0: */
+#endif
+#if (PAL_NUMBER_OF_PARTITIONS > 1)
+		{SDDISK,2}  /* 1: */
+#endif
+};
+#endif
+
+bool FileSystemInit = false;
+#define MAX_SD_READ_RETRIES	5
+#define LABEL_LENGTH	66
+/*!
+ * @brief Get event instance.
+ * @param eventType The event type
+ * @return The event instance's pointer.
+ */
+PAL_PRIVATE volatile uint32_t *EVENT_GetInstance(event_t eventType);
+
+/*! @brief Transfer complete event. */
+PAL_PRIVATE volatile uint32_t g_eventTransferComplete;
+
+PAL_PRIVATE volatile uint32_t g_eventSDReady;
+
+/*! @brief Time variable unites as milliseconds. */
+PAL_PRIVATE volatile uint32_t g_timeMilliseconds;
+
+/*! @brief Preallocated Work area (file system object) for logical drive, should NOT be free or lost*/
+PAL_PRIVATE FATFS fileSystem[2];
+
+/*! \brief CallBack function for SD card initialization
+ *		   Set systick reload value to generate 1ms interrupt
+ * @param void
+ *
+ * \return void
+ *
+ */
+void EVENT_InitTimer(void)
+{
+	/* Set systick reload value to generate 1ms interrupt */
+	SysTick_Config(CLOCK_GetFreq(kCLOCK_CoreSysClk) / 1000U);
+}
+
+
+/*! \brief CallBack function for SD card initialization
+ *
+ * @param void
+ *
+ * \return pointer to the requested instance
+ *
+ */
+PAL_PRIVATE volatile uint32_t *EVENT_GetInstance(event_t eventType)
+{
+	volatile uint32_t *event;
+
+	switch (eventType)
+	{
+	case kEVENT_TransferComplete:
+		event = &g_eventTransferComplete;
+		break;
+	default:
+		event = NULL;
+		break;
+	}
+
+	return event;
+}
+
+/*! \brief CallBack function for SD card initialization
+ *
+ * @param event_t
+ *
+ * \return TRUE if instance was found
+ *
+ */
+bool EVENT_Create(event_t eventType)
+{
+	volatile uint32_t *event = EVENT_GetInstance(eventType);
+
+	if (event)
+	{
+		*event = 0;
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+/*! \brief blockDelay - Blocks the task and count the number of ticks given
+ *
+ * @param void
+ *
+ * \return TRUE - on success
+ *
+ */
+void blockDelay(uint32_t Ticks)
+{
+	uint32_t tickCounts = 0;
+	for(tickCounts = 0; tickCounts < Ticks; tickCounts++){}
+}
+
+
+/*! \brief CallBack function for SD card initialization
+ *
+ * @param void
+ *
+ * \return TRUE - on success
+ *
+ */
+bool EVENT_Wait(event_t eventType, uint32_t timeoutMilliseconds)
+{
+	uint32_t startTime;
+	uint32_t elapsedTime;
+
+	volatile uint32_t *event = EVENT_GetInstance(eventType);
+
+	if (timeoutMilliseconds && event)
+	{
+		startTime = g_timeMilliseconds;
+		do
+		{
+			elapsedTime = (g_timeMilliseconds - startTime);
+		} while ((*event == 0U) && (elapsedTime < timeoutMilliseconds));
+		*event = 0U;
+
+		return ((elapsedTime < timeoutMilliseconds) ? true : false);
+	}
+	else
+	{
+		return false;
+	}
+}
+
+/*! \brief CallBack function for SD card initialization
+ *
+ * @param eventType
+ *
+ * \return TRUE if instance was found
+ *
+ */
+bool EVENT_Notify(event_t eventType)
+{
+	volatile uint32_t *event = EVENT_GetInstance(eventType);
+
+	if (event)
+	{
+		*event = 1U;
+		return true;
+	}
+	else
+	{
+		return false;
+	}
+}
+
+/*! \brief CallBack function for SD card initialization
+ *
+ * @param eventType
+ *
+ * \return void
+ *
+ */
+void EVENT_Delete(event_t eventType)
+{
+	volatile uint32_t *event = EVENT_GetInstance(eventType);
+
+	if (event)
+	{
+		*event = 0U;
+	}
+}
+
+
+
+
+static int initPartition(pal_fsStorageID_t partitionId)
+{
+	char folderName[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+	FRESULT fatResult = FR_OK;
+	int status = 0;
+
+	status = pal_fsGetMountPoint(partitionId,PAL_MAX_FILE_AND_FOLDER_LENGTH,folderName);
+	if (PAL_SUCCESS == status)
+	{
+		fatResult = f_mount(&fileSystem[partitionId], folderName, 1U);
+		if (FR_OK != fatResult)
+		{
+#ifdef PAL_EXAMPLE_FORMAT_PARTITION
+				PRINTF("Failed to mount partition %s in disk formating and trying again\r\n",folderName);
+				fatResult = f_mkfs(folderName, 0, 0);
+				if (FR_OK == fatResult)
+				{
+					fatResult = f_mount(&fileSystem[partitionId], folderName, 1U);
+				}
+#endif
+			if (FR_OK != fatResult)
+			{
+				PRINTF("Failed to format & mount partition %s\r\n",folderName);
+			}
+		}
+	}
+	else
+	{
+		PRINTF("Failed to get mount point for partition %d\r\n",partitionId);
+	}
+	return status;
+}
+
+/*! \brief This function mount the fatfs on and SD card
+ *
+ * @param void
+ *
+ * \return palStatus_t - PAL_SUCCESS when mount point succeeded
+ *
+ */
+
+void fileSystemMountDrive(void)
+{
+	PRINTF("%s : Creating FileSystem SetUp thread!\r\n",__FUNCTION__);
+	int count = 0;
+	int status = 0;
+
+	if (FileSystemInit == false)
+	{
+		//Detected SD card inserted
+		while (!(GPIO_ReadPinInput(BOARD_SDHC_CD_GPIO_BASE, BOARD_SDHC_CD_GPIO_PIN)))
+		{
+			blockDelay(1000U);
+			if (count++ > MAX_SD_READ_RETRIES)
+			{
+				break;
+			}
+		}
+
+		if(count < MAX_SD_READ_RETRIES)
+		{
+			/* Delay some time to make card stable. */
+			blockDelay(10000000U);
+#ifdef PAL_EXAMPLE_GENERATE_PARTITION
+#if (PAL_NUMBER_OF_PARTITIONS == 1)
+			DWORD plist[] = {100,0,0,0};
+#elif	(PAL_NUMBER_OF_PARTITIONS == 2) //else of (PAL_NUMBER_OF_PARTITIONS == 1)
+			DWORD plist[] = {50,50,0,0};
+#endif //(PAL_NUMBER_OF_PARTITIONS == 1)
+			BYTE work[_MAX_SS];
+
+			status = f_fdisk(SDDISK,plist, work);
+			PRINTF("f_fdisk fatResult=%d\r\n",status);
+			if (FR_OK != status)
+			{
+				PRINTF("Failed to create partitions in disk\r\n");
+			}
+#endif //PAL_EXAMPLE_GENERATE_PARTITION
+
+
+			status = initPartition(PAL_FS_PARTITION_PRIMARY);
+#if (PAL_NUMBER_OF_PARTITIONS == 2)
+			status = initPartition(PAL_FS_PARTITION_SECONDARY);
+#endif
+
+
+			if (!status) // status will be 0, if all passess
+			{
+				FileSystemInit = true;
+				PRINTF("%s : Exit FileSystem SetUp thread!\r\n",__FUNCTION__);
+			}
+		}
+	}
+	vTaskDelete( NULL );
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/MK64F_FreeRTOS/NetworkInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "lwip/netif.h"
+#include "lwip/sys.h"
+#include "lwip/arch.h"
+#include "lwip/api.h"
+#include "lwip/tcpip.h"
+#include "netif/etharp.h"
+#include "lwip/dhcp.h"
+#include "ethernetif.h"
+#include "lwip/inet.h"
+
+
+struct netif fsl_netif0;
+ip_addr_t fsl_netif0_ipaddr, fsl_netif0_netmask, fsl_netif0_gw;
+
+#ifndef NETWORK_BRINGUP
+#define NETWORK_BRINGUP 1
+#endif
+
+bool dhcpDone = false;
+
+#define configIP_ADDR0 0
+#define configIP_ADDR1 0
+#define configIP_ADDR2 0
+#define configIP_ADDR3 0
+
+/* Netmask configuration. */
+#define configNET_MASK0 0
+#define configNET_MASK1 0
+#define configNET_MASK2 0
+#define configNET_MASK3 0
+
+/* Default gateway address configuration */
+#define configGW_ADDR0 0
+#define configGW_ADDR1 0
+#define configGW_ADDR2 0
+#define configGW_ADDR3 0
+
+#ifndef HTTPD_STACKSIZE
+#define HTTPD_STACKSIZE 3000
+#endif
+
+#ifndef HTTPD_DEBUG
+#define HTTPD_DEBUG LWIP_DBG_ON
+#endif
+
+
+void networkInit(void *arg)
+{
+	PRINTF("%s : Starting HTTP thread! \r\n", __FUNCTION__);
+	if (NETWORK_BRINGUP)
+	{
+		err_t err = 0;
+		LWIP_UNUSED_ARG(arg);
+
+		///// MAC
+		fsl_netif0.hwaddr_len = 6;
+
+		// Fetch word 0
+		uint32_t word0 = *(uint32_t *)0x40048060;
+		// Fetch word 1
+		// we only want bottom 16 bits of word1 (MAC bits 32-47)
+		// and bit 9 forced to 1, bit 8 forced to 0
+		// Locally administered MAC, reduced conflicts
+		// http://en.wikipedia.org/wiki/MAC_address
+		uint32_t word1 = *(uint32_t *)0x4004805C;
+		word1 |= 0x00000200;
+		word1 &= 0x0000FEFF;
+
+		fsl_netif0.hwaddr[0] = (word1 & 0x000000ff);
+		fsl_netif0.hwaddr[1] = (word1 & 0x0000ff00) >> 8;
+		fsl_netif0.hwaddr[2] = (word0 & 0xff000000) >> 24;
+		fsl_netif0.hwaddr[3] = (word0 & 0x00ff0000) >> 16;
+		fsl_netif0.hwaddr[4] = (word0 & 0x0000ff00) >> 8;
+		fsl_netif0.hwaddr[5] = (word0 & 0x000000ff);
+		////
+
+		tcpip_init(NULL, NULL);
+		LWIP_DEBUGF(HTTPD_DEBUG, ("TCP/IP initialized.\r\n"));
+		IP4_ADDR(&fsl_netif0_ipaddr, configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3);
+		IP4_ADDR(&fsl_netif0_netmask, configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3);
+		IP4_ADDR(&fsl_netif0_gw, configGW_ADDR0, configGW_ADDR1, configGW_ADDR2, configGW_ADDR3);
+
+		netif_add(&fsl_netif0, &fsl_netif0_ipaddr, &fsl_netif0_netmask, &fsl_netif0_gw, NULL, ethernetif_init, tcpip_input);
+		netif_set_default(&fsl_netif0);
+
+		PRINTF("%s : Starting DCHP request\r\n", __FUNCTION__);
+		/* obtain the IP address, default gateway and subnet mask by using DHCP*/
+		err = dhcp_start(&fsl_netif0);
+		PRINTF("%s : Started DCHP request (%s)\r\n", __FUNCTION__, lwip_strerr(err));
+		for(int i=0; i < 40 && fsl_netif0.dhcp->state != DHCP_BOUND; i++)
+		{
+			PRINTF("%s : Current DHCP State : %d\r\n", __FUNCTION__, fsl_netif0.dhcp->state);
+			vTaskDelay(1000/portTICK_PERIOD_MS);
+		}
+
+		/**/
+		PRINTF("%s : DHCP state, activating interface (%d)\r\n", __FUNCTION__,fsl_netif0.dhcp->state);
+		if (fsl_netif0.dhcp->state != DHCP_BOUND)
+		{
+			PRINTF("%s : DHCP state, TIMEOUT (%d)\r\n", __FUNCTION__,fsl_netif0.dhcp->state);
+		}
+
+		LWIP_DEBUGF(HTTPD_DEBUG, ("http_server_netconn_thread: init interface START!"));
+		netif_set_up(&fsl_netif0);
+		LWIP_DEBUGF(HTTPD_DEBUG, ("http_server_netconn_thread: init interface END!"));
+
+		PRINTF("%s : Interface is up : %d\r\n", __FUNCTION__, fsl_netif0.dhcp->state);
+		PRINTF("%s : IP %s\r\n", __FUNCTION__, ipaddr_ntoa(&fsl_netif0.ip_addr));
+		PRINTF("%s : NM %s\r\n", __FUNCTION__, ipaddr_ntoa(&fsl_netif0.netmask));
+		PRINTF("%s : GW %s\r\n", __FUNCTION__, ipaddr_ntoa(&fsl_netif0.gw));
+	}
+	PRINTF("before run tests: \r\n");
+	dhcpDone = true;
+
+	vTaskDelete( NULL );
+
+}
+
+// Currently we support only one interface
+void* palTestGetNetWorkInterfaceContext()
+{
+	return (void *)&fsl_netif0;
+}
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/MK64F_FreeRTOS/pal_startup.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal.h"
+#include "PlatIncludes.h"
+#include "fsl_debug_console.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "lwip/sys.h"
+#include "pal_BSP.h"
+
+#ifndef TEST_MAIN_THREAD_STACK_SIZE
+#define TEST_MAIN_THREAD_STACK_SIZE (1024*8)
+#endif
+
+#ifndef TEST_FS_INIT_THREAD_STACK_SIZE
+#define TEST_FS_INIT_THREAD_STACK_SIZE (1024*4)
+#endif
+
+#ifndef BSP_MAX_INIT_ITERATIONS 
+#define BSP_MAX_INIT_ITERATIONS 600
+#endif
+
+#ifndef BSP_INIT_INTERATION_TIME_MS 
+#define BSP_INIT_INTERATION_TIME_MS 1000
+#endif
+
+
+
+
+extern bool dhcpDone;
+extern bool FileSystemInit;
+int main(int argc, char * argv[]);
+
+
+void freeRTOScallMain(void * arg)
+{
+    main(0,NULL);
+}
+
+
+//returns the network context
+ bspStatus_t initPlatform(void** outputContext)
+{
+    bspStatus_t status = BSP_SUCCESS;
+    static uint8_t initState = 0;
+    BaseType_t rtosStatus = pdPASS;
+    //1st time in init the system is required
+    if (0 == initState) 
+    {
+        //set for next initState
+        initState = 1;
+
+    	//Init Board
+    	boardInit();
+
+    	//Init FileSystem
+    	rtosStatus = xTaskCreate((TaskFunction_t)fileSystemMountDrive, "FileSystemInit", TEST_FS_INIT_THREAD_STACK_SIZE, NULL, tskIDLE_PRIORITY + 3, NULL);
+        if (pdPASS != rtosStatus)
+        {
+            PRINTF("BSP ERROR: failed to create task with error %x \r\n", rtosStatus);
+            status = BSP_THREAD_CREATION_FAILURE;
+            goto end;
+        }
+
+    	//Init DHCP thread - note: according to LWIP docs this funciton can't fail (states that porting code must asset in case of failure) 
+        sys_thread_new("networkInit", networkInit, NULL, 1024, tskIDLE_PRIORITY + 2);
+
+        //Init Unit testing thread
+        rtosStatus = xTaskCreate(freeRTOScallMain, "main", (uint16_t)PAL_TEST_THREAD_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
+        if (pdPASS != rtosStatus)
+        {
+            PRINTF("BSP ERROR: failed to create task with error %x \r\n", rtosStatus);
+            status = BSP_THREAD_CREATION_FAILURE;
+            goto end;
+        }
+
+    	//Start OS
+    	vTaskStartScheduler();
+        // taks scheduler shouldn't exit unless an error has occured
+        PRINTF("BSP ERROR: failed to run scheduler \r\n");
+        status = BSP_THREAD_CREATION_FAILURE;
+        goto end;
+    }  
+    if (1 == initState) 
+    {
+        uint32_t counter = 0; // limit waiting for FileSystemInit and dhcpDone to 
+        while (((!FileSystemInit) || (!dhcpDone))  && (counter < BSP_MAX_INIT_ITERATIONS))
+        {
+            vTaskDelay(BSP_INIT_INTERATION_TIME_MS);
+            PRINTF("waiting to file system % network to init\r\n");
+            counter++;
+        }
+
+        if ((!dhcpDone) || (!FileSystemInit))
+        {
+            if (!FileSystemInit)
+            {
+                status = BSP_FILE_SYSTEM_TIMEOUT;
+                PRINTF("BSP ERROR: timeout while waiting for file system init\r\n");
+                
+            }
+            if (!dhcpDone)
+            {
+                status = BSP_NETWORK_TIMEOUT;
+                PRINTF("BSP ERROR: timeout while waiting for dhcp \r\n");
+            }
+            goto end;
+        }
+
+    }
+     
+    if (NULL != outputContext)
+    {
+        *outputContext = palTestGetNetWorkInterfaceContext();
+    }
+
+end:
+   return status;
+
+}
+
+
+bool runProgram(testMain_t func, pal_args_t * args)
+{
+    func(args);
+    return true;
+}
+
+#ifndef __CC_ARM          /* ARM Compiler */
+/*This is a Hardfault handler to use in debug for more info please read -
+ * http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html */
+/* The prototype shows it is a naked function - in effect this is just an
+assembly function. */
+void HardFault_Handler( void ) __attribute__( ( naked ) );
+
+/* The fault handler implementation calls a function called
+prvGetRegistersFromStack(). */
+void HardFault_Handler(void)
+{
+    __asm volatile
+    (
+        " tst lr, #4                                                \n"
+        " ite eq                                                    \n"
+        " mrseq r0, msp                                             \n"
+        " mrsne r0, psp                                             \n"
+        " ldr r1, [r0, #24]                                         \n"
+        " ldr r2, handler2_address_const                            \n"
+        " bx r2                                                     \n"
+        " handler2_address_const: .word prvGetRegistersFromStack    \n"
+    );
+}
+
+
+void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
+{
+/* These are volatile to try and prevent the compiler/linker optimising them
+away as the variables never actually get used.  If the debugger won't show the
+values of the variables, make them global my moving their declaration outside
+of this function. */
+volatile uint32_t r0;
+volatile uint32_t r1;
+volatile uint32_t r2;
+volatile uint32_t r3;
+volatile uint32_t r12;
+volatile uint32_t lr; /* Link register. */
+volatile uint32_t pc; /* Program counter. */
+volatile uint32_t psr;/* Program status register. */
+
+    r0 = pulFaultStackAddress[ 0 ];
+    r1 = pulFaultStackAddress[ 1 ];
+    r2 = pulFaultStackAddress[ 2 ];
+    r3 = pulFaultStackAddress[ 3 ];
+
+    r12 = pulFaultStackAddress[ 4 ];
+    lr = pulFaultStackAddress[ 5 ];
+    pc = pulFaultStackAddress[ 6 ];
+    psr = pulFaultStackAddress[ 7 ];
+
+    /* When the following line is hit, the variables contain the register values. */
+    PRINTF("r0 = %d\r\n"
+           "r1 = %d\r\n"
+           "r2 = %d\r\n"
+           "r3 = %d\r\n"
+           "r12 = %d\r\n"
+           "lr = %d\r\n"
+           "pc = %d\r\n"
+           "psr = %d\r\n",
+           r0,r1,r2,r3,r12,lr,pc,psr);
+    for( ;; );
+}
+
+#endif
+// This is used by unity for output. The make file must pass a definition of the following form
+// -DUNITY_OUTPUT_CHAR=unity_output_char
+void unity_output_char(int c)
+{
+	PUTCHAR(c);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/OpenWRT_Generic_Linux/BoardInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,15 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/OpenWRT_Generic_Linux/FileSystemInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "pal.h"
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdio.h>
+
+bool FileSystemInit = true;
+
+// Desktop Linux
+// In order for tests to pass for all partition configurations we need to simulate the case of multiple
+// partitions using a single folder. We do this by creating one or two different sub-folders, depending on
+// the configuration.
+int fileSystemCreateRootFolders(void)
+{
+	int status = 0;
+	char folder[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+
+	// Get default mount point.
+	status = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, folder);
+	if(status != 0)
+	{
+	    return 1;
+	}
+	printf("Mount point for primary partition: %s\r\n",folder);
+	// Make the sub-folder
+	int res = mkdir(folder,0744);
+    if(res)
+    {
+        // Ignore error if it exists
+        if( errno != EEXIST)
+        {
+        	printf("mkdir failed errno= %d\r\n",errno);
+            return 1;
+        }
+    }
+
+    // Get default mount point.
+    memset(folder,0,sizeof(folder));
+    status = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, folder);
+    printf("Mount point for secondary partition: %s\r\n",folder);
+    if(status != 0)
+    {
+        return 1;
+    }
+
+    // Make the sub-folder
+    res = mkdir(folder,0744);
+    if(res)
+    {
+        // Ignore error if it exists
+        if( errno != EEXIST)
+        {
+        	printf("mkdir failed errno= %d\r\n",errno);
+            return 1;
+        }
+    }       
+	return status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/OpenWRT_Generic_Linux/NetworkInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <inttypes.h>
+
+#ifndef PAL_LINUX_ETH
+#define PAL_LINUX_ETH "eth0"
+#endif
+
+bool dhcpDone = true;
+
+void* palTestGetNetWorkInterfaceContext(void){
+        static const char interface[] = PAL_LINUX_ETH;
+        return (void *)&interface[0];
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/OpenWRT_Generic_Linux/pal_startup.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "PlatIncludes.h"
+#include "pal_BSP.h"
+#include <stdio.h>
+
+int fileSystemCreateRootFolders(void);
+
+bool runProgram(testMain_t func, pal_args_t * args)
+{
+	func(args);
+	return true;
+}
+
+
+bspStatus_t initPlatform(void** outputContext)
+{
+    bspStatus_t bspStatus = BSP_SUCCESS;
+    int status = fileSystemCreateRootFolders();
+
+    if (0 != status)
+    {
+        bspStatus = BSP_GENERIC_FAILURE;
+        printf("BSP ERROR: failed to create Root folders\r\n");
+    }
+
+    if (BSP_SUCCESS == bspStatus)
+    {
+        if (NULL != outputContext)
+        {
+            *outputContext = palTestGetNetWorkInterfaceContext();
+        }
+    }
+
+    return bspStatus;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/Yocto_Generic_Linux/BoardInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,15 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/Yocto_Generic_Linux/FileSystemInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "pal.h"
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdio.h>
+
+
+#ifndef PRIMARY_PARTITION_NAME
+#define PRIMARY_PARTITION_NAME "/dev/mmcblk0p3"
+#endif
+
+#ifndef SECONDARY_PARTITION_NAME
+#define SECONDARY_PARTITION_NAME "/dev/mmcblk0p4"
+#endif
+
+#ifndef PAL_PARTITION_FORMAT_TYPE
+#define PAL_PARTITION_FORMAT_TYPE "ext4"
+#endif
+
+#ifndef PARTITION_FORMAT_ADDITIONAL_PARAMS
+#define PARTITION_FORMAT_ADDITIONAL_PARAMS NULL
+#endif
+
+bool FileSystemInit = true;
+
+// Desktop Linux
+// In order for tests to pass for all partition configurations we need to simulate the case of multiple
+// partitions using a single folder. We do this by creating one or two different sub-folders, depending on
+// the configuration.
+int fileSystemCreateRootFolders(void)
+{
+	int status = 0;
+	char folder[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+
+	// Get default mount point.
+	status = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, folder);
+	if(status != 0)
+	{
+	    return 1;
+	}
+	printf("Mount point for primary partition: %s\r\n",folder);
+	// Make the sub-folder
+	int res = mkdir(folder,0744);
+    if(res)
+    {
+        // Ignore error if it exists
+        if( errno != EEXIST)
+        {
+        	printf("mkdir failed errno= %d\r\n",errno);
+            return 1;
+        }
+    }
+
+
+    // Get default mount point.
+    memset(folder,0,sizeof(folder));
+    status = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, folder);
+    printf("Mount point for secondary partition: %s\r\n",folder);
+    if(status != 0)
+    {
+        return 1;
+    }
+
+    // Make the sub-folder
+    res = mkdir(folder,0744);
+    if(res)
+    {
+        // Ignore error if it exists
+        if( errno != EEXIST)
+        {
+        	printf("mkdir failed errno= %d\r\n",errno);
+            return 1;
+        }
+    }       
+	return status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/Yocto_Generic_Linux/NetworkInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <inttypes.h>
+
+#ifndef PAL_LINUX_ETH
+#define PAL_LINUX_ETH "eth0"
+#endif
+
+bool dhcpDone = true;
+
+void* palTestGetNetWorkInterfaceContext(void){
+        static const char interface[] = PAL_LINUX_ETH;
+        return (void *)&interface[0];
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/Yocto_Generic_Linux/pal_startup.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "PlatIncludes.h"
+#include "pal_BSP.h"
+#include <stdio.h>
+
+
+int fileSystemCreateRootFolders(void);
+
+bool runProgram(testMain_t func, pal_args_t * args)
+{
+	func(args);
+	return true;
+}
+
+
+bspStatus_t initPlatform(void** outputContext)
+{
+    bspStatus_t bspStatus = BSP_SUCCESS;
+    int status = fileSystemCreateRootFolders();
+    
+    if (0 != status)
+    {
+        bspStatus = BSP_GENERIC_FAILURE;
+        printf("BSP ERROR: failed to create Root folders\r\n");
+    }
+    
+    if (BSP_SUCCESS == bspStatus)
+    {
+        if (NULL != outputContext)
+        {
+            *outputContext = palTestGetNetWorkInterfaceContext();
+        }
+    }
+
+    return bspStatus;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/mbedOS/FileSystemInit.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,152 @@
+/*******************************************************************************
+* Copyright 2016, 2017 ARM Ltd.
+*
+* 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.
+*******************************************************************************/
+//uncomment this to use littleFS instead of fatFS
+//#define PAL_EXAMPLE_USE_LITTLE_FS
+
+#include "pal.h"
+#include "mbed.h"
+#include "BlockDevice.h"
+#include "MBRBlockDevice.h"
+#include "storage-selector/storage-selector.h"
+
+bool FileSystemInit = false;
+
+#ifndef PRIMARY_PARTITION_NUMBER
+#define PRIMARY_PARTITION_NUMBER 1
+#endif
+
+#ifndef PRIMARY_PARTITION_START
+#define PRIMARY_PARTITION_START 0
+#endif
+
+#ifndef PRIMARY_PARTITION_SIZE
+#define PRIMARY_PARTITION_SIZE 512*1024
+#endif
+
+#ifndef SECONDARY_PARTITION_NUMBER
+#define SECONDARY_PARTITION_NUMBER 2
+#endif
+
+#ifndef SECONDARY_PARTITION_START
+#define SECONDARY_PARTITION_START PRIMARY_PARTITION_SIZE
+#endif
+
+#ifndef SECONDARY_PARTITION_SIZE
+#define SECONDARY_PARTITION_SIZE PRIMARY_PARTITION_SIZE
+#endif
+
+//Uncomment this to create the partitions
+#define PAL_EXAMPLE_GENERATE_PARTITION
+
+//Uncomment this to format partitions if fs->mount() fails
+#define PAL_EXAMPLE_FORMAT_PARTITION
+
+#define PAL_PARTITION_TYPE 0x83
+//
+// See the mbed_lib.json in the sd-driver library for the definitions.
+// See the sd-driver library README.md for details with CI-shield etc.
+// Add also new boards/exceptions there rather than in code directly
+// OR
+// alternatively overload via your mbed_app.json (MBED_CONF_APP...)
+//
+
+static BlockDevice *bd = storage_selector();
+
+static MBRBlockDevice part1(bd, 1);
+static FileSystem  *fs1;
+static MBRBlockDevice part2(bd, 2);
+static FileSystem  *fs2;
+
+
+static int ReFormatPartition(BlockDevice* part, FileSystem* filesystem)
+{
+	int err = 0;
+	printf("re-format partition\r\n");
+	err = filesystem->reformat(part);
+	return err;
+}
+
+static int initFileSystem(BlockDevice* part, FileSystem* filesystem, bool reformat)
+{
+	int err = 0;
+	if (reformat)
+	{
+		err = filesystem->reformat(part);
+	}
+	err = filesystem->unmount(); // filesystem_selector func do mount but doesnt return value , for checking if mount function return error we need first to unmount and then try to mount again.
+	if (err < 0) {
+		printf("failed to unmount %d\r\n", err);
+	}
+	err = filesystem->mount(part);
+	if (err < 0) {
+		printf("failed to mount %d\r\n", err);
+		err = ReFormatPartition(part, filesystem);
+	}
+	if (err == 0) {
+		err = filesystem->mkdir("bsp_test", 0600); // FATFS miss magic field. mkdir to check FS correctness.
+		if (err != 0) {
+			printf("failed to mkdir - reformat \r\n");
+			err = ReFormatPartition(part, filesystem);
+		}
+		filesystem->remove("bsp_test"); // delete in any case even after format
+	}
+	return err;
+}
+
+int initSDcardAndFileSystem(bool reformat)
+{
+	int err = 0;
+	printf("Initializing the file system\r\n");
+#if (MBED_CONF_STORAGE_SELECTOR_FILESYSTEM_INSTANCES > 0)
+		err = part1.init();
+		if (err < 0)
+		{
+			printf("failed to init primary partition cause %d\r\n", err);
+			err = MBRBlockDevice::partition(bd, PRIMARY_PARTITION_NUMBER, PAL_PARTITION_TYPE, PRIMARY_PARTITION_START, PRIMARY_PARTITION_START + PRIMARY_PARTITION_SIZE);
+			if (err < 0) {
+				printf("Failed to initialize primary partition\r\n");
+			}
+		}
+		if (!err)
+		{
+			fs1 = filesystem_selector(((char*)PAL_FS_MOUNT_POINT_PRIMARY + 1), &part1, 1);
+			err = initFileSystem(&part1, fs1, reformat);
+		}
+	#if (MBED_CONF_STORAGE_SELECTOR_FILESYSTEM_INSTANCES == 2)
+				if (!err) {
+					err = part2.init();
+					if (err < 0) {
+						printf("failed to init secondary partition cause %d\r\n", err);
+						err = MBRBlockDevice::partition(bd, SECONDARY_PARTITION_NUMBER, PAL_PARTITION_TYPE, SECONDARY_PARTITION_START, SECONDARY_PARTITION_START + SECONDARY_PARTITION_SIZE);
+						if (err < 0) {
+							printf("Failed to initialize secondary partition\r\n");
+						}
+					}
+					if (!err) {
+						fs2 = filesystem_selector(((char*)PAL_FS_MOUNT_POINT_SECONDARY + 1), &part2, 2);
+						err = initFileSystem(&part2, fs2, reformat);
+					}
+				}
+	#endif
+#endif
+	if (!err)
+	{
+		printf("Succeed to initialize the file system\r\n");
+		FileSystemInit = true;
+	}
+
+	return err;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/mbedOS/NetworkInit.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "mbed.h"
+#include "EthernetInterface.h"
+
+bool dhcpDone = true;
+static EthernetInterface* netInterface = NULL;
+extern "C" {
+    void* palTestGetNetWorkInterfaceContext(void)
+    {
+        nsapi_error_t status = NSAPI_ERROR_OK;
+        if (NULL == netInterface)
+        {
+            netInterface = new EthernetInterface();
+            printf("new interface created\r\n");
+            status = netInterface->connect();
+            if (NSAPI_ERROR_OK == status)
+            {
+                printf("interface registered : OK \r\n");
+            }
+            else //connect failed
+            {
+                printf("interface registered : FAILED! \r\n");
+                delete netInterface;
+                netInterface = NULL;
+            }
+        }
+        return netInterface;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/mbedOS/pal_startup.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "PlatIncludes.h"
+#include "pal_BSP.h"
+#include "mbed.h"
+
+#ifndef TEST_K64F_BAUD_RATE
+#define TEST_K64F_BAUD_RATE 115200
+#endif
+
+#ifndef TEST_MAIN_THREAD_STACK_SIZE
+#define TEST_MAIN_THREAD_STACK_SIZE (1024*7)
+#endif
+
+extern int initSDcardAndFileSystem(bool reformat);
+
+Serial pc(USBTX, USBRX);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+bool runProgram(testMain_t func, pal_args_t * args)
+{
+	Thread thread(osPriorityNormal, TEST_MAIN_THREAD_STACK_SIZE);
+	thread.start(callback(func, args));
+	wait(1); // to be on the safe side - sleep for 1sec
+	bool result = (thread.join() == osOK);
+	return result;
+}
+
+bspStatus_t initPlatformReformat(void** outputContext)
+{
+    bspStatus_t bspStatus = BSP_SUCCESS;
+    int err = 0;
+
+    pc.baud(TEST_K64F_BAUD_RATE);
+
+    err = initSDcardAndFileSystem(true);
+    if (err < 0) {
+        bspStatus = BSP_GENERIC_FAILURE;
+        printf("BSP ERROR: failed to init SD card and filesystem \r\n");
+    }
+
+    if (BSP_SUCCESS == bspStatus)
+    {
+        if (NULL != outputContext)
+        {
+            *outputContext = palTestGetNetWorkInterfaceContext();
+        }
+    }
+
+    return bspStatus;
+}
+
+bspStatus_t initPlatform(void** outputContext)
+{
+    bspStatus_t bspStatus = BSP_SUCCESS;
+    int err = 0;
+
+    pc.baud(TEST_K64F_BAUD_RATE);
+
+    err = initSDcardAndFileSystem(false);
+    if (err < 0) {
+        bspStatus = BSP_GENERIC_FAILURE;
+        printf("BSP ERROR: failed to init SD card and filesystem \r\n");
+    }
+
+    if (BSP_SUCCESS == bspStatus)
+    {
+        if (NULL != outputContext)
+        {
+            *outputContext = palTestGetNetWorkInterfaceContext();
+        }
+    }
+
+    return bspStatus;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/pal_insecure_ROT.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "pal.h"
+#define PAL_DEVICE_KEY_SIZE_IN_BYTES 16
+
+//THIS CODE IS FOR TESTING PURPOSES ONLY. DO NOT USE IN PRODUCTION ENVIRONMENTS. REPLACE WITH A PROPER IMPLEMENTATION BEFORE USE
+palStatus_t  __attribute__((weak)) pal_plat_osGetRoTFromHW(uint8_t *keyBuf, size_t keyLenBytes)
+{
+    #if defined (__CC_ARM)          /* ARM compiler. */
+    #warning("PAL_INSECURE- You are using insecure Root Of Trust implementation, DO NOT USE IN PRODUCTION ENVIRONMENTS. REPLACE WITH A PROPER IMPLEMENTATION BEFORE USE")
+    #else
+    #pragma message ("You are using insecure Root Of Trust implementation, DO NOT USE IN PRODUCTION ENVIRONMENTS. REPLACE WITH A PROPER IMPLEMENTATION BEFORE USE")
+    #endif
+
+	PAL_LOG(WARN, "You are using insecure Root Of Trust implementation");
+
+    if (keyLenBytes < PAL_DEVICE_KEY_SIZE_IN_BYTES)
+	{
+		return PAL_ERR_BUFFER_TOO_SMALL;
+	}
+
+	if (NULL == keyBuf)
+	{
+        return PAL_ERR_NULL_POINTER;
+	}
+
+    for (int i=0; i < PAL_DEVICE_KEY_SIZE_IN_BYTES; i++)
+    {
+        keyBuf[i] = i;
+    }
+	return PAL_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/x86_x64_Linux/BoardInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,15 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/x86_x64_Linux/FileSystemInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "pal.h"
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdio.h>
+
+bool FileSystemInit = true;
+
+// Desktop Linux
+// In order for tests to pass for all partition configurations we need to simulate the case of multiple
+// partitions using a single folder. We do this by creating one or two different sub-folders, depending on
+// the configuration.
+int fileSystemCreateRootFolders(void)
+{
+	int status = 0;
+	char folder[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+
+	// Get default mount point.
+	status = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, folder);
+	if(status != 0)
+	{
+	    return 1;
+	}
+	printf("Mount point for primary partition: %s\r\n",folder);
+	// Make the sub-folder
+	int res = mkdir(folder,0744);
+    if(res)
+    {
+        // Ignore error if it exists
+        if( errno != EEXIST)
+        {
+        	printf("mkdir failed errno= %d\r\n",errno);
+            return 1;
+        }
+    }
+
+    // Get default mount point.
+    memset(folder,0,sizeof(folder));
+    status = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, folder);
+    printf("Mount point for secondary partition: %s\r\n",folder);
+    if(status != 0)
+    {
+        return 1;
+    }
+
+    // Make the sub-folder
+    res = mkdir(folder,0744);
+    if(res)
+    {
+        // Ignore error if it exists
+        if( errno != EEXIST)
+        {
+        	printf("mkdir failed errno= %d\r\n",errno);
+            return 1;
+        }
+    }       
+	return status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/x86_x64_Linux/NetworkInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <inttypes.h>
+
+#ifndef PAL_LINUX_ETH
+#define PAL_LINUX_ETH "eth0"
+#endif
+
+bool dhcpDone = true;
+
+void* palTestGetNetWorkInterfaceContext(void){
+        static const char interface[] = PAL_LINUX_ETH;
+        return (void *)&interface[0];
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Examples/PlatformBSP/x86_x64_Linux/pal_startup.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "PlatIncludes.h"
+#include "pal_BSP.h"
+#include <stdio.h>
+
+int fileSystemCreateRootFolders(void);
+
+bool runProgram(testMain_t func, pal_args_t * args)
+{
+	func(args);
+	return true;
+}
+
+
+bspStatus_t initPlatform(void** outputContext)
+{
+    bspStatus_t bspStatus = BSP_SUCCESS;
+    int status = fileSystemCreateRootFolders();
+
+    if (0 != status)
+    {
+        bspStatus = BSP_GENERIC_FAILURE;
+        printf("BSP ERROR: failed to create Root folders\r\n");
+    }
+
+    if (BSP_SUCCESS == bspStatus)
+    {
+        if (NULL != outputContext)
+        {
+            *outputContext = palTestGetNetWorkInterfaceContext();
+        }
+    }
+
+    return bspStatus;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+Unless specifically indicated otherwise in a file, files are licensed
+under the Apache 2.0 license, as can be found in: apache-2.0.txt
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/CMakeLists.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,31 @@
+include_directories(Port/Platform-API)
+ADD_GLOBALDIR( ${CMAKE_CURRENT_SOURCE_DIR}/PAL-Impl/Services-API)
+
+set (PAL_MODULES_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/PAL-Impl/Modules)
+set (PAL_PORT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Port/Reference-Impl/OS_Specific/${OS_BRAND})
+
+set(PAL_SRCS
+    ${PAL_PORT_SOURCE_DIR}/Networking/${NETWORK_STACK}/pal_plat_network.c
+    ${PAL_PORT_SOURCE_DIR}/RTOS/pal_plat_rtos.c
+    ${PAL_PORT_SOURCE_DIR}/../../Lib_Specific/${TLS_LIBRARY}/TLS/pal_plat_TLS.c
+    ${PAL_PORT_SOURCE_DIR}/../../Lib_Specific/${TLS_LIBRARY}/Crypto/pal_plat_Crypto.c
+    ${PAL_PORT_SOURCE_DIR}/Update/pal_plat_update.c
+    ${PAL_PORT_SOURCE_DIR}/Storage/FileSystem/pal_plat_fileSystem.c    
+    ${PAL_PORT_SOURCE_DIR}/Board_Specific/TARGET_${MBED_CLOUD_CLIENT_DEVICE}/pal_plat_${MBED_CLOUD_CLIENT_DEVICE}.c        
+
+    ${PAL_MODULES_SOURCE_DIR}/Networking/pal_network.c
+    ${PAL_MODULES_SOURCE_DIR}/RTOS/pal_rtos.c
+    ${PAL_MODULES_SOURCE_DIR}/TLS/pal_TLS.c
+    ${PAL_MODULES_SOURCE_DIR}/Crypto/pal_Crypto.c
+    ${PAL_MODULES_SOURCE_DIR}/Update/pal_update.c
+    ${PAL_MODULES_SOURCE_DIR}/Storage/FileSystem/pal_fileSystem.c
+    ${PAL_MODULES_SOURCE_DIR}/Storage/Flash/pal_internalFlash.c
+
+    ${CMAKE_CURRENT_SOURCE_DIR}/PAL-Impl/pal_init.c 
+)
+
+if ( NOT (${OS_BRAND} MATCHES "Linux"))        
+       set (PAL_SRCS ${PAL_SRCS} ${PAL_PORT_SOURCE_DIR}/Storage/Flash/pal_plat_internalFlash.c)
+endif() 
+
+CREATE_LIBRARY(pal "${PAL_SRCS}" "")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Crypto/pal_Crypto.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,642 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "pal.h"
+#include "pal_plat_Crypto.h"
+
+
+palStatus_t pal_initAes(palAesHandle_t *aes)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == aes))
+
+    status = pal_plat_initAes(aes);
+    return status;
+}
+
+palStatus_t pal_freeAes(palAesHandle_t *aes)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == aes || (uintptr_t)NULL == *aes))
+
+    status = pal_plat_freeAes(aes);
+    return status;
+}
+
+palStatus_t pal_setAesKey(palAesHandle_t aes, const unsigned char* key, uint32_t keybits, palAesKeyType_t keyTarget)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == aes || NULL == key))
+
+    status = pal_plat_setAesKey(aes, key, keybits, keyTarget);
+    return status;
+}
+
+palStatus_t pal_aesCTR(palAesHandle_t aes, const unsigned char* input, unsigned char* output, size_t inLen, unsigned char iv[16])
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == aes || NULL == input || NULL == output || NULL == iv))
+
+    status = pal_plat_aesCTR(aes, input, output, inLen, iv, false);
+    return status;
+}
+
+palStatus_t pal_aesCTRWithZeroOffset(palAesHandle_t aes, const unsigned char* input, unsigned char* output, size_t inLen, unsigned char iv[16])
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == aes || NULL == input || NULL == output || NULL == iv))
+
+    status = pal_plat_aesCTR(aes, input, output, inLen, iv, true);
+    return status;
+}
+
+palStatus_t pal_aesECB(palAesHandle_t aes, const unsigned char input[PAL_CRYPT_BLOCK_SIZE], unsigned char output[PAL_CRYPT_BLOCK_SIZE], palAesMode_t mode)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == aes || NULL == input || NULL == output))
+
+    status = pal_plat_aesECB(aes, input, output, mode);
+    return status;
+}
+
+palStatus_t pal_sha256(const unsigned char* input, size_t inLen, unsigned char* output)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == input || NULL == output))
+
+    status = pal_plat_sha256(input, inLen, output);
+    return status;
+}
+
+palStatus_t pal_x509Initiate(palX509Handle_t* x509Cert)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS( (NULL == x509Cert))
+
+    status = pal_plat_x509Initiate(x509Cert);
+    return status;
+#else
+	return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_x509CertParse(palX509Handle_t x509Cert, const unsigned char* input, size_t inLen)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509Cert || NULL == input))
+
+    status = pal_plat_x509CertParse(x509Cert, input, inLen);
+    return status;
+#else
+	return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_x509CertGetAttribute(palX509Handle_t x509Cert, palX509Attr_t attr, void* output, size_t outLenBytes, size_t* actualOutLenBytes)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509Cert || NULL == output || NULL == actualOutLenBytes))
+
+    status = pal_plat_x509CertGetAttribute(x509Cert, attr, output, outLenBytes, actualOutLenBytes);
+    return status;
+#else
+	return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_x509CertVerifyExtended(palX509Handle_t x509Cert, palX509Handle_t x509CertChain, int32_t* verifyResult)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509Cert) || (NULL == verifyResult))
+    *verifyResult = 0;
+#if (PAL_ENABLE_X509 == 1)
+    status = pal_plat_x509CertVerifyExtended(x509Cert, x509CertChain, verifyResult);
+    if (0 != *verifyResult)
+    {
+        status = PAL_ERR_X509_CERT_VERIFY_FAILED;
+        *verifyResult = *verifyResult ^ PAL_ERR_MODULE_BITMASK_BASE; //! in order to turn off the MSB bit.
+    }
+#endif
+    return status;
+}
+
+palStatus_t pal_x509CertVerify(palX509Handle_t x509Cert, palX509Handle_t x509CertChain)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    int32_t verifyResult = 0;
+
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509Cert))
+
+    status = pal_plat_x509CertVerifyExtended(x509Cert, x509CertChain, &verifyResult);
+    return status;
+#else
+	return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_x509Free(palX509Handle_t* x509Cert)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509Cert || NULLPTR == *x509Cert))
+
+    status = pal_plat_x509Free(x509Cert);
+    return status;
+#else
+	return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_mdInit(palMDHandle_t* md, palMDType_t mdType)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == md))
+
+    status = pal_plat_mdInit(md, mdType);
+    return status;
+}
+
+palStatus_t pal_mdUpdate(palMDHandle_t md, const unsigned char* input, size_t inLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == md || NULL == input))
+
+    status = pal_plat_mdUpdate(md, input, inLen);
+    return status;
+}
+
+palStatus_t pal_mdGetOutputSize(palMDHandle_t md, size_t* bufferSize)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == md || NULL == bufferSize))
+
+    status = pal_plat_mdGetOutputSize(md, bufferSize);
+    return status;
+}
+
+palStatus_t pal_mdFinal(palMDHandle_t md, unsigned char* output)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == md || NULL == output))
+
+    status = pal_plat_mdFinal(md, output);
+    return status;
+}
+
+palStatus_t pal_mdFree(palMDHandle_t* md)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == md || NULLPTR == *md))
+
+    status = pal_plat_mdFree(md);
+    return status;
+}
+
+palStatus_t pal_verifySignature(palX509Handle_t x509, palMDType_t mdType, const unsigned char *hash, size_t hashLen, const unsigned char *sig, size_t sigLen)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509 || NULL == hash || NULL == sig))
+
+    status = pal_plat_verifySignature(x509, mdType, hash, hashLen, sig, sigLen);
+    return status;
+#else
+	return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+ 
+palStatus_t pal_ASN1GetTag(unsigned char **position, const unsigned char *end, size_t *len, uint8_t tag )
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == position || NULL == end || NULL == len))
+    
+    status = pal_plat_ASN1GetTag(position, end, len, tag);
+    return status;
+}
+
+palStatus_t pal_CCMInit(palCCMHandle_t* ctx)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == ctx))
+
+    status = pal_plat_CCMInit(ctx);
+    return status;
+}
+
+palStatus_t pal_CCMFree(palCCMHandle_t* ctx)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == ctx || NULLPTR == *ctx))
+
+    status = pal_plat_CCMFree(ctx);
+    return status;
+}
+
+palStatus_t pal_CCMSetKey(palCCMHandle_t ctx, const unsigned char *key, uint32_t keybits, palCipherID_t id)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == ctx || NULL == key))
+
+    status = pal_plat_CCMSetKey(ctx, id, key, keybits);
+    return status;
+}
+
+palStatus_t pal_CCMDecrypt(palCCMHandle_t ctx, unsigned char* input, size_t inLen, 
+							unsigned char* iv, size_t ivLen, unsigned char* add, 
+							size_t addLen, unsigned char* tag, size_t tagLen, 
+							unsigned char* output)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == ctx || NULL == input || NULL == iv || NULL == add || NULL == tag || NULL == output))
+
+    status = pal_plat_CCMDecrypt(ctx, input, inLen, iv, ivLen, add, addLen, tag, tagLen, output);
+    return status;
+}
+
+palStatus_t pal_CCMEncrypt(palCCMHandle_t ctx, unsigned char* input, 
+							size_t inLen, unsigned char* iv, size_t ivLen, 
+							unsigned char* add, size_t addLen, unsigned char* output, 
+							unsigned char* tag, size_t tagLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == ctx || NULL == input || NULL == iv || NULL == add || NULL == tag || NULL == output))
+
+    status = pal_plat_CCMEncrypt(ctx, input, inLen, iv, ivLen, add, addLen, output, tag, tagLen);
+    return status;
+}
+
+palStatus_t pal_CtrDRBGInit(palCtrDrbgCtxHandle_t* ctx, const void* seed, size_t len)
+{
+    palStatus_t status = PAL_SUCCESS;
+
+    PAL_VALIDATE_ARGUMENTS((NULL == ctx || NULL == seed))
+
+    status = pal_plat_CtrDRBGInit(ctx);
+    if (PAL_SUCCESS == status)
+    {
+        status = pal_plat_CtrDRBGSeed(*ctx, seed, len);
+        if (PAL_SUCCESS != status)
+        {
+            palStatus_t tmpStatus = PAL_SUCCESS;
+            tmpStatus = pal_CtrDRBGFree(ctx);
+            if (PAL_SUCCESS != tmpStatus)
+            {
+                PAL_LOG(ERR, "Failed to release CTR-DRBG context %" PRId32 ".", tmpStatus);
+            }
+        }
+    }
+
+    return status;
+}
+
+palStatus_t pal_CtrDRBGGenerate(palCtrDrbgCtxHandle_t ctx, unsigned char* out, size_t len)
+{
+    palStatus_t status = PAL_SUCCESS;
+
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == ctx || NULL == out))
+
+    status = pal_plat_CtrDRBGGenerate(ctx, out, len);
+    return status;
+}
+
+palStatus_t pal_CtrDRBGFree(palCtrDrbgCtxHandle_t* ctx)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == ctx || NULLPTR == *ctx))
+
+    status = pal_plat_CtrDRBGFree(ctx);
+    return status;
+}
+
+palStatus_t pal_cipherCMAC(const unsigned char *key, size_t keyLenInBits, const unsigned char *input, size_t inputLenInBytes, unsigned char *output)
+{
+	palStatus_t status = PAL_SUCCESS;
+	PAL_VALIDATE_ARGUMENTS((NULL == key || NULL == input || NULL == output))
+#if PAL_CMAC_SUPPORT
+    status = pal_plat_cipherCMAC(key, keyLenInBits, input, inputLenInBytes, output);
+#else   // no CMAC support		
+    status = PAL_ERR_NOT_SUPPORTED;
+    PAL_LOG(ERR, "CMAC support in PAL is disabled");		
+#endif 
+    return status;
+}
+
+palStatus_t pal_CMACStart(palCMACHandle_t *ctx, const unsigned char *key, size_t keyLenBits, palCipherID_t cipherID)
+{
+	palStatus_t status = PAL_SUCCESS;
+	PAL_VALIDATE_ARGUMENTS((NULLPTR == ctx || NULL == key))
+#if PAL_CMAC_SUPPORT
+    status = pal_plat_CMACStart(ctx, key, keyLenBits, cipherID);
+#else   // no CMAC support		
+    status = PAL_ERR_NOT_SUPPORTED;
+    PAL_LOG(ERR, "CMAC support in PAL is disabled");		
+#endif
+    return status;
+}
+
+palStatus_t pal_CMACUpdate(palCMACHandle_t ctx, const unsigned char *input, size_t inLen)
+{
+#if PAL_CMAC_SUPPORT
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == ctx || NULL == input))
+
+    status = pal_plat_CMACUpdate(ctx, input, inLen);
+#else   // no CMAC support		
+    palStatus_t status = PAL_ERR_NOT_SUPPORTED;		
+    PAL_LOG(ERR, "CMAC support in PAL is disabled");		
+#endif 
+    return status;
+}
+
+palStatus_t pal_CMACFinish(palCMACHandle_t *ctx, unsigned char *output, size_t* outLen)
+{
+#if PAL_CMAC_SUPPORT
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS(NULLPTR == ctx || NULLPTR == *ctx || NULL == output || NULL == outLen)
+
+    status = pal_plat_CMACFinish(ctx, output, outLen);
+#else   // no CMAC support		
+    palStatus_t status = PAL_ERR_NOT_SUPPORTED;		
+    PAL_LOG(ERR, "CMAC support in PAL is disabled");		
+#endif 
+    return status;
+}
+
+palStatus_t pal_mdHmacSha256(const unsigned char *key, size_t keyLenInBytes, const unsigned char *input, size_t inputLenInBytes, unsigned char *output, size_t* outputLenInBytes)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == key || NULL == input || NULL == output))
+
+    status = pal_plat_mdHmacSha256(key, keyLenInBytes, input, inputLenInBytes, output, outputLenInBytes);
+    return status;
+}
+
+palStatus_t pal_ECCheckKey(palCurveHandle_t grp, palECKeyHandle_t key, uint32_t type, bool *verified)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == grp || NULLPTR == key || NULL == verified))
+
+    status = pal_plat_ECCheckKey(grp, key, type, verified);
+    return status;
+}
+
+palStatus_t pal_ECKeyNew(palECKeyHandle_t* key)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == key))
+
+    status = pal_plat_ECKeyNew(key);
+    return status;
+}
+
+palStatus_t pal_ECKeyFree(palECKeyHandle_t* key)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == key || NULLPTR == *key))
+
+    status = pal_plat_ECKeyFree(key);
+    return status;
+}
+
+palStatus_t pal_parseECPrivateKeyFromDER(const unsigned char* prvDERKey, size_t keyLen, palECKeyHandle_t key)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == prvDERKey || NULLPTR == key))
+
+    status = pal_plat_parseECPrivateKeyFromDER(prvDERKey, keyLen, key);
+    return status;
+}
+
+palStatus_t pal_parseECPublicKeyFromDER(const unsigned char* pubDERKey, size_t keyLen, palECKeyHandle_t key)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == pubDERKey || NULLPTR == key))
+
+    status = pal_plat_parseECPublicKeyFromDER(pubDERKey, keyLen, key);
+    return status;
+}
+
+palStatus_t pal_writePrivateKeyToDer(palECKeyHandle_t key, unsigned char* derBuffer, size_t bufferSize, size_t* actualSize)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == key || NULL == derBuffer || NULL == actualSize))
+
+    status = pal_plat_writePrivateKeyToDer(key, derBuffer, bufferSize, actualSize);
+    return status;
+}
+
+palStatus_t pal_writePublicKeyToDer(palECKeyHandle_t key, unsigned char* derBuffer, size_t bufferSize, size_t* actualSize)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == key || NULL == derBuffer || NULL == actualSize))
+
+    status = pal_plat_writePublicKeyToDer(key, derBuffer, bufferSize, actualSize);
+    return status;
+}
+palStatus_t pal_ECGroupInitAndLoad(palCurveHandle_t* grp, palGroupIndex_t index)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == grp))
+
+    status = pal_plat_ECGroupInitAndLoad(grp, index);
+    return status;
+}
+
+palStatus_t pal_ECGroupFree(palCurveHandle_t* grp)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == grp || NULLPTR == *grp))
+
+    status = pal_plat_ECGroupFree(grp);
+    return status;
+}
+
+palStatus_t pal_ECKeyGenerateKey(palGroupIndex_t grpID, palECKeyHandle_t key)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == key))
+
+    status = pal_plat_ECKeyGenerateKey(grpID, key);
+    return status;
+}
+
+palStatus_t pal_ECKeyGetCurve(palECKeyHandle_t key, palGroupIndex_t* grpID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == key || NULL == grpID))
+
+    status = pal_plat_ECKeyGetCurve(key, grpID);
+    return status;
+}
+
+palStatus_t pal_x509CSRInit(palx509CSRHandle_t *x509CSR)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == x509CSR))
+
+    status = pal_plat_x509CSRInit(x509CSR);
+    return status;
+#else
+    return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_x509CSRSetSubject(palx509CSRHandle_t x509CSR, const char* subjectName)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509CSR || NULL == subjectName))
+
+    status = pal_plat_x509CSRSetSubject(x509CSR, subjectName);
+    return status;
+#else
+    return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_x509CSRSetKey(palx509CSRHandle_t x509CSR, palECKeyHandle_t pubKey, palECKeyHandle_t prvKey)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509CSR || NULLPTR == pubKey))
+
+    status = pal_plat_x509CSRSetKey(x509CSR, pubKey, prvKey);
+    return status;
+#else
+    return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_x509CSRSetMD(palx509CSRHandle_t x509CSR, palMDType_t mdType)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509CSR))
+
+    status = pal_plat_x509CSRSetMD(x509CSR, mdType);
+    return status;
+#else
+    return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_x509CSRSetKeyUsage(palx509CSRHandle_t x509CSR, uint32_t keyUsage)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509CSR))
+
+    status = pal_plat_x509CSRSetKeyUsage(x509CSR, keyUsage);
+    return status;
+#else
+    return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_x509CSRSetExtendedKeyUsage(palx509CSRHandle_t x509CSR, uint32_t extKeyUsage)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509CSR))
+
+    status = pal_plat_x509CSRSetExtendedKeyUsage(x509CSR, extKeyUsage);
+    return status;
+#else
+    return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_x509CSRSetExtension(palx509CSRHandle_t x509CSR,const char* oid, size_t oidLen, const unsigned char* value, size_t valueLen)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509CSR || NULL == oid || NULL == value))
+
+    status = pal_plat_x509CSRSetExtension(x509CSR, oid, oidLen, value, valueLen);
+    return status;
+#else
+    return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_x509CSRWriteDER(palx509CSRHandle_t x509CSR, unsigned char* derBuf, size_t derBufLen, size_t* actualDerLen)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == x509CSR || NULL == derBuf))
+
+    status = pal_plat_x509CSRWriteDER(x509CSR, derBuf, derBufLen, actualDerLen);
+    return status;
+#else
+    return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_x509CSRFree(palx509CSRHandle_t *x509CSR)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == x509CSR || NULLPTR == *x509CSR))
+
+    status = pal_plat_x509CSRFree(x509CSR);
+    return status;
+#else
+    return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_ECDHComputeKey(const palCurveHandle_t grp, const palECKeyHandle_t peerPublicKey, 
+                            const palECKeyHandle_t privateKey, palECKeyHandle_t outKey)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == grp || NULLPTR == peerPublicKey || NULLPTR == privateKey || NULLPTR == outKey))
+
+    status = pal_plat_ECDHComputeKey(grp, peerPublicKey, privateKey, outKey);
+    return status;
+}
+
+palStatus_t pal_ECDSASign(palCurveHandle_t grp, palMDType_t mdType, palECKeyHandle_t prvKey, unsigned char* dgst, 
+							uint32_t dgstLen, unsigned char *sig, size_t *sigLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == grp || NULLPTR == prvKey || NULL == dgst || NULL == sig || NULL == sigLen))
+    
+    status = pal_plat_ECDSASign(grp, mdType, prvKey, dgst, dgstLen, sig, sigLen);
+    return status;
+}
+
+palStatus_t pal_ECDSAVerify(palECKeyHandle_t pubKey, unsigned char* dgst, uint32_t dgstLen, 
+                            unsigned char* sig, size_t sigLen, bool* verified)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == pubKey || NULL == dgst || NULL == sig || NULL == verified))
+    
+    status = pal_plat_ECDSAVerify(pubKey, dgst, dgstLen, sig, sigLen, verified);
+    return status;
+}
+
+palStatus_t pal_x509CertGetHTBS(palX509Handle_t x509Cert, palMDType_t hash_type, unsigned char *output, size_t outLenBytes, size_t* actualOutLenBytes)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS((NULL == output || NULL == actualOutLenBytes || NULLPTR == x509Cert));
+
+    status = pal_plat_x509CertGetHTBS(x509Cert, hash_type, output, outLenBytes, actualOutLenBytes);
+    return status;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Networking/pal_network.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,488 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#include "pal.h"
+#include "pal_network.h"
+#include "pal_plat_network.h"
+
+typedef struct pal_in_addr {
+    uint32_t s_addr; // that's a 32-bit int (4 bytes)
+} pal_in_addr_t;
+
+#if PAL_SUPPORT_IP_V4
+typedef struct pal_socketAddressInternal {
+    short int          pal_sin_family;  // address family
+    unsigned short int pal_sin_port;    // port
+    pal_in_addr_t     pal_sin_addr;    // ipv4 address
+    unsigned char      pal_sin_zero[8]; // 
+} pal_socketAddressInternal_t;
+#endif
+
+#if PAL_SUPPORT_IP_V6
+typedef struct pal_socketAddressInternal6{
+    uint16_t       pal_sin6_family;   // address family, 
+    uint16_t       pal_sin6_port;     // port number, Network Byte Order
+    uint32_t       pal_sin6_flowinfo; // IPv6 flow information
+    palIpV6Addr_t pal_sin6_addr;     // IPv6 address
+    uint32_t       pal_sin6_scope_id; // Scope ID
+} pal_socketAddressInternal6_t;
+#endif
+
+#if PAL_NET_DNS_SUPPORT
+
+// structure used by pal_getAddressInfoAsync
+#ifndef PAL_DNS_API_V2
+typedef struct pal_asyncAddressInfo
+{
+    char* url;
+    palSocketAddress_t* address;
+    palSocketLength_t* addressLength;
+    palGetAddressInfoAsyncCallback_t callback;
+    void* callbackArgument;
+} pal_asyncAddressInfo_t;
+#endif // PAL_DNS_API_V2
+#endif // PAL_NET_DNS_SUPPORT
+
+palStatus_t pal_registerNetworkInterface(void* networkInterfaceContext, uint32_t* interfaceIndex)
+{
+    PAL_VALIDATE_ARGUMENTS((networkInterfaceContext == NULL) || (interfaceIndex == NULL));
+    palStatus_t result = pal_plat_registerNetworkInterface(networkInterfaceContext, interfaceIndex);;
+
+    return result;
+}
+
+palStatus_t pal_setSockAddrPort(palSocketAddress_t* address, uint16_t port)
+{
+    palStatus_t result = PAL_SUCCESS;
+    bool found = false;
+    PAL_VALIDATE_ARGUMENTS(NULL == address);
+
+#if PAL_SUPPORT_IP_V4
+    if (address->addressType == PAL_AF_INET)
+    {
+        pal_socketAddressInternal_t* innerAddr = (pal_socketAddressInternal_t*)address;
+        // Set Linux format
+        innerAddr->pal_sin_port = PAL_HTONS(port);
+        found = true;
+    }
+#endif
+
+#if PAL_SUPPORT_IP_V6
+    if (address->addressType == PAL_AF_INET6)
+    {
+        pal_socketAddressInternal6_t * innerAddr = (pal_socketAddressInternal6_t*)address;
+        // Set Linux format
+        innerAddr->pal_sin6_port = PAL_HTONS(port);
+        found = true;
+    }
+#endif
+    if (false == found)
+    {
+        result =  PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY;
+    }
+
+    return result;
+}
+
+
+
+#if PAL_SUPPORT_IP_V4
+palStatus_t pal_setSockAddrIPV4Addr(palSocketAddress_t* address, palIpV4Addr_t ipV4Addr)
+{
+    PAL_VALIDATE_ARGUMENTS((NULL == address) || (NULL == ipV4Addr));
+
+    pal_socketAddressInternal_t* innerAddr = (pal_socketAddressInternal_t*)address;
+    innerAddr->pal_sin_family = PAL_AF_INET;
+    innerAddr->pal_sin_addr.s_addr = (ipV4Addr[0]) | (ipV4Addr[1] << 8) | (ipV4Addr[2] << 16) | (ipV4Addr[3] << 24);
+    return PAL_SUCCESS;
+}
+
+palStatus_t pal_getSockAddrIPV4Addr(const palSocketAddress_t* address, palIpV4Addr_t ipV4Addr)
+{
+    PAL_VALIDATE_ARGUMENTS(NULL == address);
+    PAL_VALIDATE_CONDITION_WITH_ERROR((address->addressType != PAL_AF_INET),PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY);
+    palStatus_t result = PAL_SUCCESS;
+
+    if (address->addressType == PAL_AF_INET)
+    {
+        pal_socketAddressInternal_t* innerAddr = (pal_socketAddressInternal_t*)address;
+        ipV4Addr[0] = (innerAddr->pal_sin_addr.s_addr) & 0xFF;
+        ipV4Addr[1] = (innerAddr->pal_sin_addr.s_addr >> 8) & 0xFF;
+        ipV4Addr[2] = (innerAddr->pal_sin_addr.s_addr >> 16) & 0xFF;
+        ipV4Addr[3] = (innerAddr->pal_sin_addr.s_addr >> 24) & 0xFF;
+
+    }
+
+    return result;
+}
+#else 
+palStatus_t pal_setSockAddrIPV4Addr(palSocketAddress_t* address, palIpV4Addr_t ipV4Addr)
+{
+    return PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY;
+}
+palStatus_t pal_getSockAddrIPV4Addr(const palSocketAddress_t* address, palIpV4Addr_t ipV4Addr)
+{
+    return PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY;
+}
+
+#endif
+
+
+#if PAL_SUPPORT_IP_V6
+palStatus_t pal_getSockAddrIPV6Addr(const palSocketAddress_t* address, palIpV6Addr_t ipV6Addr)
+{ 
+    palStatus_t result = PAL_SUCCESS;
+    int index = 0;
+    PAL_VALIDATE_ARGUMENTS (NULL == address);
+    PAL_VALIDATE_CONDITION_WITH_ERROR((address->addressType != PAL_AF_INET6),PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY);
+   
+    pal_socketAddressInternal6_t * innerAddr = (pal_socketAddressInternal6_t*)address;
+    for (index = 0; index < PAL_IPV6_ADDRESS_SIZE; index++) // TODO: use mem copy?
+    {
+        ipV6Addr[index] = innerAddr->pal_sin6_addr[index];
+    }
+
+
+    return result;
+}
+
+palStatus_t pal_setSockAddrIPV6Addr(palSocketAddress_t* address, palIpV6Addr_t ipV6Addr)
+{
+    int index;
+    PAL_VALIDATE_ARGUMENTS((NULL == address) || (NULL == ipV6Addr));
+
+    pal_socketAddressInternal6_t* innerAddr = (pal_socketAddressInternal6_t*)address;
+    innerAddr->pal_sin6_family = PAL_AF_INET6;
+    for (index = 0; index < PAL_IPV6_ADDRESS_SIZE; index++) // TODO: use mem copy?
+    {
+        innerAddr->pal_sin6_addr[index] = ipV6Addr[index];
+    }
+    return PAL_SUCCESS;
+}
+#else
+palStatus_t pal_setSockAddrIPV6Addr(palSocketAddress_t* address, palIpV6Addr_t ipV6Addr)
+{
+    return PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY;
+}
+
+palStatus_t pal_getSockAddrIPV6Addr(const palSocketAddress_t* address, palIpV6Addr_t ipV6Addr)
+{
+    return PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY;
+}
+
+#endif
+
+
+palStatus_t pal_getSockAddrPort(const palSocketAddress_t* address, uint16_t* port)
+{
+    bool found = false;
+    palStatus_t result = PAL_SUCCESS;
+
+    PAL_VALIDATE_ARGUMENTS ((NULL == address) || (NULL == port));
+
+#if PAL_SUPPORT_IP_V4
+
+    if (address->addressType == PAL_AF_INET)
+    {
+        pal_socketAddressInternal_t* innerAddr = (pal_socketAddressInternal_t*)address;
+        // Set numeric formal
+        *port = PAL_NTOHS(innerAddr->pal_sin_port);
+        found = true;
+    }
+#endif
+#if PAL_SUPPORT_IP_V6
+    if (address->addressType == PAL_AF_INET6)
+    {
+        pal_socketAddressInternal6_t * innerAddr = (pal_socketAddressInternal6_t*)address;
+        // Set numeric formal
+        *port = PAL_NTOHS(innerAddr->pal_sin6_port);
+        found = true;
+    }
+#endif
+    if (false == found)
+    {
+        result =  PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY;
+    }
+
+    return result;
+}
+
+
+palStatus_t pal_socket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palSocket_t* socket)
+{
+    PAL_VALIDATE_ARGUMENTS (NULL == socket);
+
+    palStatus_t result = pal_plat_socket(domain, type, nonBlockingSocket, interfaceNum, socket);;
+
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+palStatus_t pal_setSocketOptions(palSocket_t socket, int optionName, const void* optionValue, palSocketLength_t optionLength)
+{
+    
+    PAL_VALIDATE_ARGUMENTS (NULL == optionValue);
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_setSocketOptions( socket,  optionName, optionValue,  optionLength);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+palStatus_t pal_isNonBlocking(palSocket_t socket, bool* isNonBlocking)
+{   
+    PAL_VALIDATE_ARGUMENTS (NULL == isNonBlocking);
+
+    palStatus_t result = pal_plat_isNonBlocking(socket, isNonBlocking);;
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+palStatus_t pal_bind(palSocket_t socket, palSocketAddress_t* myAddress, palSocketLength_t addressLength)
+{
+    
+    PAL_VALIDATE_ARGUMENTS(NULL == myAddress);
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_bind(socket, myAddress, addressLength);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+palStatus_t pal_receiveFrom(palSocket_t socket, void* buffer, size_t length, palSocketAddress_t* from, palSocketLength_t* fromLength, size_t* bytesReceived)
+{
+    
+    PAL_VALIDATE_ARGUMENTS((NULL == buffer) || (NULL == bytesReceived));
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_receiveFrom(socket,  buffer,  length,  from, fromLength, bytesReceived);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)    
+}
+
+
+palStatus_t pal_sendTo(palSocket_t socket, const void* buffer, size_t length, const palSocketAddress_t* to, palSocketLength_t toLength, size_t* bytesSent)
+{
+    
+    PAL_VALIDATE_ARGUMENTS((NULL == buffer) || (NULL == bytesSent) || (NULL == to));
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_sendTo(socket, buffer, length, to, toLength, bytesSent);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+palStatus_t pal_close(palSocket_t* socket)
+{
+    
+    PAL_VALIDATE_ARGUMENTS(NULL == socket);
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_close(socket);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+palStatus_t pal_getNumberOfNetInterfaces( uint32_t* numInterfaces)
+{
+    
+    PAL_VALIDATE_ARGUMENTS(NULL == numInterfaces);
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_getNumberOfNetInterfaces(numInterfaces);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+palStatus_t pal_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t * interfaceInfo)
+{
+    PAL_VALIDATE_ARGUMENTS(NULL == interfaceInfo)
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_getNetInterfaceInfo(interfaceNum, interfaceInfo);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+#if PAL_NET_TCP_AND_TLS_SUPPORT // functionality below supported only in case TCP is supported.
+
+palStatus_t pal_listen(palSocket_t socket, int backlog)
+{
+    palStatus_t result = pal_plat_listen(socket, backlog);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+palStatus_t pal_accept(palSocket_t socket, palSocketAddress_t* address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket)
+{
+    
+    PAL_VALIDATE_ARGUMENTS ((NULL == acceptedSocket) || (NULL == address)|| (NULL == addressLen));
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_accept(socket,  address, addressLen,  acceptedSocket);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+palStatus_t pal_connect(palSocket_t socket, const palSocketAddress_t* address, palSocketLength_t addressLen)
+{
+    PAL_VALIDATE_ARGUMENTS(NULL == address);
+
+    palStatus_t result = PAL_SUCCESS;
+    
+    result = pal_plat_connect( socket, address, addressLen);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+palStatus_t pal_recv(palSocket_t socket, void* buf, size_t len, size_t* recievedDataSize)
+{
+    PAL_VALIDATE_ARGUMENTS((NULL == recievedDataSize) ||  (NULL == buf));
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_recv(socket, buf, len, recievedDataSize);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+palStatus_t pal_send(palSocket_t socket, const void* buf, size_t len, size_t* sentDataSize)
+{
+    
+    PAL_VALIDATE_ARGUMENTS((NULL == buf) || (NULL == sentDataSize));
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_send( socket, buf, len, sentDataSize);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+
+palStatus_t pal_asynchronousSocket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, palSocket_t* socket)
+{    
+    PAL_VALIDATE_ARGUMENTS((NULL == socket) || (NULL == callback));
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_asynchronousSocket(domain,  type,  nonBlockingSocket,  interfaceNum,  callback, NULL, socket);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+palStatus_t pal_asynchronousSocketWithArgument(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void* callbackArgument, palSocket_t* socket)
+{
+    PAL_VALIDATE_ARGUMENTS((NULL == socket) || (NULL == callback));
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_asynchronousSocket(domain, type, nonBlockingSocket, interfaceNum, callback, callbackArgument, socket);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+#endif
+
+#if PAL_NET_DNS_SUPPORT
+
+palStatus_t pal_getAddressInfo(const char *url, palSocketAddress_t *address, palSocketLength_t* addressLength)
+{    
+    PAL_VALIDATE_ARGUMENTS ((NULL == url) || (NULL == address) || (NULL == addressLength));
+
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_plat_getAddressInfo(url, address, addressLength);
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+// the function invoked by the thread created in pal_getAddressInfoAsync
+#ifndef PAL_DNS_API_V2
+PAL_PRIVATE void getAddressInfoAsyncThreadFunc(void const* arg)
+{
+    pal_asyncAddressInfo_t* info = (pal_asyncAddressInfo_t*)arg;
+    palStatus_t status = pal_getAddressInfo(info->url, info->address, info->addressLength);
+    if (PAL_SUCCESS != status)
+    {
+        PAL_LOG(ERR, "getAddressInfoAsyncThreadFunc: pal_getAddressInfo failed\n");
+    }
+    info->callback(info->url, info->address, info->addressLength, status, info->callbackArgument); // invoke callback
+    free(info);
+}
+
+palStatus_t pal_getAddressInfoAsync(const char* url,
+                                    palSocketAddress_t* address,
+                                    palSocketLength_t* addressLength,
+                                    palGetAddressInfoAsyncCallback_t callback,
+                                    void* callbackArgument)
+{
+    PAL_VALIDATE_ARGUMENTS ((NULL == url) || (NULL == address) || (NULL == addressLength) || (NULL == callback))
+
+    palStatus_t status;
+    palThreadID_t threadID = NULLPTR;
+
+    pal_asyncAddressInfo_t* info = (pal_asyncAddressInfo_t*)malloc(sizeof(pal_asyncAddressInfo_t)); // thread function argument allocation
+    if (NULL == info) {
+        status = PAL_ERR_NO_MEMORY;
+    }
+    else {
+        info->url = (char*)url;
+        info->address = address;
+        info->addressLength = addressLength;
+        info->callback = callback;
+        info->callbackArgument = callbackArgument;
+
+        status = pal_osThreadCreateWithAlloc(getAddressInfoAsyncThreadFunc, info, PAL_osPriorityReservedDNS, PAL_NET_ASYNC_DNS_THREAD_STACK_SIZE, NULL, &threadID);
+        if (PAL_SUCCESS != status) {
+            free(info); // free memory allocation in case thread creation failed
+        }
+    }
+    return status;
+}
+#else
+#ifndef TARGET_LIKE_MBED
+#error "PAL_DNS_API_V2 is only supported with mbed-os"
+#endif
+palStatus_t pal_getAddressInfoAsync(const char* url, 
+                                     palSocketAddress_t* address, 
+                                     palGetAddressInfoAsyncCallback_t callback, 
+                                     void* callbackArgument, 
+                                     palDNSQuery_t* queryHandle)
+{
+    PAL_VALIDATE_ARGUMENTS ((NULL == url) || (NULL == address) || (NULL == callback))
+
+    palStatus_t status;
+
+    pal_asyncAddressInfo_t* info = (pal_asyncAddressInfo_t*)malloc(sizeof(pal_asyncAddressInfo_t));
+    if (NULL == info) {
+        status = PAL_ERR_NO_MEMORY;
+    }
+    else {
+        info->url = (char*)url;
+        info->address = address;
+        info->callback = callback;
+        info->callbackArgument = callbackArgument;
+        info->queryHandle = queryHandle; 
+        status = pal_plat_getAddressInfoAsync(info);
+        if (status != PAL_SUCCESS) {
+            free(info);
+        }
+    }
+    return status;
+}
+ 
+palStatus_t pal_cancelAddressInfoAsync(palDNSQuery_t queryHandle)
+{
+    return pal_plat_cancelAddressInfoAsync(queryHandle);
+}
+#endif //  #ifndef PAL_DNS_API_V2
+
+#endif // PAL_NET_DNS_SUPPORT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/RTOS/pal_rtos.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1123 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include <stdio.h>
+#include "pal.h"
+#include "pal_plat_rtos.h"
+#include "sotp.h"
+
+//! Store the last saved time in SOTP (ram) for quick access
+PAL_PRIVATE uint64_t g_lastSavedTimeInSec = 0;
+
+//! static variables for Random functionality.
+//! CTR-DRBG context to be used for generating random numbers from given seed
+static palCtrDrbgCtxHandle_t s_ctrDRBGCtx = NULLPTR;
+
+PAL_PRIVATE palStatus_t pal_setWeakTimeForward(uint64_t setNewTimeInSeconds, uint64_t currentOsTime);
+PAL_PRIVATE palStatus_t pal_setWeakTimeBackward(uint64_t setNewTimeInSeconds, uint64_t currentOsTime);
+
+static uint64_t g_palDeviceBootTimeInSec = 0;
+
+/*
+ * Here we define const keys for RoT derivation algorithm.
+ * Must be 16 characters or less
+ */
+#define PAL_STORAGE_SIGNATURE_128_BIT_KEY  "RoTStorageSgn128"
+#define PAL_STORAGE_ENCRYPTION_128_BIT_KEY "RoTStorageEnc128"
+#define PAL_STORAGE_ENCRYPTION_256_BIT_KEY "StorageEnc256HMACSHA256SIGNATURE"
+
+PAL_PRIVATE bool palRTOSInitialized = false;
+
+#if (PAL_SIMULATE_RTOS_REBOOT == 1)
+    #include <unistd.h>
+    extern char *program_invocation_name;
+#endif
+
+#define PAL_NOISE_WAIT_FOR_WRITERS_DELAY_MILLI_SEC 1
+#define PAL_NOISE_BITS_TO_BYTES(x) (x / CHAR_BIT)
+
+typedef struct palNoise
+{
+    int32_t buffer[PAL_NOISE_BUFFER_LEN];
+    volatile uint32_t bitCountAllocated;
+    volatile uint32_t bitCountActual;
+    volatile uint32_t numWriters;
+    volatile bool isReading;
+} palNoise_t;
+
+PAL_PRIVATE palNoise_t g_noise;
+
+palStatus_t pal_noiseWriteBuffer(int32_t* buffer, uint16_t lenBits, uint16_t* bitsWritten); // forward declaration
+palStatus_t pal_noiseRead(int32_t buffer[PAL_NOISE_BUFFER_LEN], bool partial, uint16_t* bitsRead); // forward declaration
+
+#if PAL_USE_HW_TRNG
+    PAL_PRIVATE palThreadID_t g_trngThreadID = NULLPTR;
+#endif
+
+extern palStatus_t pal_plat_CtrDRBGGenerateWithAdditional(palCtrDrbgCtxHandle_t ctx, unsigned char* out, size_t len, unsigned char* additional, size_t additionalLen);
+
+//Error Translation from SOTP module to PAL
+PAL_PRIVATE palStatus_t pal_osSotpErrorTranslation(sotp_result_e err)
+{
+    palStatus_t ret;
+    switch(err)
+    {
+        case SOTP_BAD_VALUE:
+            ret = PAL_ERR_INVALID_ARGUMENT;
+            break;
+
+        case SOTP_BUFF_TOO_SMALL:
+            ret = PAL_ERR_BUFFER_TOO_SMALL;
+            break;
+
+        case SOTP_BUFF_NOT_ALIGNED:
+            ret = PAL_ERR_RTOS_BUFFER_NOT_ALIGNED;
+            break;
+
+        case SOTP_READ_ERROR:
+        case SOTP_DATA_CORRUPT:
+        case SOTP_OS_ERROR:
+        default:
+            ret = PAL_ERR_GENERIC_FAILURE;
+            break;
+    }
+    return ret;
+}
+
+palStatus_t pal_RTOSInitialize(void* opaqueContext)
+{
+    palStatus_t status = PAL_SUCCESS;
+    if (palRTOSInitialized)
+    {
+        return status;
+    }
+
+    status = pal_plat_RTOSInitialize(opaqueContext);
+    if (PAL_SUCCESS == status)
+    {
+        memset(g_noise.buffer, 0, PAL_NOISE_SIZE_BYTES);
+        g_noise.bitCountActual = g_noise.bitCountAllocated = 0;
+        g_noise.numWriters = 0;
+        g_noise.isReading = false;
+#if PAL_USE_HW_TRNG
+        g_trngThreadID = NULLPTR;
+#endif
+        palRTOSInitialized = true;
+    }
+    else
+    {
+        PAL_LOG(ERR, "pal_RTOSInitialize: pal_plat_RTOSInitialize failed, status=%" PRIx32 "\n", status);
+    }
+    return status;
+}
+
+palStatus_t pal_RTOSDestroy(void)
+{
+    palStatus_t status = PAL_ERR_NOT_INITIALIZED;
+    if (!palRTOSInitialized)
+    {
+        return status;
+    }
+
+#if PAL_USE_HW_TRNG
+    if (NULLPTR != g_trngThreadID)
+    {
+        if (PAL_SUCCESS != pal_osThreadTerminate(&g_trngThreadID))
+        {
+            PAL_LOG(ERR, "pal_RTOSDestroy: failed to terminate trng noise thread\n");
+        }
+    }
+#endif
+
+    if (NULLPTR != s_ctrDRBGCtx)
+    {
+        status = pal_CtrDRBGFree(&s_ctrDRBGCtx);
+        if (PAL_SUCCESS != status)
+        {
+            PAL_LOG(ERR, "pal_RTOSDestroy: pal_CtrDRBGFree failed, status=%" PRIx32 "\n", status);
+        }
+    }
+
+    status = pal_plat_RTOSDestroy();
+    if (PAL_SUCCESS != status)
+    {
+        PAL_LOG(ERR, "pal_RTOSDestroy: pal_plat_RTOSDestroy failed, status=%" PRIx32 "\n", status);
+    }
+    palRTOSInitialized = false;
+    return status;
+}
+
+void pal_osReboot(void)
+{
+    PAL_LOG(INFO, "pal_osReboot\r\n");
+#if (PAL_USE_APPLICATION_REBOOT)
+    pal_plat_osApplicationReboot();
+#else
+    //Simulator is currently for Linux only
+    #if (PAL_SIMULATE_RTOS_REBOOT == 1)
+        const char *argv[] = {"0" , 0};
+        char *const envp[] = { 0 };
+        argv[0] = program_invocation_name;
+
+        PAL_LOG(INFO, "pal_osReboot -> simulated reboot with execve(%s).\r\n", argv[0]);
+  
+        if (-1 == execve(argv[0], (char **)argv , envp))
+        {
+            PAL_LOG(ERR,"child process execve failed [%s]",argv[0]);
+        }
+    #else
+        PAL_LOG(INFO, "Rebooting the system\r\n");
+        pal_plat_osReboot();
+    #endif
+#endif
+}
+
+uint64_t pal_osKernelSysTick(void)
+{
+    static uint64_t lastValue = 0;
+    static uint64_t wraparoundsDetected = 0;
+    const uint64_t one = 1;
+    uint64_t tics = pal_plat_osKernelSysTick();
+    uint64_t tmp = tics + (wraparoundsDetected << 32);
+
+    if (tmp < lastValue) //erez's "wraparound algorithm" if we detect a wrap around add 1 to the higher 32 bits
+    {
+        tmp = tmp + (one << 32);
+        wraparoundsDetected++;
+    }
+    lastValue = tmp;
+    return (uint64_t)tmp;
+}
+
+uint64_t pal_osKernelSysTickMicroSec(uint64_t microseconds)
+{
+    uint64_t result;
+    result = pal_plat_osKernelSysTickMicroSec(microseconds);
+    return result;
+}
+
+uint64_t pal_osKernelSysMilliSecTick(uint64_t sysTicks)
+{
+    uint64_t result = 0;
+    uint64_t osTickFreq = pal_plat_osKernelSysTickFrequency();
+    if ((sysTicks) && (osTickFreq)) // > 0
+    {
+        result = (uint64_t)((sysTicks) * PAL_TICK_TO_MILLI_FACTOR / osTickFreq); //convert ticks per second to milliseconds
+    }
+
+    return result;
+}
+
+uint64_t pal_osKernelSysTickFrequency(void)
+{
+    uint64_t result;
+    result = pal_plat_osKernelSysTickFrequency();
+    return result;
+}
+
+palStatus_t pal_osThreadCreateWithAlloc(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, palThreadLocalStore_t* store, palThreadID_t* threadID)
+{
+    PAL_VALIDATE_ARGUMENTS((NULL == function) || (PAL_osPrioritylast < priority) || (PAL_osPriorityError == priority) || (0 == stackSize) || (NULL == threadID));
+    if (store)
+    {
+        PAL_LOG(ERR, "thread storage in not supported\n");
+        return PAL_ERR_NOT_SUPPORTED;
+    }
+    palStatus_t status = pal_plat_osThreadCreate(function, funcArgument, priority, stackSize, threadID);
+    return status;
+}
+
+palStatus_t pal_osThreadTerminate(palThreadID_t* threadID)
+{
+    PAL_VALIDATE_ARGUMENTS ((NULL == threadID) || (PAL_INVALID_THREAD == *threadID));
+    palStatus_t status = pal_plat_osThreadTerminate(threadID);
+    return status;
+}
+
+palThreadID_t pal_osThreadGetId(void)
+{
+    palThreadID_t threadID = pal_plat_osThreadGetId();
+    return threadID;
+}
+
+palStatus_t pal_osDelay(uint32_t milliseconds)
+{
+    palStatus_t status;
+    status = pal_plat_osDelay(milliseconds);
+    return status;
+}
+
+palStatus_t pal_osTimerCreate(palTimerFuncPtr function, void* funcArgument, palTimerType_t timerType, palTimerID_t* timerID)
+{
+    PAL_VALIDATE_ARGUMENTS(NULL == timerID || NULL == function);
+    palStatus_t status;
+    status = pal_plat_osTimerCreate(function, funcArgument, timerType, timerID);
+    return status;
+}
+
+palStatus_t pal_osTimerStart(palTimerID_t timerID, uint32_t millisec)
+{
+    PAL_VALIDATE_ARGUMENTS (NULLPTR == timerID);
+    palStatus_t status;
+    if (0 == millisec)
+    {
+        return PAL_ERR_RTOS_VALUE;
+    }
+    status = pal_plat_osTimerStart(timerID, millisec);
+    return status;
+}
+
+palStatus_t pal_osTimerStop(palTimerID_t timerID)
+{
+    PAL_VALIDATE_ARGUMENTS(NULLPTR == timerID);
+    palStatus_t status;
+    status = pal_plat_osTimerStop(timerID);
+    return status;
+}
+
+palStatus_t pal_osTimerDelete(palTimerID_t* timerID)
+{
+    PAL_VALIDATE_ARGUMENTS(NULL == timerID || NULLPTR == *timerID);
+    palStatus_t status;
+    status = pal_plat_osTimerDelete(timerID);
+    return status;
+}
+
+palStatus_t pal_osMutexCreate(palMutexID_t* mutexID)
+{
+    PAL_VALIDATE_ARGUMENTS(NULL == mutexID);
+    palStatus_t status;
+    status = pal_plat_osMutexCreate(mutexID);
+    return status;
+}
+
+palStatus_t pal_osMutexWait(palMutexID_t mutexID, uint32_t millisec)
+{
+    PAL_VALIDATE_ARGUMENTS((NULLPTR == mutexID));
+    palStatus_t status;
+    status = pal_plat_osMutexWait(mutexID, millisec);
+    return status;
+}
+
+palStatus_t pal_osMutexRelease(palMutexID_t mutexID)
+{
+    PAL_VALIDATE_ARGUMENTS(NULLPTR == mutexID);
+    palStatus_t status;
+    status = pal_plat_osMutexRelease(mutexID);
+    return status;
+}
+
+palStatus_t pal_osMutexDelete(palMutexID_t* mutexID)
+{
+    PAL_VALIDATE_ARGUMENTS(NULL == mutexID || NULLPTR == *mutexID);
+    palStatus_t status;
+    status = pal_plat_osMutexDelete(mutexID);
+    return status;
+}
+
+palStatus_t pal_osSemaphoreCreate(uint32_t count, palSemaphoreID_t* semaphoreID)
+{
+    PAL_VALIDATE_ARGUMENTS(NULL == semaphoreID);
+    palStatus_t status;
+    status = pal_plat_osSemaphoreCreate(count, semaphoreID);
+    return status;
+}
+
+palStatus_t pal_osSemaphoreWait(palSemaphoreID_t semaphoreID, uint32_t millisec,  int32_t* countersAvailable)
+{
+    PAL_VALIDATE_ARGUMENTS(NULLPTR == semaphoreID);
+    palStatus_t status;
+    status = pal_plat_osSemaphoreWait(semaphoreID, millisec, countersAvailable);
+    return status;
+}
+
+palStatus_t pal_osSemaphoreRelease(palSemaphoreID_t semaphoreID)
+{
+    PAL_VALIDATE_ARGUMENTS(NULLPTR == semaphoreID);
+    palStatus_t status;
+    status = pal_plat_osSemaphoreRelease(semaphoreID);
+    return status;
+}
+
+palStatus_t pal_osSemaphoreDelete(palSemaphoreID_t* semaphoreID)
+{
+    PAL_VALIDATE_ARGUMENTS(NULL == semaphoreID || NULLPTR == *semaphoreID);
+    palStatus_t status;
+    status = pal_plat_osSemaphoreDelete(semaphoreID);
+    return status;
+}
+
+
+int32_t pal_osAtomicIncrement(int32_t* valuePtr, int32_t increment)
+{
+    PAL_VALIDATE_ARGUMENTS(NULL == valuePtr);
+    int32_t result;
+    result = pal_plat_osAtomicIncrement(valuePtr, increment);
+    return result;
+}
+
+
+PAL_PRIVATE uint64_t pal_sysTickTimeToSec()
+{
+	uint64_t sysTicksFromBoot = pal_osKernelSysTick();
+	uint64_t secFromBoot = pal_osKernelSysMilliSecTick(sysTicksFromBoot) / PAL_MILLI_PER_SECOND;
+
+	return secFromBoot;
+}
+
+uint64_t pal_osGetTime(void)
+{
+    uint64_t curSysTimeInSec = 0;
+	if (0 < g_palDeviceBootTimeInSec) //time was previously set
+	{
+		uint64_t secFromBoot = pal_sysTickTimeToSec();
+		curSysTimeInSec = g_palDeviceBootTimeInSec + secFromBoot; //boot time in sec + sec passed since boot
+
+		if((curSysTimeInSec > g_lastSavedTimeInSec) && (curSysTimeInSec - g_lastSavedTimeInSec > PAL_LAST_SAVED_TIME_LATENCY_SEC))
+		{
+            sotp_result_e status = SOTP_SUCCESS;
+            status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&curSysTimeInSec);
+            if (SOTP_SUCCESS != status)
+            {
+                PAL_LOG(ERR,"SOTP set time failed \n");  
+            }
+            else
+            {
+                g_lastSavedTimeInSec = curSysTimeInSec;
+            }
+                     
+		}
+	}
+
+	return curSysTimeInSec;
+}
+
+palStatus_t pal_osSetTime(uint64_t seconds)
+{
+	palStatus_t status = PAL_SUCCESS;
+	if(0 == seconds)
+	{
+	    g_palDeviceBootTimeInSec = 0;
+	}
+	else if (seconds < (uint64_t)PAL_MIN_SEC_FROM_EPOCH)
+	{
+		status = PAL_ERR_INVALID_TIME;
+	}
+	else
+	{
+		uint64_t secFromBoot = pal_sysTickTimeToSec();
+		g_palDeviceBootTimeInSec = seconds - secFromBoot; //update device boot time
+	}
+
+	return status;
+}
+
+
+
+#if PAL_USE_HW_TRNG
+PAL_PRIVATE void pal_trngNoiseThreadFunc(void const* arg)
+{
+    uint8_t buf[PAL_NOISE_SIZE_BYTES] PAL_PTR_ADDR_ALIGN_UINT8_TO_UINT32 = { 0 };
+    size_t trngBytesRead = 0;
+    uint16_t noiseBitsWritten = 0;
+    palStatus_t status;
+    while (true)
+    {
+        status = pal_plat_osRandomBuffer(buf, PAL_NOISE_SIZE_BYTES, &trngBytesRead);
+        if ((0 < trngBytesRead) && ((PAL_SUCCESS == status) || (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status)))
+        {
+            noiseBitsWritten = 0;
+            status = pal_noiseWriteBuffer((int32_t*)buf, (trngBytesRead * CHAR_BIT), &noiseBitsWritten);            
+        }
+        pal_osDelay(PAL_NOISE_TRNG_THREAD_DELAY_MILLI_SEC);
+    }
+}
+#endif // PAL_USE_HW_TRNG
+
+
+// this function generates drbg with the possibility of adding noise as additional input to the drbg function.
+PAL_PRIVATE palStatus_t pal_generateDrbgWithNoiseAttempt(palCtrDrbgCtxHandle_t drbgContext, uint8_t* outBuffer, bool partial, size_t numBytesToGenerate)
+{
+    uint16_t bitsRead = 0;
+    int32_t buffer[PAL_NOISE_BUFFER_LEN] = { 0 };
+    palStatus_t status = pal_noiseRead(buffer, partial, &bitsRead);
+    if (PAL_SUCCESS == status)
+    {
+        status = pal_plat_CtrDRBGGenerateWithAdditional(drbgContext, (unsigned char*)outBuffer, numBytesToGenerate, (unsigned char*)buffer, (size_t)PAL_NOISE_BITS_TO_BYTES(bitsRead));
+    }
+    else
+    {
+        status = pal_CtrDRBGGenerate(drbgContext, (unsigned char*)outBuffer, numBytesToGenerate);
+    }
+    return status;
+}
+
+palStatus_t pal_osRandomBuffer(uint8_t *randomBuf, size_t bufSizeBytes)
+{
+    PAL_VALIDATE_ARGUMENTS (NULL == randomBuf);
+
+    palStatus_t status = PAL_ERR_GENERIC_FAILURE;
+    if (palRTOSInitialized == true)
+    {
+        if (NULLPTR == s_ctrDRBGCtx)
+        {
+            uint32_t sotpCounter = 0;
+            uint8_t buf[(PAL_INITIAL_RANDOM_SIZE * 2 + sizeof(sotpCounter))] PAL_PTR_ADDR_ALIGN_UINT8_TO_UINT32 = { 0 }; // space for 48 bytes short term + 48 bytes long term + 4 counter bytes (note this buffer will also be used to collect TRNG noise)
+            const uint16_t sotpLenBytes = PAL_INITIAL_RANDOM_SIZE + sizeof(sotpCounter); // the max number of bytes expected to be read/written form/to sotp, note that sotpCounter will probably be empty the 1st time data is read from sotp
+            uint32_t* ptrSotpRead = (uint32_t*)&buf; // pointer to the memory address in buf which will point to the data that will be read from sotp
+            uint32_t* ptrSotpWrite = (uint32_t*)&buf[PAL_INITIAL_RANDOM_SIZE]; // pointer to the memory address in buf which will point to the data which needs to be written back to sotp
+            uint32_t* ptrSotpCounterRead = ptrSotpWrite; // pointer to the memory address in buf which will point to the counter read from sotp
+            uint32_t* ptrSotpCounterWrite = (uint32_t*)&buf[PAL_INITIAL_RANDOM_SIZE * 2]; // pointer to the memory address in buf which will point to the incremented counter which will be written back to sotp
+            uint16_t sotpBytesRead = 0, noiseBitsWrittern = 0;
+            size_t trngBytesRead = 0;
+            palCtrDrbgCtxHandle_t longCtrDRBGCtx = NULLPTR; // long term drbg context            
+            palStatus_t tmpStatus;
+            sotp_result_e sotpResult = sotp_get(SOTP_TYPE_RANDOM_SEED, sotpLenBytes, ptrSotpRead, &sotpBytesRead); // read 48 drbg bytes + 4 counter bytes
+            if (SOTP_SUCCESS == sotpResult)
+            {
+                if ((PAL_INITIAL_RANDOM_SIZE != sotpBytesRead) && (sotpLenBytes != sotpBytesRead))
+                {
+                    status = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT;
+                    PAL_LOG(ERR, "Invalid number of bytes read from sotp, bytes read=%" PRIu16, sotpBytesRead);
+                    goto finish;
+                }
+                status = pal_CtrDRBGInit(&longCtrDRBGCtx, ptrSotpRead, PAL_INITIAL_RANDOM_SIZE); // initialize long term drbg with the seed that was read from sotp
+                if (PAL_SUCCESS != status)
+                {
+                    PAL_LOG(ERR, "Failed to initialize long term drbg context, status=%" PRIx32 "\n", status);
+                    goto finish;
+                }
+                memcpy((void*)&sotpCounter, (void*)ptrSotpCounterRead, sizeof(sotpCounter)); // read the counter from the buffer (sotp data) to local var
+#if PAL_USE_HW_TRNG
+                memset((void*)buf, 0, sizeof(buf));                
+                status = pal_plat_osRandomBuffer(buf, PAL_NOISE_SIZE_BYTES, &trngBytesRead);
+                if ((PAL_SUCCESS == status) || (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status))
+                {
+                    if (0 < trngBytesRead)
+                    {
+                        tmpStatus = pal_noiseWriteBuffer((int32_t*)buf, (trngBytesRead * CHAR_BIT), &noiseBitsWrittern); // write whatever was collected from trng to the noise buffer
+                        PAL_LOG(DBG, "Write trng to noise buffer, status=%" PRIx32 ", bits writtern=%" PRIu16 "\n", tmpStatus, noiseBitsWrittern);
+                    }
+                }
+                else
+                {
+                    PAL_LOG(ERR, "Read from TRNG failed, status=%" PRIx32 "\n", status);
+                }                
+#endif // PAL_USE_HW_TRNG
+                memset((void*)buf, 0, sizeof(buf));
+                status = pal_generateDrbgWithNoiseAttempt(longCtrDRBGCtx, buf, true, (PAL_INITIAL_RANDOM_SIZE * 2)); // generate 96 bytes, the 1st 48 bytes will be used for short term drbg and the other 48 bytes will be used for long term drbg
+                if (PAL_SUCCESS != status)
+                {
+                    PAL_LOG(ERR, "Failed to gererate drbg long term and short term seeds, status=%" PRIx32 "\n", status);
+                    goto drbg_cleanup;
+                }
+                sotpCounter++; // increment counter before writting it back to sotp
+                memcpy((void*)ptrSotpCounterWrite, (void*)&sotpCounter, sizeof(sotpCounter)); // copy the incremented counter to the last 4 bytes of the buffer
+                sotpResult = sotp_set(SOTP_TYPE_RANDOM_SEED, sotpLenBytes, ptrSotpWrite); // write 48 long term drbg bytes + 4 counter bytes
+                if (SOTP_SUCCESS != sotpResult)
+                {
+                    PAL_LOG(ERR, "Failed to write to sotp, sotp result=%d", sotpResult);
+                    status = PAL_ERR_GENERIC_FAILURE;
+                }                
+drbg_cleanup:
+                {
+                    tmpStatus = pal_CtrDRBGFree(&longCtrDRBGCtx);
+                    if (PAL_SUCCESS != tmpStatus)
+                    {
+                        PAL_LOG(ERR, "Failed to free long term drbg context, status=%" PRIx32 "\n", tmpStatus);
+                    }
+                    longCtrDRBGCtx = NULLPTR;                    
+                    if (PAL_SUCCESS != status)
+                    {
+                        goto finish;
+                    }
+#if PAL_USE_HW_TRNG
+                    status = pal_osThreadCreateWithAlloc(pal_trngNoiseThreadFunc, NULL, PAL_osPriorityReservedTRNG, PAL_NOISE_TRNG_THREAD_STACK_SIZE, NULL, &g_trngThreadID);
+                    if (PAL_SUCCESS != status)
+                    {
+                        PAL_LOG(ERR, "Failed to create noise trng thread, status=%" PRIx32 "\n", tmpStatus);
+                    }
+#endif // PAL_USE_HW_TRNG
+                }
+            }
+            else if (SOTP_NOT_FOUND == sotpResult)
+            {
+#if PAL_USE_HW_TRNG
+                memset((void*)buf, 0, sizeof(buf));
+                uint8_t* seedPtr = buf;
+                size_t randomCounterBytes = 0;
+                do
+                {
+                    status = pal_plat_osRandomBuffer(seedPtr, PAL_INITIAL_RANDOM_SIZE - randomCounterBytes, &trngBytesRead);
+                    if (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status)
+                    {
+                        pal_osDelay(PAL_TRNG_COLLECT_DELAY_MILLI_SEC); // sleep to let the device to collect random data.
+                        randomCounterBytes += trngBytesRead;
+                        seedPtr += trngBytesRead;
+                    }
+                } while (PAL_ERR_RTOS_TRNG_PARTIAL_DATA == status);
+#endif // PAL_USE_HW_TRNG
+            }
+            if (PAL_SUCCESS != status)
+            {
+                goto finish;
+            }
+            status = pal_CtrDRBGInit(&s_ctrDRBGCtx, (void*)buf, PAL_INITIAL_RANDOM_SIZE);
+            if (PAL_SUCCESS != status)
+            {
+                PAL_LOG(ERR, "Failed to initialize short term drbg context, status=%" PRIx32 "\n", status);
+                goto finish;
+            }
+        }
+        status = pal_generateDrbgWithNoiseAttempt(s_ctrDRBGCtx, randomBuf, false, bufSizeBytes);
+        if (PAL_SUCCESS != status)
+        {
+            PAL_LOG(ERR, "Failed to gererate random, status=%" PRIx32 "\n", status);
+        }
+    }
+    else
+    {
+        return PAL_ERR_NOT_INITIALIZED;
+    }
+finish:
+    return status;
+}
+
+palStatus_t pal_osRandom32bit(uint32_t *random)
+{
+    palStatus_t status = PAL_SUCCESS;
+
+    PAL_VALIDATE_ARGUMENTS(NULL == random);
+        
+    status = pal_osRandomBuffer((uint8_t*)random, sizeof(uint32_t));
+    return status;
+}
+
+
+PAL_PRIVATE palStatus_t pal_osGetRoT(uint8_t * key,size_t keyLenBytes)
+{
+    palStatus_t palStatus = PAL_SUCCESS;
+#if (PAL_USE_HW_ROT)
+    palStatus = pal_plat_osGetRoTFromHW(key, keyLenBytes);
+#else
+    sotp_result_e sotpStatus = SOTP_SUCCESS;
+    uint16_t actual_size;
+    sotpStatus = sotp_get(SOTP_TYPE_ROT, keyLenBytes, (uint32_t *)key, &actual_size);
+    if (SOTP_NOT_FOUND == sotpStatus) 
+    {
+        palStatus = pal_osRandomBuffer(key , keyLenBytes);
+        if (PAL_SUCCESS == palStatus) 
+        {
+            sotpStatus = sotp_set(SOTP_TYPE_ROT,keyLenBytes, (uint32_t *)key);
+        }
+    }
+    if (SOTP_SUCCESS != sotpStatus)
+    {
+        palStatus = pal_osSotpErrorTranslation(sotpStatus);
+    }
+#endif
+    return palStatus;
+}
+
+palStatus_t pal_osGetDeviceKey(palDevKeyType_t keyType, uint8_t *key, size_t keyLenBytes)
+{
+	palStatus_t status = PAL_SUCCESS;
+    uint8_t rotBuffer[PAL_DEVICE_KEY_SIZE_IN_BYTES] __attribute__ ((aligned(4))) = {0};
+
+    
+	PAL_VALIDATE_CONDITION_WITH_ERROR(((keyLenBytes < PAL_DEVICE_KEY_SIZE_IN_BYTES) || ((palOsStorageHmacSha256 == keyType) && (keyLenBytes < PAL_SHA256_DEVICE_KEY_SIZE_IN_BYTES))),PAL_ERR_BUFFER_TOO_SMALL)
+
+	PAL_VALIDATE_CONDITION_WITH_ERROR ((NULL == key),PAL_ERR_NULL_POINTER)
+
+    status = pal_osGetRoT(rotBuffer, keyLenBytes);
+	if (PAL_SUCCESS == status)
+	{   // Logic of RoT according to key type using 128 bit strong Key Derivation Algorithm
+
+#if (PAL_DEVICE_KEY_DERIVATION_BACKWARD_COMPATIBILITY_CALC == 1) //calculate the key derivation in an old way
+        switch(keyType)
+        {
+            case palOsStorageEncryptionKey128Bit:
+            {
+                //USE strong KDF here!
+                status = pal_cipherCMAC((const unsigned char*)PAL_STORAGE_ENCRYPTION_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BYTES, key);
+                break;
+            }
+            case palOsStorageSignatureKey128Bit:
+            {
+                //USE strong KDF here!
+                status = pal_cipherCMAC((const unsigned char *)PAL_STORAGE_SIGNATURE_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BYTES, key);
+                break;
+            }
+            case palOsStorageHmacSha256:
+            {
+                size_t outputLenInBytes = 0;
+                status = pal_mdHmacSha256((const unsigned char *)PAL_STORAGE_ENCRYPTION_256_BIT_KEY, PAL_SHA256_DEVICE_KEY_SIZE_IN_BYTES, (const unsigned char*)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BYTES, key, &outputLenInBytes);
+                break;
+            }
+            default:
+                status = PAL_ERR_GET_DEV_KEY;
+        } //switch end
+#else //calculate the key derivation in a new way
+        switch(keyType)
+        {
+            case palOsStorageEncryptionKey128Bit:
+            {
+                //USE strong KDF here!
+                status = pal_cipherCMAC((const unsigned char*)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)PAL_STORAGE_ENCRYPTION_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BYTES, key);
+                break;
+            }
+            case palOsStorageSignatureKey128Bit:
+            {
+                //USE strong KDF here!
+                status = pal_cipherCMAC((const unsigned char*)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BITS, (const unsigned char *)PAL_STORAGE_SIGNATURE_128_BIT_KEY, PAL_DEVICE_KEY_SIZE_IN_BYTES, key);                
+                break;
+            }
+            case palOsStorageHmacSha256:
+            {
+                size_t outputLenInBytes = 0;
+                status = pal_mdHmacSha256((const unsigned char*)rotBuffer, PAL_DEVICE_KEY_SIZE_IN_BYTES, (const unsigned char *)PAL_STORAGE_ENCRYPTION_256_BIT_KEY, PAL_SHA256_DEVICE_KEY_SIZE_IN_BYTES, key, &outputLenInBytes);                
+                break;
+            }
+            default:
+                status = PAL_ERR_GET_DEV_KEY;
+        } //switch end
+#endif        
+
+	} // outer if
+    else
+    {
+        status = PAL_ERR_GET_DEV_KEY;
+    }
+
+	return status;
+
+}
+
+palStatus_t pal_initTime(void)
+{
+    uint64_t rtcTime = 0;
+    uint64_t sotpGetTime = 0, sotpLastTimeBack = 0;
+    palStatus_t ret = PAL_SUCCESS;
+    sotp_result_e status = SOTP_SUCCESS;
+    uint16_t actualLenBytes = 0;
+
+    status = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status))
+    {
+        ret = pal_osSotpErrorTranslation(status);
+    }
+    else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status))
+    {
+        ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT;
+    }
+
+    status = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t*)&sotpLastTimeBack, &actualLenBytes);
+    if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status))
+    {
+        ret = pal_osSotpErrorTranslation(status);
+    }
+    else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status))
+    {
+        ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT;
+    }
+
+    if (sotpLastTimeBack > sotpGetTime)
+    {//Enter here only when reset occurs during set weak or strong time
+        status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&sotpLastTimeBack);
+        if (SOTP_SUCCESS != status)
+        {
+            ret = pal_osSotpErrorTranslation(status);
+        }
+        sotpGetTime = sotpLastTimeBack;
+    }
+    g_lastSavedTimeInSec = sotpGetTime;
+
+#if (PAL_USE_HW_RTC)
+    if (PAL_SUCCESS == ret)
+    {
+        ret = pal_plat_osGetRtcTime(&rtcTime);
+    }
+#endif
+
+    if (PAL_SUCCESS == ret)
+    {//set the max time as boot time of the device
+       pal_osSetTime(PAL_MAX(rtcTime, sotpGetTime));
+    }
+    return ret;
+}
+
+
+palStatus_t pal_osSetStrongTime(uint64_t setNewTimeInSeconds)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    uint64_t getSotpTimeValue = 0;
+    uint16_t actualLenBytes = 0;
+    sotp_result_e status = SOTP_SUCCESS;
+    
+#if (PAL_USE_HW_RTC)
+    //RTC Time Latency
+    if (PAL_SUCCESS == ret)
+    {
+        uint64_t getRtcTimeValue = 0;
+        ret = pal_plat_osGetRtcTime(&getRtcTimeValue);
+        if (PAL_SUCCESS == ret)
+        {
+            if(llabs(setNewTimeInSeconds - getRtcTimeValue) > PAL_MINIMUM_RTC_LATENCY_SEC)
+            {
+                ret = pal_plat_osSetRtcTime(setNewTimeInSeconds);
+            }
+        }
+    }
+#endif
+
+    status = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&getSotpTimeValue, &actualLenBytes);
+    if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status))
+    {
+        ret = pal_osSotpErrorTranslation(status);
+    }
+    else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status))
+    {
+        ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT;
+    }    
+    else if (((setNewTimeInSeconds > getSotpTimeValue) && (setNewTimeInSeconds - getSotpTimeValue > PAL_MINIMUM_SOTP_FORWARD_LATENCY_SEC)) //Forward Time
+            || ((setNewTimeInSeconds < getSotpTimeValue) && (getSotpTimeValue - setNewTimeInSeconds > PAL_MINIMUM_SOTP_BACKWARD_LATENCY_SEC))) //Backward Time
+    {
+        status = sotp_set(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds);
+        if (SOTP_SUCCESS != status)
+        {
+            ret = pal_osSotpErrorTranslation(status);
+        }
+        else
+        {            
+            status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds);
+            if (SOTP_SUCCESS != status)
+            {
+                ret = pal_osSotpErrorTranslation(status);
+            }
+            g_lastSavedTimeInSec = setNewTimeInSeconds;
+        }
+    }
+
+    if(PAL_SUCCESS == ret)
+    {
+       ret = pal_osSetTime(setNewTimeInSeconds); //Save new time to RAM
+    }
+
+    return ret;
+}
+
+PAL_PRIVATE palStatus_t pal_setWeakTimeForward(uint64_t setNewTimeInSeconds, uint64_t currentOsTime)
+{
+    sotp_result_e status = SOTP_SUCCESS;
+    palStatus_t ret = PAL_SUCCESS;
+
+    ret = pal_osSetTime(setNewTimeInSeconds); //Save new time to RAM
+#if (PAL_USE_HW_RTC)
+    //RTC Time Forward
+    if (PAL_SUCCESS == ret)
+    {
+        uint64_t getRtcTimeValue = 0;
+        ret = pal_plat_osGetRtcTime(&getRtcTimeValue);
+        if (PAL_SUCCESS == ret)
+        {
+            if((setNewTimeInSeconds > getRtcTimeValue) && (setNewTimeInSeconds - getRtcTimeValue > PAL_MINIMUM_RTC_LATENCY_SEC))
+            {
+                ret = pal_plat_osSetRtcTime(setNewTimeInSeconds);
+            }
+        }
+    }
+#endif// (PAL_USE_HW_RTC)
+
+    if ((setNewTimeInSeconds - currentOsTime > PAL_MINIMUM_SOTP_FORWARD_LATENCY_SEC) && (PAL_SUCCESS == ret))
+    {//SOTP time forward
+        status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds);
+        if (SOTP_SUCCESS != status)
+        {
+            ret = pal_osSotpErrorTranslation(status);
+        }
+        else
+        {
+            g_lastSavedTimeInSec = setNewTimeInSeconds;
+        }
+    }
+    return ret;
+}
+
+PAL_PRIVATE palStatus_t pal_setWeakTimeBackward(uint64_t setNewTimeInSeconds, uint64_t currentOsTime)
+{
+    uint64_t getSotpTimeValue = 0;
+    uint16_t actualLenBytes = 0;
+    sotp_result_e status = SOTP_SUCCESS;
+    palStatus_t ret = PAL_SUCCESS;
+
+    status = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&getSotpTimeValue, &actualLenBytes);
+    if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status))
+    {
+        ret = pal_osSotpErrorTranslation(status);
+    }
+    else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status))
+    {
+        ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT;
+    }
+    else if (setNewTimeInSeconds > getSotpTimeValue)
+    {
+        if ((setNewTimeInSeconds - getSotpTimeValue) / PAL_RATIO_SECONDS_PER_DAY  > (currentOsTime - setNewTimeInSeconds))
+        {
+            status = sotp_set(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds);
+            if (SOTP_SUCCESS != status)
+            {
+                ret = pal_osSotpErrorTranslation(status);
+            }
+            else
+            {               
+                status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds);
+                if (SOTP_SUCCESS != status)
+                {
+                    ret = pal_osSotpErrorTranslation(status);
+                }
+                else
+                {
+                    g_lastSavedTimeInSec = setNewTimeInSeconds;
+                    ret = pal_osSetTime(setNewTimeInSeconds); //Save new time to RAM
+                }
+            }
+        }
+    }
+
+    return ret;
+}
+
+palStatus_t pal_osSetWeakTime(uint64_t setNewTimeInSeconds)
+{
+    uint64_t getSotpTimeValue = 0;
+    uint16_t actualLenBytes = 0;
+    sotp_result_e status = SOTP_SUCCESS;
+    palStatus_t ret = PAL_SUCCESS;
+    uint64_t getOsTimeValue = 0;
+    
+    getOsTimeValue = pal_osGetTime(); //get current system time
+
+    if (setNewTimeInSeconds > getOsTimeValue)
+    {//Time Forward
+        ret = pal_setWeakTimeForward(setNewTimeInSeconds, getOsTimeValue);
+    }
+    else if (getOsTimeValue > setNewTimeInSeconds)
+    {//Time Backward
+        ret = pal_setWeakTimeBackward(setNewTimeInSeconds, getOsTimeValue);
+    }
+
+    if(PAL_SUCCESS == ret)
+    {
+        getSotpTimeValue = 0;
+        status = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&getSotpTimeValue, &actualLenBytes);
+        if ((SOTP_SUCCESS != status) && (SOTP_NOT_FOUND != status))
+        {
+            ret = pal_osSotpErrorTranslation(status);
+        }
+        else if ((sizeof(uint64_t) != actualLenBytes) && (SOTP_NOT_FOUND != status))
+        {
+            ret = PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT;
+        }
+        else if ((setNewTimeInSeconds > getSotpTimeValue) && (setNewTimeInSeconds - getSotpTimeValue > PAL_MINIMUM_STORAGE_LATENCY_SEC))
+        {
+            status = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setNewTimeInSeconds);
+            if (SOTP_SUCCESS != status)
+            {
+                ret = pal_osSotpErrorTranslation(status);
+            }
+            else
+            {
+                g_lastSavedTimeInSec = setNewTimeInSeconds;
+            }
+        }
+    }
+    return ret;
+}
+
+/*! Write a value (either all or specific bits) to the global noise buffer
+*
+* @param[in] data The value containing the bits to be written.
+* @param[in] startBit The index of the first bit to be written, valid values are 0-31.
+* @param[in] lenBits The number of bits that should be written (startBit+lenBits must be less than 32).
+* @param[out] bitsWritten The number of bits that were actually written.
+*
+* \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_noiseWriteValue(const int32_t* data, uint8_t startBit, uint8_t lenBits, uint8_t* bitsWritten)
+{
+    PAL_VALIDATE_ARGUMENTS((NULL == data) || (PAL_INT32_BITS - 1 < startBit) || (PAL_INT32_BITS < lenBits + startBit) || (NULL == bitsWritten));
+
+    palStatus_t status = PAL_SUCCESS;
+    uint16_t incrementedBitCount;
+    uint8_t currentIndex, occupiedBitsInCurrentIndex, availableBitsInCurrentIndex;
+    uint32_t mask, value;
+
+    *bitsWritten = 0;
+    if (PAL_NOISE_SIZE_BITS == g_noise.bitCountActual)
+    {
+        return PAL_ERR_RTOS_NOISE_BUFFER_FULL;
+    }
+
+    pal_osAtomicIncrement((int32_t*)(&g_noise.numWriters), 1); // increment number of writers
+    if (g_noise.isReading) // if we're in read mode then discard & exit
+    {
+        status = PAL_ERR_RTOS_NOISE_BUFFER_IS_READING;
+        goto finish;
+    }
+
+    incrementedBitCount = (uint16_t)pal_osAtomicIncrement((int32_t*)(&g_noise.bitCountAllocated), lenBits); // reserve space in the array
+    if (PAL_NOISE_SIZE_BITS < incrementedBitCount) // we want to write more bits than are available in the (entire) buffer
+    {
+        lenBits -= incrementedBitCount - PAL_NOISE_SIZE_BITS; // max number of bits that are avialable for writing
+        if ((int8_t)lenBits <= 0) // we don't have any available bits for writing
+        {
+            status = PAL_ERR_RTOS_NOISE_BUFFER_FULL;
+            goto finish;
+        }
+        incrementedBitCount = PAL_NOISE_SIZE_BITS;
+    }
+
+    currentIndex = (incrementedBitCount - lenBits) / PAL_INT32_BITS; // the current index in the array
+    occupiedBitsInCurrentIndex = (incrementedBitCount - lenBits) % PAL_INT32_BITS; // how many bits are already occupied (with either 0 or 1) in the current index
+    availableBitsInCurrentIndex = PAL_INT32_BITS - occupiedBitsInCurrentIndex; // how many bits are available in the current index
+
+    if (lenBits > availableBitsInCurrentIndex) // we want to write more bits than are available in the current index so we need to split the bits
+    {
+        mask = ((((int32_t)1) << availableBitsInCurrentIndex) - 1) << startBit; // mask to isolate the wanted bits
+        value = *data & mask;
+        if (((int8_t)(startBit - occupiedBitsInCurrentIndex)) > 0)
+        {
+            value = value >> (startBit - occupiedBitsInCurrentIndex);
+        }
+        else if (((int8_t)(startBit - occupiedBitsInCurrentIndex)) < 0)
+        {
+            value = value << (occupiedBitsInCurrentIndex - startBit);
+        }
+        pal_osAtomicIncrement(&g_noise.buffer[currentIndex], value); // write the 1st part of the splitted bits to the current index of the noise buffer
+        *bitsWritten = availableBitsInCurrentIndex;
+        lenBits -= availableBitsInCurrentIndex; // how many bits remain to be written
+        startBit += availableBitsInCurrentIndex;
+        mask = ((((int32_t)1) << lenBits) - 1) << startBit; // mask for the remaining bits that have not been written yet
+        value = *data & mask;
+        value = value >> startBit; // since we're writting to the next index we start at bit 0
+        pal_osAtomicIncrement(&g_noise.buffer[currentIndex + 1], value); // write the 2nd part of the splitted bits to the next index of the noise buffer
+        *bitsWritten += lenBits;
+    }
+    else // we have enough available bits for the current index (no need to split the bits)
+    {
+        mask = ((((int64_t)1) << lenBits) - 1) << startBit; // int64_t in case we want all the 32 bits
+        value = *data & mask;
+        if (((int8_t)(startBit - occupiedBitsInCurrentIndex)) > 0)
+        {
+            value = value >> (startBit - occupiedBitsInCurrentIndex);
+        }
+        else if (((int8_t)(startBit - occupiedBitsInCurrentIndex)) < 0)
+        {
+            value = value << (occupiedBitsInCurrentIndex - startBit);
+        }
+        pal_osAtomicIncrement(&g_noise.buffer[currentIndex], value); // write the bits to the current index of the noise buffer
+        *bitsWritten = lenBits;
+    }
+    pal_osAtomicIncrement((int32_t*)(&g_noise.bitCountActual) , *bitsWritten); // increment how many bits were actually written    
+finish:
+    pal_osAtomicIncrement((int32_t*)(&g_noise.numWriters), -1); // decrement number of writers
+    return status;
+}
+
+/*! Write values to the global noise buffer
+*
+* @param[in] buffer The buffer which contains the values to be written.
+* @param[in] lenBits The number of bits that should be written.
+* @param[out] bitsWritten The number of bits that were actually written.
+*
+* \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_noiseWriteBuffer(int32_t* buffer, uint16_t lenBits, uint16_t* bitsWritten)
+{
+    PAL_VALIDATE_ARGUMENTS((NULL == buffer) || (PAL_NOISE_SIZE_BITS < lenBits) || (NULL == bitsWritten));
+
+    palStatus_t status;
+    uint8_t idx, bitsToWrite;
+    uint16_t totalBitsWritten;
+
+    idx = 0;
+    totalBitsWritten = 0;
+    do
+    {
+        bitsToWrite = (lenBits > PAL_INT32_BITS) ? PAL_INT32_BITS : lenBits; // we can write a max number of 32 bits at a time
+        status = pal_noiseWriteValue(&buffer[idx], 0, bitsToWrite, (uint8_t*)bitsWritten);
+        lenBits -= bitsToWrite;
+        idx++;
+        totalBitsWritten += *bitsWritten;
+    } while ((PAL_SUCCESS == status) && (bitsToWrite == *bitsWritten) && lenBits); // exit if there was an error, or the noise buffer has no more space, or all bits were written
+
+    *bitsWritten = totalBitsWritten;
+    if (0 < totalBitsWritten)
+    {
+        status = PAL_SUCCESS;
+    }
+    return status;
+}
+
+/*! Read values from the global noise buffer
+*
+* @param[out] buffer The output buffer which will contain the noise data collected.
+* @param[in] partial When true read what was collected so far, otherwise read only if the noise buffer is full.
+* @param[out] bitsRead he number of bits that were actually read.
+*
+* \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_noiseRead(int32_t buffer[PAL_NOISE_BUFFER_LEN], bool partial, uint16_t* bitsRead)
+{
+    PAL_VALIDATE_ARGUMENTS((NULL == buffer) || (NULL == bitsRead));
+
+    static uint32_t numOfNoiseReaders = 0; // allow only one reader at a time (no concurrent reads)
+    palStatus_t status = PAL_SUCCESS;
+    uint8_t numBytesToRead, numReadersLocal;
+    uint16_t bitCountActual = (uint16_t)g_noise.bitCountActual;
+    numReadersLocal = (uint8_t)pal_osAtomicIncrement((int32_t*)(&numOfNoiseReaders), 1); // increment number of readers
+    *bitsRead = 0;
+    if (1 != numReadersLocal) // single reader
+    {
+        PAL_LOG(DBG, "noise cannot read by multiple readers\n");
+        status = PAL_ERR_RTOS_NOISE_BUFFER_EMPTY;
+        goto finish;
+    }
+    
+    if ((CHAR_BIT > bitCountActual) || (!partial && (PAL_NOISE_SIZE_BITS != bitCountActual))) // exit if less than 1 byte was written or if we want a full read and not all bits were written
+    {
+        status = (CHAR_BIT > bitCountActual) ? PAL_ERR_RTOS_NOISE_BUFFER_EMPTY : PAL_ERR_RTOS_NOISE_BUFFER_NOT_FULL;
+        goto finish;
+    }
+
+    g_noise.isReading = true; // set mode to reading so that no more writes will be allowed
+    while (g_noise.numWriters) // wait for currently executing writers to finish (relevant only for partial read)
+    {
+        pal_osDelay(PAL_NOISE_WAIT_FOR_WRITERS_DELAY_MILLI_SEC);
+    }
+    bitCountActual = (uint16_t)g_noise.bitCountActual; // this may occur if we waited for the writers to finish writing, meaning we might have a few more bits (relevant only for partial read)
+    numBytesToRead = (uint8_t)PAL_NOISE_BITS_TO_BYTES(bitCountActual);    
+    memcpy((void*)buffer, (void*)g_noise.buffer, numBytesToRead); // copy noise buffer to output buffer
+    *bitsRead = (numBytesToRead * CHAR_BIT); // set out param of how many bits were actually read
+    memset((void*)g_noise.buffer, 0, PAL_NOISE_SIZE_BYTES); // reset the noise buffer
+    g_noise.bitCountActual = g_noise.bitCountAllocated = 0; // reset counters
+    g_noise.isReading = false; // exit read mode so that writters will be able to continue writting
+    PAL_LOG(DBG, "noise read %" PRIu8 " bits\n", *bitsRead);
+finish:
+    pal_osAtomicIncrement((int32_t*)(&numOfNoiseReaders), -1); // decrement number of readers
+    return status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Storage/FileSystem/pal_fileSystem.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,281 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+/*
+ * 2.c
+ *
+ *  Created on: 22 Jan 2017
+ *      Author: alonof01
+ */
+
+#include "pal.h"
+#include "pal_fileSystem.h"
+#include "pal_plat_fileSystem.h"
+
+PAL_PRIVATE char* g_RootFolder[PAL_FS_PARTITION_LAST] = { NULL , NULL };      //!< global var that holds the  root folder
+PAL_PRIVATE bool g_RootFolderIsSet[PAL_FS_PARTITION_LAST] = { false, false };    //!< global var that holds the state root folder
+
+
+void pal_fsCleanup()
+{
+    if (NULL != g_RootFolder[PAL_FS_PARTITION_PRIMARY])
+    {
+        free(g_RootFolder[PAL_FS_PARTITION_PRIMARY]);
+        g_RootFolder[PAL_FS_PARTITION_PRIMARY] = NULL;
+    }
+
+    if (NULL != g_RootFolder[PAL_FS_PARTITION_SECONDARY])
+    {
+        free(g_RootFolder[PAL_FS_PARTITION_SECONDARY]);
+        g_RootFolder[PAL_FS_PARTITION_SECONDARY] = NULL;
+    }
+
+    g_RootFolder[PAL_FS_PARTITION_SECONDARY] = NULL;
+    g_RootFolderIsSet[PAL_FS_PARTITION_PRIMARY] = false;
+    g_RootFolderIsSet[PAL_FS_PARTITION_SECONDARY] = false;
+}
+
+
+
+palStatus_t pal_fsMkDir(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    PAL_VALIDATE_CONDITION_WITH_ERROR((pathName == NULL), PAL_ERR_FS_INVALID_FILE_NAME)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((pal_plat_fsSizeCheck(pathName) >= PAL_MAX_FOLDER_DEPTH_CHAR), PAL_ERR_FS_FILENAME_LENGTH)
+
+	ret = pal_plat_fsMkdir(pathName);
+	if ((PAL_SUCCESS != ret) && (PAL_ERR_FS_NAME_ALREADY_EXIST != ret))
+	{
+		PAL_LOG(ERR, "Failed to create folder, was the storage properly initialized?");
+	}
+
+    return ret;
+}
+
+
+
+palStatus_t pal_fsRmDir(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    PAL_VALIDATE_CONDITION_WITH_ERROR((pathName == NULL), PAL_ERR_FS_INVALID_FILE_NAME)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((pal_plat_fsSizeCheck(pathName) >= PAL_MAX_FOLDER_DEPTH_CHAR), PAL_ERR_FS_FILENAME_LENGTH)
+
+    ret = pal_plat_fsRmdir(pathName);
+    return ret;
+}
+
+palStatus_t pal_fsFopen(const char *pathName, pal_fsFileMode_t mode, palFileDescriptor_t *fd)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    PAL_VALIDATE_CONDITION_WITH_ERROR((fd == NULL), PAL_ERR_FS_INVALID_ARGUMENT)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((pathName == NULL), PAL_ERR_FS_INVALID_FILE_NAME)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((pal_plat_fsSizeCheck(pathName) >= PAL_MAX_FOLDER_DEPTH_CHAR), PAL_ERR_FS_FILENAME_LENGTH)
+	PAL_VALIDATE_CONDITION_WITH_ERROR((!((mode > PAL_FS_FLAG_KEEP_FIRST) && (mode < PAL_FS_FLAG_KEEP_LAST))), PAL_ERR_FS_INVALID_OPEN_FLAGS)
+
+    ret = pal_plat_fsFopen(pathName,  mode, fd);
+    if (ret != PAL_SUCCESS)
+    {
+        *fd = 0;
+    }
+    return ret;
+}
+
+
+palStatus_t pal_fsFclose(palFileDescriptor_t *fd)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    PAL_VALIDATE_CONDITION_WITH_ERROR((fd == NULL), PAL_ERR_FS_INVALID_ARGUMENT)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((*fd == 0), PAL_ERR_FS_BAD_FD)
+
+	ret = pal_plat_fsFclose(fd);
+	*fd = 0;
+    return ret;
+}
+
+
+palStatus_t pal_fsFread(palFileDescriptor_t *fd, void * buffer, size_t numOfBytes, size_t *numberOfBytesRead)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    *numberOfBytesRead = 0;
+    PAL_VALIDATE_CONDITION_WITH_ERROR((*fd == 0), PAL_ERR_FS_BAD_FD)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((buffer == NULL), PAL_ERR_FS_BUFFER_ERROR)
+
+    ret = pal_plat_fsFread(fd, buffer, numOfBytes, numberOfBytesRead);
+    return ret;
+}
+
+
+palStatus_t pal_fsFwrite(palFileDescriptor_t *fd, const void * buffer, size_t numOfBytes, size_t *numberOfBytesWritten)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    *numberOfBytesWritten = 0;
+    PAL_VALIDATE_CONDITION_WITH_ERROR((*fd == 0), PAL_ERR_FS_BAD_FD)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((numOfBytes == 0), PAL_ERR_FS_LENGTH_ERROR)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((buffer == NULL), PAL_ERR_FS_BUFFER_ERROR)
+
+    ret = pal_plat_fsFwrite(fd, buffer, numOfBytes, numberOfBytesWritten);
+    return ret;
+}
+
+
+palStatus_t pal_fsFseek(palFileDescriptor_t *fd, int32_t offset, pal_fsOffset_t whence)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    PAL_VALIDATE_CONDITION_WITH_ERROR((*fd == 0), PAL_ERR_FS_BAD_FD)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((!((whence < PAL_FS_OFFSET_KEEP_LAST) && (whence > PAL_FS_OFFSET_KEEP_FIRST))), PAL_ERR_FS_OFFSET_ERROR)
+
+    ret = pal_plat_fsFseek(fd, offset, whence);
+    return ret;
+}
+
+
+palStatus_t pal_fsFtell(palFileDescriptor_t *fd, int32_t *pos)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    PAL_VALIDATE_CONDITION_WITH_ERROR((*fd == 0), PAL_ERR_FS_BAD_FD)
+
+    ret = pal_plat_fsFtell(fd, pos);
+    return ret;
+}
+
+palStatus_t pal_fsUnlink(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    PAL_VALIDATE_CONDITION_WITH_ERROR((pathName == NULL), PAL_ERR_FS_INVALID_FILE_NAME)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((pal_plat_fsSizeCheck(pathName) >= PAL_MAX_FULL_FILE_NAME), PAL_ERR_FS_FILENAME_LENGTH)
+
+    ret = pal_plat_fsUnlink(pathName);
+    return ret;
+}
+
+
+
+palStatus_t pal_fsRmFiles(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    PAL_VALIDATE_CONDITION_WITH_ERROR((pathName == NULL), PAL_ERR_FS_INVALID_FILE_NAME)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((pal_plat_fsSizeCheck(pathName) >= PAL_MAX_FOLDER_DEPTH_CHAR), PAL_ERR_FS_FILENAME_LENGTH)
+
+	ret = pal_plat_fsRmFiles(pathName);
+    return ret;
+}
+
+
+palStatus_t pal_fsCpFolder(const char *pathNameSrc,  char *pathNameDest)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    PAL_VALIDATE_CONDITION_WITH_ERROR(((pathNameSrc == NULL) || ((pathNameDest == NULL))), PAL_ERR_FS_INVALID_FILE_NAME)
+    PAL_VALIDATE_CONDITION_WITH_ERROR(((pal_plat_fsSizeCheck(pathNameSrc) >= PAL_MAX_FOLDER_DEPTH_CHAR) || (pal_plat_fsSizeCheck(pathNameDest) >= PAL_MAX_FOLDER_DEPTH_CHAR)), PAL_ERR_FS_FILENAME_LENGTH)
+
+	ret = pal_plat_fsCpFolder(pathNameSrc, pathNameDest);
+    return ret;
+}
+
+
+
+palStatus_t pal_fsSetMountPoint(pal_fsStorageID_t dataID, const char *path)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    PAL_VALIDATE_CONDITION_WITH_ERROR(((dataID >= PAL_FS_PARTITION_LAST) || (NULL == path)), PAL_ERR_FS_INVALID_FILE_NAME)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((pal_plat_fsSizeCheck(path) >= PAL_MAX_FOLDER_DEPTH_CHAR), PAL_ERR_FS_FILENAME_LENGTH)
+
+	if (g_RootFolderIsSet[dataID])
+	{
+		ret = PAL_ERR_FS_ERROR;
+	}
+	else
+	{
+		if (NULL == g_RootFolder[dataID])
+		{
+			g_RootFolder[dataID] = (char*)malloc(PAL_MAX_FOLDER_DEPTH_CHAR);
+			if (NULL == g_RootFolder[dataID])
+			{
+				return PAL_ERR_NO_MEMORY;
+			}
+			g_RootFolder[dataID][0] = NULLPTR;
+		}
+		strncat( g_RootFolder[dataID], path, PAL_MAX_FOLDER_DEPTH_CHAR - pal_plat_fsSizeCheck(g_RootFolder[dataID]));// same buffer is used for active backup root dirs using indexing
+		g_RootFolderIsSet[dataID] = true;
+	}
+    return ret;
+}
+
+palStatus_t pal_fsGetMountPoint(pal_fsStorageID_t dataID, size_t length, char *path)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    PAL_VALIDATE_CONDITION_WITH_ERROR((dataID >= PAL_FS_PARTITION_LAST), PAL_ERR_INVALID_ARGUMENT)
+    PAL_VALIDATE_CONDITION_WITH_ERROR((length < PAL_MAX_FOLDER_DEPTH_CHAR), PAL_ERR_FS_LENGTH_ERROR)
+
+    if (path)
+    {
+        if (false == g_RootFolderIsSet[dataID])
+        {
+            strncpy(path, pal_plat_fsGetDefaultRootFolder(dataID), length);
+        }
+        else 
+        {
+            strncpy(path, g_RootFolder[dataID], length); // same buffer is used for active backup root dirs using indexing
+        }
+        
+    }
+    else
+    {
+        ret = PAL_ERR_FS_BUFFER_ERROR;
+    }
+    return ret;
+}
+
+
+palStatus_t pal_fsFormat(pal_fsStorageID_t dataID)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    PAL_VALIDATE_CONDITION_WITH_ERROR((((int32_t)dataID < PAL_FS_PARTITION_PRIMARY) || ((int32_t)dataID >= PAL_FS_PARTITION_LAST)), PAL_ERR_INVALID_ARGUMENT)
+
+#if PAL_SIMULATOR_FS_RM_INSTEAD_OF_FORMAT //Simulator    
+	char rootFolder[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+	ret = pal_fsGetMountPoint(dataID, PAL_MAX_FILE_AND_FOLDER_LENGTH, rootFolder);
+	if (PAL_SUCCESS == ret)
+	{
+		ret = pal_plat_fsRmFiles(rootFolder);
+		if (PAL_SUCCESS != ret)
+		{
+			PAL_LOG(ERR,"(%s:%d) pal_plat_fsRmFiles  failed ",__FILE__,__LINE__);
+		}
+	}
+#else //Real life scenario
+	ret = pal_plat_fsFormat(dataID);
+#endif        
+    
+    return ret;
+}
+
+
+
+
+bool pal_fsIsPrivatePartition(pal_fsStorageID_t dataID)
+{
+    bool isPrivate;
+    if (PAL_FS_PARTITION_PRIMARY == dataID)
+    {
+        isPrivate = PAL_PRIMARY_PARTITION_PRIVATE;
+    }
+    else
+    {
+        isPrivate = PAL_SECONDARY_PARTITION_PRIVATE;
+    }
+    return isPrivate;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Storage/Flash/pal_internalFlash.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,507 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "pal.h"
+#include "pal_plat_internalFlash.h"
+#include "stdio.h"
+
+#if (PAL_USE_INTERNAL_FLASH)
+
+#define BITS_ALIGNED_TO_32 	0x3
+#define PAL_MAX_PAGE_SIZE   16
+
+//////////////////////////GLOBALS SECTION ////////////////////////////
+#if PAL_THREAD_SAFETY	
+// Use semaphore and not mutex, as mutexes don't behave well when trying to delete them while taken (which may happen in our tests).
+static palSemaphoreID_t flashSem = NULLPTR;
+#endif
+
+#if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+	PAL_PRIVATE palFileDescriptor_t g_fd = 0;
+#endif
+//////////////////////////END GLOBALS SECTION ////////////////////////////
+
+
+//////////////////////////START PRIVATE SECTION////////////////////////////
+// Verify that the alignment  to sector size
+// Parameters :
+// @param[in] address     - Address to verify.
+// @param[in] size        - Size to write
+// Return     : None.
+PAL_PRIVATE bool pal_isAlignedToSector(uint32_t address, size_t size)
+{
+    uint32_t currentSectorSize = pal_internalFlashGetSectorSize(address);
+    if ((size % currentSectorSize) || (address % currentSectorSize))
+    {
+        return false;
+    }
+    else
+    {
+        return true;
+	}
+}
+
+
+
+#if !PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+
+// Program to Flash with alignments to page size
+// Parameters :
+// @param[in]	buffer - pointer to the buffer to be written
+// @param[in]	size - the size of the buffer in bytes.
+// @param[in]	address - the address of the internal flash, must be aligned to minimum writing unit (page size).
+// Return     : None.
+PAL_PRIVATE palStatus_t pal_programToFlashAligned(const size_t size, const uint32_t address, const uint32_t * buffer)
+{
+	palStatus_t ret = PAL_SUCCESS;
+	uint32_t pageSize = 0, alignmentLeft = 0;
+
+	pageSize = pal_internalFlashGetPageSize();
+	alignmentLeft = size % pageSize; //Keep the leftover to be copied separately
+
+	if (size >= pageSize)
+	{
+		ret = pal_plat_internalFlashWrite(size - alignmentLeft, address, buffer);
+	}
+
+	if ((ret == PAL_SUCCESS) && (alignmentLeft != 0))
+	{
+		uint32_t * pageBuffer = (uint32_t *)malloc(pageSize);
+		if (pageBuffer == NULL)
+		{
+			ret = PAL_ERR_NO_MEMORY;
+		}
+		else
+		{
+			memset(pageBuffer, 0xFF, pageSize);
+			memcpy(pageBuffer, (uint8_t*)buffer + (size - alignmentLeft), alignmentLeft);
+			ret = pal_plat_internalFlashWrite(pageSize, address + (size - alignmentLeft), pageBuffer);
+			free(pageBuffer);
+		}		
+	}
+	return ret;
+}
+
+#else //PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+
+// Append root folder to path 
+// Parameters :
+// @param[in] input        - string to add the root prefix
+// @param[out] path        - output buffer
+// Return     : None.
+PAL_PRIVATE palStatus_t pal_addRootToPath(const char* input, char* path)
+{
+    char root[PAL_MAX_FILE_AND_FOLDER_LENGTH] = { 0 };
+    palStatus_t status = PAL_SUCCESS;
+
+    memset(path, 0, PAL_MAX_FILE_AND_FOLDER_LENGTH);
+    status = pal_fsGetMountPoint(PAL_FS_PARTITION_SECONDARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, root);
+	if(PAL_SUCCESS == status)
+	{
+		snprintf(path, PAL_MAX_FILE_AND_FOLDER_LENGTH -1,"%s/%s", root, input);
+	}
+    
+    return status;
+}
+
+// Check whether area file exists. Create it if not. 
+// Parameters :
+// @param[in] area        - Flash area.
+// Return     : None.
+// Note - If file does not exist create and fill with 0xFF this simulate erased flash
+PAL_PRIVATE palStatus_t pal_verifyAndCreateFlashFile(void)
+{
+	uint32_t index;
+	uint8_t writeBuffer[SIMULATE_FLASH_PAGE_SIZE] = {0};
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+	palStatus_t ret = PAL_SUCCESS;
+	size_t numOfBytes = 0;
+	palSotpAreaData_t areaData_1, areaData_2;
+
+	pal_internalFlashGetAreaInfo(0, &areaData_1);
+	pal_internalFlashGetAreaInfo(1, &areaData_2);
+
+	ret = pal_addRootToPath(SIMULATE_FLASH_FILE_NAME, buffer);
+	if(PAL_SUCCESS == ret )
+	{
+		ret = pal_fsFopen(buffer, PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd);
+		if(PAL_ERR_FS_NAME_ALREADY_EXIST == ret)
+		{
+			return PAL_SUCCESS; //file exist nothing else to do
+		}
+		else if(PAL_SUCCESS == ret)
+		{
+			memset(writeBuffer, PAL_INT_FLASH_BLANK_VAL, SIMULATE_FLASH_PAGE_SIZE);
+			for (index = 0; index < (areaData_1.size + areaData_2.size) / SIMULATE_FLASH_PAGE_SIZE; index++) 
+			{		
+				ret = pal_fsFwrite(&g_fd, (void *)writeBuffer, SIMULATE_FLASH_PAGE_SIZE, &numOfBytes);
+				if(PAL_SUCCESS != ret)
+				{
+					break;
+				}
+			}
+			pal_fsFclose(&g_fd);
+		}
+	}
+    return ret;
+}
+#endif //PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+
+
+//////////////////////////END PRIVATE SECTION////////////////////////////
+
+
+size_t pal_internalFlashGetPageSize(void)
+{
+#if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+	size_t ret = SIMULATE_FLASH_PAGE_SIZE;
+#else
+	size_t ret = pal_plat_internalFlashGetPageSize();
+#endif	//PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+	if(ret > PAL_MAX_PAGE_SIZE)
+	{
+	    ret = PAL_MAX_PAGE_SIZE;
+	}
+	return ret;
+}
+
+size_t pal_internalFlashGetSectorSize(uint32_t address)
+{
+#if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+	size_t ret = SIMULATE_FLASH_SECTOR_SIZE;
+#else
+	size_t ret = pal_plat_internalFlashGetSectorSize(address);
+#endif	//PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+	return ret;
+}
+
+palStatus_t pal_internalFlashInit(void)
+{
+	palStatus_t ret = PAL_SUCCESS;
+#if !PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM	
+	ret = pal_plat_internalFlashInit();
+#endif	
+	if(PAL_SUCCESS == ret)
+	{
+#if PAL_THREAD_SAFETY		
+		ret = pal_osSemaphoreCreate(1, &flashSem);
+		if (PAL_SUCCESS != ret) 
+		{
+			PAL_LOG(ERR, "Semaphore Create Error %" PRId32 ".", ret);		
+		}
+		else
+#endif		
+		{
+#if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+			char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+			int32_t ctrs = 0;
+
+			if(SIMULATE_FLASH_DIR[0] != '\0')
+			{						
+				ret = pal_addRootToPath(SIMULATE_FLASH_DIR, buffer);
+				if (PAL_SUCCESS == ret )
+				{
+					ret = pal_fsMkDir(buffer); //Create Directory		
+					if ((PAL_ERR_FS_NAME_ALREADY_EXIST == ret))
+					{
+						ret = PAL_SUCCESS;
+					}
+				}
+			}
+			if (PAL_SUCCESS == ret )
+			{											
+#if PAL_THREAD_SAFETY							
+				ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, &ctrs);
+				if (PAL_SUCCESS == ret)	
+#endif					
+				{
+					ret = pal_verifyAndCreateFlashFile();
+#if PAL_THREAD_SAFETY						
+					palStatus_t error = pal_osSemaphoreRelease(flashSem);
+					if(PAL_SUCCESS != error)
+					{
+						PAL_LOG(ERR, "SemaphoreRelease Error %" PRId32 ".", error);
+					}
+#endif						
+				}
+			}		
+#endif	//PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+		}
+	}
+
+#if !PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+	if(PAL_SUCCESS != ret)
+	{//Clean resources 
+		pal_plat_internalFlashDeInit();
+	}
+#endif	//PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+
+	return ret;
+}
+
+
+palStatus_t pal_internalFlashDeInit(void)
+{
+	palStatus_t ret = PAL_SUCCESS;
+#if !PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM	
+	ret = pal_plat_internalFlashDeInit();
+#endif
+
+	// Semaphore may be taken, so deleting it would fail. Try releasing (without checking return code).
+	if(PAL_SUCCESS == ret)
+	{
+#if PAL_THREAD_SAFETY
+		pal_osSemaphoreRelease(flashSem);
+		ret = pal_osSemaphoreDelete(&flashSem);
+#endif		
+	}
+	return ret;
+}
+
+palStatus_t pal_internalFlashRead(const size_t size, const uint32_t address, uint32_t * buffer)
+{
+	palStatus_t ret = PAL_SUCCESS;
+	int32_t ctrs = 0;
+
+
+	PAL_VALIDATE_CONDITION_WITH_ERROR ((buffer == NULL), PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED)
+	PAL_VALIDATE_CONDITION_WITH_ERROR ((size == 0),PAL_ERR_INTERNAL_FLASH_WRONG_SIZE)
+
+#if PAL_THREAD_SAFETY
+	ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, &ctrs);
+	if (PAL_SUCCESS != ret)	
+	{
+		return ret;
+	}
+#endif
+
+#if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM	
+	size_t numberOfBytesRead = 0;
+	char fileBuffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+
+	pal_addRootToPath(SIMULATE_FLASH_FILE_NAME, fileBuffer);
+	ret = pal_fsFopen(fileBuffer, PAL_FS_FLAG_READONLY, &g_fd);	
+	if(PAL_SUCCESS == ret)
+	{
+		ret = pal_fsFseek(&g_fd, address, PAL_FS_OFFSET_SEEKSET);
+		if(PAL_SUCCESS == ret)
+		{
+			ret = pal_fsFread(&g_fd, buffer, size, &numberOfBytesRead);	
+		}
+		pal_fsFclose(&g_fd);
+	}
+#else
+	ret = pal_plat_internalFlashRead(size, address, buffer);
+#endif	//PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+
+#if PAL_THREAD_SAFETY
+	palStatus_t error = pal_osSemaphoreRelease(flashSem);
+	if(PAL_SUCCESS != error)
+	{
+		PAL_LOG(ERR, "SemaphoreRelease Error %" PRId32 ".", error);
+	}
+#endif
+
+	return ret;
+}
+
+
+palStatus_t pal_internalFlashErase(uint32_t address, size_t size)
+{
+	palStatus_t ret = PAL_SUCCESS;
+
+	int32_t ctrs = 0;
+	
+	PAL_VALIDATE_CONDITION_WITH_ERROR ((size == 0),PAL_ERR_INTERNAL_FLASH_WRONG_SIZE)
+	PAL_VALIDATE_ARG_RLZ ((address & BITS_ALIGNED_TO_32),PAL_ERR_INTERNAL_FLASH_BUFFER_ADDRESS_NOT_ALIGNED)//Address not aligned to 32 bit
+	PAL_VALIDATE_ARG_RLZ ((!pal_isAlignedToSector(address,size)),PAL_ERR_INTERNAL_FLASH_SECTOR_NOT_ALIGNED)//not aligned to sector
+
+#if PAL_THREAD_SAFETY
+	ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, &ctrs);
+	if (PAL_SUCCESS != ret)	
+	{
+		return ret;
+	}
+#endif 
+
+#if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+	char fileBuffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+	size_t numOfBytes = 0, index = 0;
+	uint8_t writeBuffer[SIMULATE_FLASH_PAGE_SIZE] = {0};
+	
+	pal_addRootToPath(SIMULATE_FLASH_FILE_NAME, fileBuffer);
+	ret = pal_fsFopen(fileBuffer, PAL_FS_FLAG_READWRITE, &g_fd);
+	if (PAL_SUCCESS == ret)	
+	{
+        ret = pal_fsFseek(&g_fd, address, PAL_FS_OFFSET_SEEKSET);
+        if (PAL_SUCCESS == ret)
+        {
+            memset(writeBuffer, PAL_INT_FLASH_BLANK_VAL, SIMULATE_FLASH_PAGE_SIZE);
+            for (index = 0; index < size / SIMULATE_FLASH_PAGE_SIZE; index++)
+            {
+                ret = pal_fsFwrite(&g_fd, (void *)writeBuffer, SIMULATE_FLASH_PAGE_SIZE, &numOfBytes);
+                if(PAL_SUCCESS != ret)
+                {
+                    break;
+                }
+            }
+        }
+		pal_fsFclose(&g_fd);
+	}
+#else	
+	size_t sectorSize = 0;
+	sectorSize = pal_internalFlashGetSectorSize(address);
+	while(size)
+	{
+		ret = pal_plat_internalFlashErase(address, size);
+		size -= sectorSize;
+		address += pal_internalFlashGetSectorSize(address + sectorSize);
+		sectorSize = pal_internalFlashGetSectorSize(address);
+	}
+#endif
+
+#if PAL_THREAD_SAFETY
+	palStatus_t error = pal_osSemaphoreRelease(flashSem);
+	if(PAL_SUCCESS != error)
+	{
+		PAL_LOG(ERR, "SemaphoreRelease Error %" PRId32 ".", error);
+	}
+#endif	
+	return ret;
+}
+
+
+palStatus_t pal_internalFlashWrite(const size_t size, const uint32_t address, const uint32_t * buffer)
+{
+	palStatus_t ret = PAL_SUCCESS;
+	uint32_t pageSize = 0;
+	int32_t ctrs = 0;
+
+	PAL_VALIDATE_CONDITION_WITH_ERROR ((buffer == NULL), PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED)
+	PAL_VALIDATE_ARG_RLZ ((address & BITS_ALIGNED_TO_32),PAL_ERR_INTERNAL_FLASH_BUFFER_ADDRESS_NOT_ALIGNED)//Address not aligned to 32 bit
+	PAL_VALIDATE_ARG_RLZ ((size == 0),PAL_ERR_INTERNAL_FLASH_WRONG_SIZE)
+
+
+	pageSize = pal_internalFlashGetPageSize();	
+	if (address % pageSize)
+	{
+		ret =  PAL_ERR_INTERNAL_FLASH_ADDRESS_NOT_ALIGNED;
+	}
+	else
+	{	
+#if PAL_THREAD_SAFETY
+		ret = pal_osSemaphoreWait(flashSem, PAL_RTOS_WAIT_FOREVER, &ctrs);
+		if (PAL_SUCCESS != ret)	
+		{
+			return ret;
+		}
+#endif
+#if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+		char fileBuffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+		uint32_t alignmentLeft = 0;
+		size_t numOfBytes = 0;
+
+		pal_addRootToPath(SIMULATE_FLASH_FILE_NAME, fileBuffer);
+		ret = pal_fsFopen(fileBuffer, PAL_FS_FLAG_READWRITE, &g_fd);	
+		if (PAL_SUCCESS == ret)			
+		{
+			alignmentLeft = size % pageSize; //Keep the leftover to be copied separately		
+			if (size >= pageSize)
+			{							
+				ret = pal_fsFseek(&g_fd, address, PAL_FS_OFFSET_SEEKSET);
+				if (PAL_SUCCESS == ret)
+				{
+					ret = pal_fsFwrite(&g_fd, (void *)buffer, size - alignmentLeft, &numOfBytes);				
+				}						
+			}
+
+			if ((ret == PAL_SUCCESS) && (alignmentLeft != 0))
+			{
+				uint32_t * pageBuffer = (uint32_t *)malloc(pageSize);
+				if (pageBuffer == NULL)
+				{
+					ret = PAL_ERR_NO_MEMORY;
+				}
+				else
+				{
+					memset(pageBuffer, 0xFF, pageSize);
+					memcpy(pageBuffer, (uint8_t*)buffer + (size - alignmentLeft), alignmentLeft);				
+					ret = pal_fsFseek(&g_fd, address + (size - alignmentLeft), PAL_FS_OFFSET_SEEKSET);
+					if(PAL_SUCCESS == ret)
+					{
+						ret = pal_fsFwrite(&g_fd, (void *)pageBuffer, pageSize, &numOfBytes);
+					}
+					free(pageBuffer);
+				}
+			}
+			pal_fsFclose(&g_fd);
+		}
+#else	
+		size_t sizeLeft = size;
+		uint32_t tempAddress = address;
+		uint32_t sectorSize = pal_internalFlashGetSectorSize(address);
+		
+		//This section handles writing on cross sectors
+		while (((tempAddress % sectorSize) + sizeLeft) > sectorSize)
+		{
+			size_t tmpSize = sectorSize - (tempAddress % sectorSize);			
+			ret = pal_programToFlashAligned(tmpSize, tempAddress, buffer); //Fill the sector to the end
+			if( PAL_SUCCESS != ret)
+			{
+				break;
+			}
+			sizeLeft -= tmpSize;
+			tempAddress += tmpSize;
+			buffer += tmpSize / sizeof(uint32_t);
+			//Read sector size again because Sector size can change when crossing sectors.
+			sectorSize = pal_internalFlashGetSectorSize(address); 
+		}
+
+		//Write part of a sector (remainder of the buffer)
+		if ((PAL_SUCCESS == ret) && (sizeLeft > 0))
+		{
+			ret = pal_programToFlashAligned(sizeLeft, tempAddress, buffer);
+		}
+#endif
+#if PAL_THREAD_SAFETY
+		palStatus_t error = pal_osSemaphoreRelease(flashSem);
+		if(PAL_SUCCESS != error)
+		{
+			PAL_LOG(ERR, "SemaphoreRelease Error %" PRId32 ".", error);
+		}
+#endif		
+		
+	}
+	return ret;
+}
+
+
+palStatus_t pal_internalFlashGetAreaInfo(uint8_t section, palSotpAreaData_t *data)
+{
+	palStatus_t ret = PAL_SUCCESS;
+	const palSotpAreaData_t internalFlashArea[] =
+    {
+    		{PAL_INTERNAL_FLASH_SECTION_1_ADDRESS, PAL_INTERNAL_FLASH_SECTION_1_SIZE},
+    		{PAL_INTERNAL_FLASH_SECTION_2_ADDRESS, PAL_INTERNAL_FLASH_SECTION_2_SIZE}
+    };
+
+	PAL_VALIDATE_CONDITION_WITH_ERROR ((data == NULL), PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED)
+	
+	data->address = internalFlashArea[section].address;
+    data->size = internalFlashArea[section].size;
+	return ret;
+}
+
+#endif //(PAL_USE_INTERNAL_FLASH)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/TLS/pal_TLS.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,591 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#include "pal.h"
+#include "pal_plat_TLS.h"
+#include "sotp.h"
+
+PAL_PRIVATE uint8_t g_storedCertSerial[PAL_CERT_ID_SIZE] __attribute__ ((aligned(4))) = {0};
+PAL_PRIVATE bool g_trustedServerValid = false;
+PAL_PRIVATE palMutexID_t g_palTLSHandshakeMutex = NULLPTR;
+
+typedef struct palTLSService
+{
+	bool retryHandShake;
+	uint64_t serverTime;
+	palTLSHandle_t platTlsHandle;
+}palTLSService_t;
+
+typedef struct palTLSConfService
+{
+	bool trustedTimeServer;
+	palTLSConfHandle_t platTlsConfHandle;
+}palTLSConfService_t;
+
+palStatus_t pal_initTLSLibrary(void)
+{
+	palStatus_t status = PAL_SUCCESS;
+	status = pal_osMutexCreate(&g_palTLSHandshakeMutex);
+    if(PAL_SUCCESS != status)
+	{
+		PAL_LOG(ERR, "Failed to Create TLS handshake Mutex error: %" PRId32 ".", status);
+	}
+	else
+	{
+		status = pal_plat_initTLSLibrary();
+	}
+	return status;
+}
+
+palStatus_t pal_cleanupTLS(void)
+{
+	palStatus_t status = PAL_SUCCESS;
+	status = pal_osMutexDelete(&g_palTLSHandshakeMutex);
+    if(PAL_SUCCESS != status)
+	{
+		PAL_LOG(ERR, "Failed to Delete TLS handshake Mutex error: %" PRId32 ".", status);
+	}
+	status = pal_plat_cleanupTLS();
+	return status;
+}
+
+
+palStatus_t pal_initTLS(palTLSConfHandle_t palTLSConf, palTLSHandle_t* palTLSHandle)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palStatus_t mutexStatus = PAL_SUCCESS;
+	palTLSConfService_t* palTLSConfCtx = (palTLSConfService_t*)palTLSConf;
+	palTLSService_t* palTLSCtx = NULL;
+
+	PAL_VALIDATE_ARGUMENTS ((NULLPTR == palTLSConf || NULLPTR == palTLSHandle));
+
+	mutexStatus = pal_osMutexWait(g_palTLSHandshakeMutex, PAL_RTOS_WAIT_FOREVER);
+	if (PAL_SUCCESS != mutexStatus)
+	{
+		PAL_LOG(ERR, "Failed to get TLS context init Mutex error: %" PRId32 ".", mutexStatus);
+		goto finish;
+	}
+
+	palTLSCtx = (palTLSService_t*)malloc(sizeof(palTLSService_t));
+	if (NULL == palTLSCtx)
+	{
+		status = PAL_ERR_NO_MEMORY;
+		goto finish;
+	}
+	status = pal_plat_initTLS(palTLSConfCtx->platTlsConfHandle, &palTLSCtx->platTlsHandle);
+	if (PAL_SUCCESS == status)
+	{
+		*palTLSHandle = (palTLSHandle_t)palTLSCtx;
+	}
+	
+	memset(g_storedCertSerial, 0, sizeof(g_storedCertSerial));
+	g_trustedServerValid = false;
+	palTLSCtx->retryHandShake = false;
+
+finish:
+	if (PAL_SUCCESS == mutexStatus)
+	{
+		mutexStatus = pal_osMutexRelease(g_palTLSHandshakeMutex);
+		if (PAL_SUCCESS != mutexStatus)
+		{
+			PAL_LOG(ERR, "Failed to release TLS context init Mutex error: %" PRId32 ".", mutexStatus);
+		}
+	}
+	
+	if (PAL_SUCCESS == status)
+	{
+		status = mutexStatus;
+	}
+
+	if (PAL_SUCCESS != status)
+	{
+		free(palTLSCtx);
+	}
+	return status;
+}
+
+
+palStatus_t pal_freeTLS(palTLSHandle_t* palTLSHandle)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palStatus_t mutexStatus = PAL_SUCCESS;
+
+	palTLSService_t* palTLSCtx = NULL;
+
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSHandle || NULLPTR == *palTLSHandle);
+
+	mutexStatus = pal_osMutexWait(g_palTLSHandshakeMutex, PAL_RTOS_WAIT_FOREVER);
+	if (PAL_SUCCESS != mutexStatus)
+	{
+		PAL_LOG(ERR, "Failed to get TLS context init Mutex error: %" PRId32 ".", mutexStatus);
+		goto finish;
+	}
+
+	palTLSCtx = (palTLSService_t*)*palTLSHandle;
+	status = pal_plat_freeTLS(&palTLSCtx->platTlsHandle);
+	if (PAL_SUCCESS == status)
+	{
+		free(palTLSCtx);
+		*palTLSHandle = NULLPTR;
+	}
+
+	mutexStatus = pal_osMutexRelease(g_palTLSHandshakeMutex);
+	if (PAL_SUCCESS != mutexStatus)
+	{
+		PAL_LOG(ERR, "Failed to release TLS context init Mutex error: %" PRId32 ".", mutexStatus);
+	}
+finish:
+	if (PAL_SUCCESS == status)
+	{
+		status = mutexStatus;
+	}
+	return status;
+}
+
+
+palStatus_t pal_initTLSConfiguration(palTLSConfHandle_t* palTLSConf, palTLSTransportMode_t transportationMode)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConfService_t* palTLSConfCtx = NULL;
+
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConf);
+
+
+	palTLSConfCtx = (palTLSConfService_t*)malloc(sizeof(palTLSConfService_t));
+	if (NULL == palTLSConfCtx)
+	{
+		status = PAL_ERR_NO_MEMORY;
+		goto finish;
+	}
+	status = pal_plat_initTLSConf(&palTLSConfCtx->platTlsConfHandle, transportationMode, PAL_TLS_IS_CLIENT);
+	if (PAL_SUCCESS != status)
+	{
+		goto finish;
+	}
+	
+	status = pal_plat_setAuthenticationMode(palTLSConfCtx->platTlsConfHandle, PAL_TLS_VERIFY_OPTIONAL);
+	if (PAL_SUCCESS != status)
+	{
+		goto finish;
+	}
+#if (PAL_TLS_CIPHER_SUITE & PAL_TLS_PSK_WITH_AES_128_CBC_SHA256_SUITE)
+	status = pal_plat_setCipherSuites(palTLSConfCtx->platTlsConfHandle, PAL_TLS_PSK_WITH_AES_128_CBC_SHA256);
+#elif (PAL_TLS_CIPHER_SUITE & PAL_TLS_PSK_WITH_AES_128_CCM_8_SUITE)
+	status = pal_plat_setCipherSuites(palTLSConfCtx->platTlsConfHandle, PAL_TLS_PSK_WITH_AES_128_CCM_8);
+#elif (PAL_TLS_CIPHER_SUITE & PAL_TLS_PSK_WITH_AES_256_CCM_8_SUITE)
+	status = pal_plat_setCipherSuites(palTLSConfCtx->platTlsConfHandle, PAL_TLS_PSK_WITH_AES_256_CCM_8);
+#elif (PAL_TLS_CIPHER_SUITE & PAL_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8_SUITE)
+	status = pal_plat_setCipherSuites(palTLSConfCtx->platTlsConfHandle, PAL_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+#elif (PAL_TLS_CIPHER_SUITE & PAL_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_SUITE)
+	status = pal_plat_setCipherSuites(palTLSConfCtx->platTlsConfHandle, PAL_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+#elif (PAL_TLS_CIPHER_SUITE & PAL_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_SUITE)
+	status = pal_plat_setCipherSuites(palTLSConfCtx->platTlsConfHandle, PAL_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
+#elif (PAL_TLS_CIPHER_SUITE & PAL_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256_SUITE)
+    status = pal_plat_setCipherSuites(palTLSConfCtx->platTlsConfHandle, PAL_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256);
+#elif (PAL_TLS_CIPHER_SUITE & PAL_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256_SUITE)
+    status = pal_plat_setCipherSuites(palTLSConfCtx->platTlsConfHandle, PAL_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256);
+#else
+	#error : No CipherSuite was defined!
+#endif
+	if (PAL_SUCCESS != status)
+	{
+		goto finish;
+	}
+	palTLSConfCtx->trustedTimeServer = false;
+	*palTLSConf = (palTLSHandle_t)palTLSConfCtx;
+finish:
+	if (PAL_SUCCESS != status)
+	{
+		free(palTLSConfCtx);
+	}
+	return status;
+}
+
+
+palStatus_t pal_tlsConfigurationFree(palTLSConfHandle_t* palTLSConf)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConfService_t* palTLSConfCtx = NULL;
+
+	PAL_VALIDATE_ARGUMENTS ((NULLPTR == palTLSConf || NULLPTR == *palTLSConf));
+
+	palTLSConfCtx = (palTLSConfService_t*)*palTLSConf;
+	status = pal_plat_tlsConfigurationFree(&palTLSConfCtx->platTlsConfHandle);
+	if (PAL_SUCCESS == status)
+	{
+		free(palTLSConfCtx);
+		*palTLSConf = NULLPTR;
+	}
+	return status;
+}
+
+
+palStatus_t pal_addEntropySource(palEntropySource_f entropyCallback)
+{
+	palStatus_t status = PAL_SUCCESS;
+	status = pal_plat_addEntropySource(entropyCallback);
+	return status;
+}
+
+palStatus_t pal_setOwnCertAndPrivateKey(palTLSConfHandle_t palTLSConf, palX509_t* ownCert, palPrivateKey_t* privateKey)
+{
+#if (PAL_ENABLE_X509 == 1)
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConfService_t* palTLSConfCtx =  (palTLSConfService_t*)palTLSConf;
+
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConf);
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConfCtx->platTlsConfHandle || NULL == ownCert || NULL == privateKey);
+
+	status = pal_plat_setOwnCertAndPrivateKey(palTLSConfCtx->platTlsConfHandle, ownCert, privateKey);    
+	return status;
+#else
+	return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_setOwnCertChain(palTLSConfHandle_t palTLSConf, palX509_t* ownCert)
+{
+#if (PAL_ENABLE_X509 == 1)
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConfService_t* palTLSConfCtx =  (palTLSConfService_t*)palTLSConf;
+
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConf);
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConfCtx->platTlsConfHandle || NULL == ownCert);
+
+	status = pal_plat_setOwnCertChain(palTLSConfCtx->platTlsConfHandle, ownCert);
+	return status;
+#else
+	return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_setOwnPrivateKey(palTLSConfHandle_t palTLSConf, palPrivateKey_t* privateKey)
+{
+#if (PAL_ENABLE_X509 == 1)
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConfService_t* palTLSConfCtx =  (palTLSConfService_t*)palTLSConf;
+
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConf);
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConfCtx->platTlsConfHandle || NULL == privateKey);
+
+	status = pal_plat_setOwnPrivateKey(palTLSConfCtx->platTlsConfHandle, privateKey);
+	return status;
+#else
+	return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+palStatus_t pal_setCAChain(palTLSConfHandle_t palTLSConf, palX509_t* caChain, palX509CRL_t* caCRL)
+{
+#if (PAL_ENABLE_X509 == 1)
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConfService_t* palTLSConfCtx = (palTLSConfService_t*)palTLSConf;
+	palX509Handle_t x509Ctx = NULLPTR;
+
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConf);
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConfCtx->platTlsConfHandle || NULL == caChain);
+
+
+	status = pal_plat_setCAChain(palTLSConfCtx->platTlsConfHandle, caChain, caCRL);
+#if PAL_USE_SECURE_TIME
+	if (PAL_SUCCESS == status)
+	{
+		uint8_t certID[PAL_CERT_ID_SIZE] = {0};	
+		size_t actualCertIDLen = 0;
+		
+		status = pal_x509Initiate(&x509Ctx);
+		if (PAL_SUCCESS != status)
+		{
+			goto finish;
+		}
+		
+		status = pal_x509CertParse(x509Ctx, caChain->buffer, caChain->size);
+		if (PAL_SUCCESS != status)
+		{
+			goto finish;
+		}
+		
+		status = pal_x509CertGetAttribute(x509Ctx, PAL_X509_CERT_ID_ATTR, certID, sizeof(certID), &actualCertIDLen);
+		if (PAL_SUCCESS != status)
+		{
+			goto finish;
+		}
+
+		if (!g_trustedServerValid)
+		{
+			sotp_result_e sotpRes;
+			uint16_t actualLenBytes = 0;
+			
+			sotpRes = sotp_get(SOTP_TYPE_TRUSTED_TIME_SRV_ID, (uint16_t)sizeof(g_storedCertSerial), (uint32_t*)g_storedCertSerial, &actualLenBytes);
+			if (SOTP_SUCCESS == sotpRes)
+			{
+				g_trustedServerValid = true;
+			}
+		}
+
+		if ( (sizeof(g_storedCertSerial) == actualCertIDLen) && (0 == memcmp(certID, g_storedCertSerial, sizeof(g_storedCertSerial))))
+		{
+			palTLSConfCtx->trustedTimeServer = true;
+		}
+	}
+	finish:
+#endif //PAL_USE_SECURE_TIME
+	if (NULLPTR != x509Ctx)
+	{
+		pal_x509Free(&x509Ctx);
+	}
+	return status;
+#else
+	return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+
+palStatus_t pal_setPSK(palTLSConfHandle_t palTLSConf, const unsigned char *identity, uint32_t maxIdentityLenInBytes, const unsigned char *psk, uint32_t maxPskLenInBytes)
+{
+#if (PAL_ENABLE_PSK == 1)
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConfService_t* palTLSConfCtx = (palTLSConfService_t*)palTLSConf;
+
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConf);
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConfCtx->platTlsConfHandle || NULL == identity || NULL == psk);
+
+
+	status = pal_plat_setPSK(palTLSConfCtx->platTlsConfHandle, identity, maxIdentityLenInBytes, psk, maxPskLenInBytes);
+	return status;
+#else
+	return PAL_ERR_NOT_SUPPORTED;
+#endif
+}
+
+
+palStatus_t pal_tlsSetSocket(palTLSConfHandle_t palTLSConf, palTLSSocket_t* socket)
+{	//palSocket_t depend on the library (socket or bio pointer)
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConfService_t* palTLSConfCtx = (palTLSConfService_t*)palTLSConf;
+
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConf);
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConfCtx->platTlsConfHandle || NULL == socket);
+
+	status = pal_plat_tlsSetSocket(palTLSConfCtx->platTlsConfHandle, socket);
+	return status;
+}
+
+#if PAL_USE_SECURE_TIME
+PAL_PRIVATE palStatus_t pal_updateTime(uint64_t serverTime, bool trustedTimeServer)
+{
+	palStatus_t status = PAL_SUCCESS;
+	if (trustedTimeServer)
+	{
+		status = pal_osSetStrongTime(serverTime);
+		if (PAL_SUCCESS != status)
+		{
+			PAL_LOG(DBG, "Setting strong time failed! return code %" PRId32 ".", status);
+		}
+	}
+	else
+	{
+		status = pal_osSetWeakTime(serverTime);
+		if (PAL_SUCCESS != status)
+		{
+			PAL_LOG(DBG, "Setting weak time failed! return code %" PRId32 ".", status);
+		}
+	}
+	return status;
+}
+#endif //PAL_USE_SECURE_TIME
+
+palStatus_t pal_handShake(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSConf)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConfService_t* palTLSConfCtx = (palTLSConfService_t*)palTLSConf;
+	palTLSService_t* palTLSCtx = (palTLSService_t*)palTLSHandle;
+
+	PAL_VALIDATE_ARGUMENTS((NULLPTR == palTLSConfCtx || NULLPTR == palTLSCtx));
+	PAL_VALIDATE_ARGUMENTS((NULLPTR == palTLSCtx->platTlsHandle || NULLPTR == palTLSConfCtx->platTlsConfHandle));
+
+	status = pal_plat_sslSetup(palTLSCtx->platTlsHandle, palTLSConfCtx->platTlsConfHandle);
+	if (PAL_SUCCESS != status)
+	{
+		goto finish;
+	}
+
+	if (!palTLSCtx->retryHandShake)
+	{
+		status = pal_plat_handShake(palTLSCtx->platTlsHandle, &palTLSCtx->serverTime);
+		if (PAL_SUCCESS == status)
+		{
+			int32_t verifyResult = 0;
+			status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult);
+#if PAL_USE_SECURE_TIME
+			if (PAL_ERR_X509_CERT_VERIFY_FAILED == status)
+			{
+				if ((PAL_ERR_X509_BADCERT_FUTURE & verifyResult) || ((true == palTLSConfCtx->trustedTimeServer) && (PAL_ERR_X509_BADCERT_EXPIRED & verifyResult)))
+				{
+					PAL_LOG(DBG, "SSL EXPIRED OR FUTURE - retry");
+					palTLSCtx->retryHandShake = true;
+					status = PAL_SUCCESS;
+				}
+				else if (PAL_SUCCESS != status)
+				{
+					status = PAL_ERR_X509_CERT_VERIFY_FAILED;
+					palTLSCtx->serverTime = 0;
+				}
+			}
+#else 
+			if (PAL_SUCCESS != status)
+			{
+				status = PAL_ERR_X509_CERT_VERIFY_FAILED;
+				palTLSCtx->serverTime = 0;
+			}
+#endif //PAL_USE_SECURE_TIME
+		}
+	}
+#if PAL_USE_SECURE_TIME
+	if ((PAL_SUCCESS == status) && (palTLSCtx->retryHandShake))
+	{
+		PAL_LOG(DBG, "SSL START RENEGOTIATE");
+		if (!palTLSConfCtx->trustedTimeServer) //! if we are not proccessing handshake with the time trusted server we 
+		{									  //! will use PAL_TLS_VERIFY_REQUIRED authentication mode
+			status = pal_plat_setAuthenticationMode(palTLSConfCtx->platTlsConfHandle, PAL_TLS_VERIFY_REQUIRED);
+			if (PAL_SUCCESS != status)
+			{
+				goto finish;
+			}
+		}
+		status = pal_plat_renegotiate(palTLSCtx->platTlsHandle, palTLSCtx->serverTime);
+		if (PAL_SUCCESS == status)
+		{
+			int32_t verifyResult = 0;
+			status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult);
+			if ((palTLSConfCtx->trustedTimeServer) && 
+				((PAL_ERR_X509_CERT_VERIFY_FAILED == status) && ((PAL_ERR_X509_BADCERT_EXPIRED & verifyResult) || (PAL_ERR_X509_BADCERT_FUTURE & verifyResult))))
+			{
+				status = PAL_SUCCESS;
+			}
+		}
+	}
+
+	if (PAL_SUCCESS == status)
+	{
+		//! We ignore the pal_updateTime() result, because it should not cause a failure to the handshake process.
+		//! Logs are printed in the pal_updateTime() function in case of failure.
+		pal_updateTime(palTLSCtx->serverTime, palTLSConfCtx->trustedTimeServer);
+	}
+#endif //PAL_USE_SECURE_TIME
+finish:
+	return status;
+}
+
+
+palStatus_t pal_sslGetVerifyResultExtended(palTLSHandle_t palTLSHandle, int32_t* verifyResult)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSService_t* palTLSCtx = NULL;
+	
+	PAL_VALIDATE_ARGUMENTS((NULLPTR == palTLSHandle) || (NULL == verifyResult));
+
+	palTLSCtx = (palTLSService_t*)palTLSHandle;
+	PAL_VALIDATE_ARGUMENTS(NULLPTR == palTLSCtx->platTlsHandle);
+
+	status = pal_plat_sslGetVerifyResultExtended(palTLSCtx->platTlsHandle, verifyResult);
+	if (0 != *verifyResult)
+    {
+        status = PAL_ERR_X509_CERT_VERIFY_FAILED;
+		*verifyResult = *verifyResult ^ PAL_ERR_MODULE_BITMASK_BASE; //! in order to turn off the MSB bit.
+    }
+
+	return status;
+}
+
+
+palStatus_t pal_sslGetVerifyResult(palTLSHandle_t palTLSHandle)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSService_t* palTLSCtx = NULL;
+	int32_t verifyResult = 0;
+
+	PAL_VALIDATE_ARGUMENTS(NULLPTR == palTLSHandle);
+
+	palTLSCtx = (palTLSService_t*)palTLSHandle;
+	PAL_VALIDATE_ARGUMENTS(NULLPTR == palTLSCtx->platTlsHandle);
+
+	status = pal_plat_sslGetVerifyResultExtended(palTLSCtx->platTlsHandle, &verifyResult);
+	return status;
+}
+
+
+palStatus_t pal_setHandShakeTimeOut(palTLSConfHandle_t palTLSConf, uint32_t timeoutInMilliSec)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConfService_t* palTLSConfCtx =  (palTLSConfService_t*)palTLSConf;
+
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSConfCtx || 0 == timeoutInMilliSec);
+
+	status = pal_plat_setHandShakeTimeOut(palTLSConfCtx->platTlsConfHandle, timeoutInMilliSec);
+	return status;
+}
+
+
+palStatus_t pal_sslRead(palTLSHandle_t palTLSHandle, void *buffer, uint32_t len, uint32_t* actualLen)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSService_t* palTLSCtx = (palTLSService_t*)palTLSHandle;
+	
+	PAL_VALIDATE_ARGUMENTS (NULLPTR == palTLSHandle);
+	PAL_VALIDATE_ARGUMENTS ((NULLPTR == palTLSCtx->platTlsHandle || NULL == buffer || NULL == actualLen));
+
+	status = pal_plat_sslRead(palTLSCtx->platTlsHandle, buffer, len, actualLen);
+	return status;
+}
+
+
+palStatus_t pal_sslWrite(palTLSHandle_t palTLSHandle, const void *buffer, uint32_t len, uint32_t *bytesWritten)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSService_t* palTLSCtx = (palTLSService_t*)palTLSHandle;
+	
+	PAL_VALIDATE_ARGUMENTS((NULLPTR == palTLSHandle || NULL == buffer || NULL == bytesWritten));
+
+	status = pal_plat_sslWrite(palTLSCtx->platTlsHandle, buffer, len, bytesWritten);
+	return status;
+}
+
+palStatus_t pal_sslDebugging(uint8_t turnOn)
+{
+    return PAL_ERR_NOT_SUPPORTED;
+}
+
+
+/*! Turn on/off the TLS library debugging for the given configuration handle. The logs are sent via the mbedTrace.
+*   In case of release mode, an error will be returned.
+*
+* @param[in] palTLSConf : the TLS confuguraiton to modify
+* @param[in] turnOn: if greater than 0 turn on debugging, otherwise turn it off
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_sslSetDebugging(palTLSConfHandle_t palTLSConf, uint8_t turnOn)
+{
+    palStatus_t status = PAL_SUCCESS;
+
+    palTLSConfService_t* palTLSConfCtx = (palTLSConfService_t*)palTLSConf;
+
+    status = pal_plat_sslSetDebugging(palTLSConfCtx->platTlsConfHandle, turnOn);
+    return status;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Modules/Update/pal_update.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,710 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <pal.h>
+#include "pal_plat_update.h"
+#include "pal_update.h"
+#include "pal_macros.h"
+
+PAL_PRIVATE uint8_t palUpdateInitFlag = 0;
+
+#define PAL_KILOBYTE 1024
+
+#ifndef PAL_UPDATE_IMAGE_LOCATION
+#error "Please definee PAL_UPDATE_IMAGE_LOCATION to UPDATE_USE_FLASH (value 1) or UPDATE_USE_FS(2)"
+#endif
+
+#if (PAL_UPDATE_IMAGE_LOCATION == PAL_UPDATE_USE_FS)
+#define SEEK_POS_INVALID            0xFFFFFFFF
+PAL_PRIVATE FirmwareHeader_t pal_pi_mbed_firmware_header;
+PAL_PRIVATE palImageSignalEvent_t g_palUpdateServiceCBfunc;
+PAL_PRIVATE palFileDescriptor_t image_file[IMAGE_COUNT_MAX];
+PAL_PRIVATE bool last_read_nwrite[IMAGE_COUNT_MAX];
+PAL_PRIVATE uint32_t last_seek_pos[IMAGE_COUNT_MAX];
+PAL_PRIVATE bool valid_index(uint32_t index);
+PAL_PRIVATE size_t safe_read(uint32_t index, size_t offset, uint8_t *buffer, uint32_t size);
+PAL_PRIVATE size_t safe_write(uint32_t index, size_t offset, const uint8_t *buffer, uint32_t size);
+PAL_PRIVATE bool open_if_necessary(uint32_t index, bool read_nwrite);
+PAL_PRIVATE bool seek_if_necessary(uint32_t index, size_t offset, bool read_nwrite);
+PAL_PRIVATE bool close_if_necessary(uint32_t index);
+PAL_PRIVATE const char *image_path_alloc_from_index(uint32_t index);
+PAL_PRIVATE const char *header_path_alloc_from_index(uint32_t index);
+PAL_PRIVATE const char *path_join_and_alloc(const char * const * path_list);
+
+PAL_PRIVATE palStatus_t pal_set_fw_header(palImageId_t index, FirmwareHeader_t *headerP);
+PAL_PRIVATE uint32_t internal_crc32(const uint8_t* buffer, uint32_t length);
+
+
+char* pal_imageGetFolder(void)
+{
+    return PAL_UPDATE_FIRMWARE_DIR;
+}
+
+
+palStatus_t pal_imageInitAPI(palImageSignalEvent_t CBfunction)
+{
+    palStatus_t status = PAL_SUCCESS;
+    //printf("pal_imageInitAPI\r\n");
+    PAL_MODULE_INIT(palUpdateInitFlag);
+
+    // create absolute path.
+
+
+    pal_fsMkDir(PAL_UPDATE_FIRMWARE_DIR);
+
+    g_palUpdateServiceCBfunc = CBfunction;
+    g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_INIT);
+    return status;
+}
+
+palStatus_t pal_imageDeInit(void)
+{
+    //printf("pal_plat_imageDeInit\r\n");
+    PAL_MODULE_DEINIT(palUpdateInitFlag);
+
+    for (int i = 0; i < IMAGE_COUNT_MAX; i++)
+    {
+        close_if_necessary(i);
+    }
+
+    return PAL_SUCCESS;
+}
+
+palStatus_t pal_imagePrepare(palImageId_t imageId, palImageHeaderDeails_t *headerDetails)
+{
+    //printf("pal_imagePrepare(imageId=%lu, size=%lu)\r\n", imageId, headerDetails->imageSize);
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t ret;
+    uint8_t *buffer;
+
+    // write the image header to file system
+    memset(&pal_pi_mbed_firmware_header,0,sizeof(pal_pi_mbed_firmware_header));
+    pal_pi_mbed_firmware_header.totalSize = headerDetails->imageSize;
+    pal_pi_mbed_firmware_header.magic = FIRMWARE_HEADER_MAGIC;
+    pal_pi_mbed_firmware_header.version = FIRMWARE_HEADER_VERSION;
+    pal_pi_mbed_firmware_header.firmwareVersion = headerDetails->version;
+    memcpy(pal_pi_mbed_firmware_header.firmwareSHA256,headerDetails->hash.buffer,SIZEOF_SHA256);
+
+    pal_pi_mbed_firmware_header.checksum = internal_crc32((uint8_t *) &pal_pi_mbed_firmware_header,
+                                                          sizeof(pal_pi_mbed_firmware_header));
+
+    ret = pal_set_fw_header(imageId, &pal_pi_mbed_firmware_header);
+
+    /*Check that the size of the image is valid and reserve space for it*/
+    if (ret == PAL_SUCCESS)
+    {
+        buffer = malloc(PAL_KILOBYTE);
+        if (NULL != buffer)
+        {
+        	uint32_t writeCounter = 0;
+			memset(buffer,0,PAL_KILOBYTE);
+			while(writeCounter <= headerDetails->imageSize)
+			{
+                int written = safe_write(imageId,0,buffer,PAL_KILOBYTE);
+                writeCounter+=PAL_KILOBYTE;
+                if (PAL_KILOBYTE != written)
+                {
+                    ret = PAL_ERR_UPDATE_ERROR;
+                }
+			}
+			if ((PAL_SUCCESS == ret) && (writeCounter < headerDetails->imageSize))
+			{
+				//writing the last bytes
+                int written = safe_write(imageId,0,buffer,(headerDetails->imageSize - writeCounter));
+                if ((headerDetails->imageSize - writeCounter) != written)
+                {
+                    ret = PAL_ERR_UPDATE_ERROR;
+                }
+			}
+			free(buffer);
+			if (PAL_SUCCESS == ret)
+			{
+				ret = pal_fsFseek(&(image_file[imageId]),0,PAL_FS_OFFSET_SEEKSET);
+			}
+			else
+			{
+				pal_fsUnlink(image_path_alloc_from_index(imageId));
+			}
+        }
+        else
+        {
+        	ret = PAL_ERR_NO_MEMORY;
+        }
+    }
+    if (PAL_SUCCESS == ret)
+    {
+    	g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_PREPARE);
+    }
+    else
+    {
+    	g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_ERROR);
+    }
+
+
+    return ret;
+}
+
+palStatus_t pal_imageWrite(palImageId_t imageId, size_t offset, palConstBuffer_t *chunk)
+{
+    //printf("pal_imageWrite(imageId=%lu, offset=%lu)\r\n", imageId, offset);
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t ret = PAL_ERR_UPDATE_ERROR;
+
+    int xfer_size_or_error = safe_write(imageId, offset, chunk->buffer, chunk->bufferLength);
+    if ((xfer_size_or_error < 0) || ((uint32_t)xfer_size_or_error != chunk->bufferLength))
+    {
+        //printf("Error writing to file\r\n");
+    }
+    else
+    {
+        ret = PAL_SUCCESS;
+        g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_WRITE);
+    }
+
+    return ret;
+}
+
+palStatus_t  pal_imageFinalize(palImageId_t imageId)
+{
+    //printf("pal_imageFinalize(id=%i)\r\n", imageId);
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t ret = PAL_ERR_UPDATE_ERROR;
+
+    if (close_if_necessary(imageId))
+    {
+        ret = PAL_SUCCESS;
+        g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_FINALIZE);
+    }
+
+    return ret;
+}
+
+palStatus_t pal_imageGetDirectMemoryAccess(palImageId_t imageId, void** imagePtr, size_t* imageSizeInBytes)
+{
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_plat_imageGetDirectMemAccess(imageId, imagePtr, imageSizeInBytes);
+    return status;
+}
+
+palStatus_t pal_imageReadToBuffer(palImageId_t imageId, size_t offset, palBuffer_t *chunk)
+{
+    //printf("pal_imageReadToBuffer(imageId=%lu, offset=%lu)\r\n", imageId, offset);
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t ret = PAL_ERR_UPDATE_ERROR;
+
+    int xfer_size_or_error = safe_read(imageId, offset, chunk->buffer, chunk->maxBufferLength);
+    if (xfer_size_or_error < 0)
+    {
+        //printf("Error reading from file\r\n");
+    }
+    else
+    {
+        chunk->bufferLength = xfer_size_or_error;
+        g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_READTOBUFFER);
+        ret = PAL_SUCCESS;
+    }
+
+    return ret;
+}
+
+palStatus_t pal_imageActivate(palImageId_t imageId)
+{
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_plat_imageActivate(imageId);
+    return status;
+}
+
+palStatus_t pal_imageGetFirmwareHeaderData(palImageId_t imageId, palBuffer_t *headerData)
+{
+		palStatus_t ret = PAL_SUCCESS;
+		palFileDescriptor_t file = 0;
+		size_t xfer_size;
+        if (NULL == headerData)
+        {
+            return PAL_ERR_NULL_POINTER;
+        }
+		if (headerData->maxBufferLength < sizeof(palFirmwareHeader_t))
+		{
+			PAL_LOG(ERR, "Firmware header buffer size is too small(is %" PRIu32 " needs to be at least %zu)\r\n"
+					    ,headerData->maxBufferLength, sizeof(palFirmwareHeader_t));
+			return PAL_ERR_INVALID_ARGUMENT;
+		}
+
+		const char *file_path = header_path_alloc_from_index(imageId);
+		if (file_path)
+		{
+			ret = pal_fsFopen(file_path, PAL_FS_FLAG_READONLY, &file);
+			if (ret == PAL_SUCCESS)
+			{
+				ret = pal_fsFread(&file, headerData->buffer, sizeof(palFirmwareHeader_t), &xfer_size);
+				if (PAL_SUCCESS == ret)
+				{
+					headerData->bufferLength = xfer_size;
+				}
+				pal_fsFclose(&file);
+			}
+			free((void*)file_path);
+		}
+		else
+		{
+			ret = PAL_ERR_NO_MEMORY;
+		}
+	    return ret;
+}
+
+palStatus_t pal_imageGetActiveHash(palBuffer_t *hash)
+{
+    //printf("pal_imageGetActiveHash\r\n");
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t ret;
+
+    if (hash->maxBufferLength < SIZEOF_SHA256)
+    {
+        ret = PAL_ERR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+    hash->bufferLength = 0;
+    memset(hash->buffer, 0, hash->maxBufferLength);
+
+    ret = pal_plat_imageGetActiveHash(hash);
+    if (ret == PAL_SUCCESS)
+    {
+        g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_GETACTIVEHASH);
+    }
+
+exit:
+    return ret;
+}
+
+palStatus_t pal_imageGetActiveVersion(palBuffer_t *version)
+{
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_plat_imageGetActiveVersion(version);
+    return status;
+}
+
+palStatus_t pal_imageWriteDataToMemory(palImagePlatformData_t dataId, const palConstBuffer_t * const dataBuffer)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    // this switch is for further use when there will be more options
+    switch(dataId)
+    {
+    case PAL_IMAGE_DATA_HASH:
+        status = pal_plat_imageWriteHashToMemory(dataBuffer);
+        break;
+    default:
+        {
+            PAL_LOG(ERR, "Update image write to memory error");
+            status = PAL_ERR_GENERIC_FAILURE;
+        }
+    }
+    return status;
+}
+
+PAL_PRIVATE palStatus_t pal_set_fw_header(palImageId_t index, FirmwareHeader_t *headerP)
+{
+    palStatus_t ret;
+    palFileDescriptor_t file = 0;
+    size_t xfer_size;
+
+    const char *file_path = header_path_alloc_from_index(index);
+    ret = pal_fsFopen(file_path, PAL_FS_FLAG_READWRITETRUNC, &file);
+    if (ret != PAL_SUCCESS)
+    {
+        //printf("pal_fsFopen returned 0x%x\r\n", ret);
+        goto exit;
+    }
+
+    ret = pal_fsFwrite(&file, headerP, sizeof(FirmwareHeader_t), &xfer_size);
+    if (ret != PAL_SUCCESS)
+    {
+        //printf("pal_fsFread returned 0x%x\r\n", ret);
+        goto exit;
+    }
+    else if (xfer_size != sizeof(FirmwareHeader_t))
+    {
+        //printf("Size written %lu expected %lu\r\n", xfer_size, sizeof(FirmwareHeader_t));
+        goto exit;
+    }
+
+    ret = PAL_SUCCESS;
+
+exit:
+    if (file != 0)
+    {
+        ret = pal_fsFclose(&file);
+        if (ret != PAL_SUCCESS)
+        {
+            //printf("Error closing file %s\r\n", file_path);
+            ret = PAL_ERR_UPDATE_ERROR;
+        }
+    }
+    free((void*)file_path);
+
+    return ret;
+}
+
+/**
+ * @brief Bitwise CRC32 calculation
+ * @details Modified from ARM Keil code:
+ *          http://www.keil.com/appnotes/docs/apnt_277.asp
+ *
+ * @param buffer Input byte array.
+ * @param length Number of bytes in array.
+ *
+ * @return CRC32
+ */
+PAL_PRIVATE uint32_t internal_crc32(const uint8_t* buffer,
+                                    uint32_t length)
+{
+    const uint8_t* current = buffer;
+    uint32_t crc = 0xFFFFFFFF;
+
+    while (length--)
+    {
+        crc ^= *current++;
+
+        for (uint32_t counter = 0; counter < 8; counter++)
+        {
+            if (crc & 1)
+            {
+                crc = (crc >> 1) ^ 0xEDB88320;
+            }
+            else
+            {
+                crc = crc >> 1;
+            }
+        }
+    }
+
+    return (crc ^ 0xFFFFFFFF);
+}
+
+PAL_PRIVATE bool valid_index(uint32_t index)
+{
+    return (index < IMAGE_COUNT_MAX);
+}
+
+PAL_PRIVATE size_t safe_read(uint32_t index, size_t offset, uint8_t *buffer, uint32_t size)
+{
+    const bool read_nwrite = true;
+    size_t xfer_size = 0;
+    palStatus_t status;
+
+    if ((!valid_index(index)) || (!open_if_necessary(index, read_nwrite)) || (!seek_if_necessary(index, offset, read_nwrite)))
+    {
+        return 0;
+    }
+
+    status = pal_fsFread(&(image_file[index]), buffer, size, &xfer_size);
+    if (status == PAL_SUCCESS)
+    {
+    	last_read_nwrite[index] = read_nwrite;
+		last_seek_pos[index] += xfer_size;
+    }
+
+    return xfer_size;
+}
+
+PAL_PRIVATE size_t safe_write(uint32_t index, size_t offset, const uint8_t *buffer, uint32_t size)
+{
+    const bool read_nwrite = false;
+    size_t xfer_size = 0;
+    palStatus_t status;
+    if ((!valid_index(index)) ||  (!open_if_necessary(index, read_nwrite)) ||  (!seek_if_necessary(index, offset, read_nwrite)))
+    {
+        return 0;
+    }
+    status = pal_fsFseek(&(image_file[index]), offset, PAL_FS_OFFSET_SEEKSET);
+    if (status == PAL_SUCCESS)
+    {
+    status  = pal_fsFwrite(&(image_file[index]), buffer, size, &xfer_size);
+		if (status == PAL_SUCCESS)
+		{
+			last_read_nwrite[index] = read_nwrite;
+			last_seek_pos[index] += xfer_size;
+
+			if (size != xfer_size)
+			{
+				//printf("WRONG SIZE expected %u got %lu\r\n", size, xfer_size);
+				return 0;
+			}
+
+		}
+    }
+
+    return xfer_size;
+}
+
+PAL_PRIVATE bool open_if_necessary(uint32_t index, bool read_nwrite)
+{
+    if (!valid_index(index))
+    {
+        return false;
+    }
+    if ( (unsigned int*)image_file[index] == NULL )
+    {
+        const char *file_path = image_path_alloc_from_index(index);
+        pal_fsFileMode_t mode = read_nwrite ? PAL_FS_FLAG_READWRITE : PAL_FS_FLAG_READWRITETRUNC;
+
+        palStatus_t ret = pal_fsFopen(file_path, mode, &(image_file[index]));
+        free((void*)file_path);
+        last_seek_pos[index] = 0;
+        if (ret != PAL_SUCCESS)
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+PAL_PRIVATE bool seek_if_necessary(uint32_t index, size_t offset, bool read_nwrite)
+{
+    if (!valid_index(index))
+    {
+        return false;
+    }
+
+    if ((read_nwrite != last_read_nwrite[index]) ||
+        (offset != last_seek_pos[index]))
+    {
+        palStatus_t ret = pal_fsFseek(&(image_file[index]), offset, PAL_FS_OFFSET_SEEKSET);
+        if (ret != PAL_SUCCESS)
+        {
+            last_seek_pos[index] = SEEK_POS_INVALID;
+            return false;
+        }
+    }
+
+    last_read_nwrite[index] = read_nwrite;
+    last_seek_pos[index] = offset;
+
+    return true;
+}
+
+PAL_PRIVATE bool close_if_necessary(uint32_t index)
+{
+    if (!valid_index(index))
+    {
+        return false;
+    }
+
+    palFileDescriptor_t file = image_file[index];
+    image_file[index] = 0;
+    last_seek_pos[index] = SEEK_POS_INVALID;
+
+    if (file != 0)
+    {
+        palStatus_t ret = pal_fsFclose(&file);
+        if (ret != 0)
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+PAL_PRIVATE const char *image_path_alloc_from_index(uint32_t index)
+{
+    char file_name[32] = {0};
+    snprintf(file_name, sizeof(file_name)-1, "image_%" PRIu32 ".bin", index);
+    file_name[sizeof(file_name) - 1] = 0;
+    const char * const path_list[] = {
+         (char*)PAL_UPDATE_FIRMWARE_DIR,
+        file_name,
+        NULL
+    };
+
+    return path_join_and_alloc(path_list);
+}
+
+PAL_PRIVATE const char *header_path_alloc_from_index(uint32_t index)
+{
+    char file_name[32] = {0};
+
+    if (ACTIVE_IMAGE_INDEX == index)
+    {
+        snprintf(file_name, sizeof(file_name)-1, "header_active.bin");
+    }
+    else
+    {
+        snprintf(file_name, sizeof(file_name)-1, "header_%" PRIu32 ".bin", index);
+    }
+
+    const char * const path_list[] = {
+         (char*)PAL_UPDATE_FIRMWARE_DIR,
+        file_name,
+        NULL
+    };
+
+    return path_join_and_alloc(path_list);
+}
+
+
+PAL_PRIVATE const char *path_join_and_alloc(const char * const * path_list)
+{
+    uint32_t string_size = 1;
+    uint32_t pos = 0;
+
+    // Determine size of string to return
+    while (path_list[pos] != NULL)
+    {
+        // Size of string and space for separator
+        string_size += strlen(path_list[pos]) + 1;
+        pos++;
+    }
+
+    // Allocate and initialize memory
+    char *path = (char*)malloc(string_size);
+    if (NULL != path)
+    {
+    	memset(path, 0, string_size);
+    	// Write joined path
+    	pos = 0;
+    	while (path_list[pos] != NULL)
+    	{
+    		bool has_slash = '/' == path_list[pos][strlen(path_list[pos]) - 1];
+    		bool is_last = NULL == path_list[pos + 1];
+            strncat(path, path_list[pos], string_size - strlen(path) - 1);
+    		if (!has_slash && !is_last)
+    		{
+                strncat(path, "/", string_size - strlen(path) - 1);
+    		}
+    		pos++;
+    	}
+    }
+    return path;
+}
+
+
+
+
+#elif (PAL_UPDATE_IMAGE_LOCATION == PAL_UPDATE_USE_FLASH)
+
+palStatus_t pal_imageInitAPI(palImageSignalEvent_t CBfunction)
+{
+    PAL_MODULE_INIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_plat_imageInitAPI(CBfunction);
+    return status;
+}
+
+palStatus_t pal_imageDeInit(void)
+{
+    PAL_MODULE_DEINIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_plat_imageDeInit();
+    return status;
+}
+
+
+
+palStatus_t pal_imagePrepare(palImageId_t imageId, palImageHeaderDeails_t *headerDetails)
+{
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+    pal_plat_imageSetHeader(imageId,headerDetails);
+    status = pal_plat_imageReserveSpace(imageId, headerDetails->imageSize);
+
+    return status;
+}
+
+palStatus_t pal_imageWrite (palImageId_t imageId, size_t offset, palConstBuffer_t *chunk)
+{
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_plat_imageWrite(imageId, offset, chunk);
+    return status;
+}
+
+palStatus_t  pal_imageFinalize(palImageId_t imageId)
+{
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_plat_imageFlush(imageId);
+    return status;
+}
+
+palStatus_t pal_imageGetDirectMemoryAccess(palImageId_t imageId, void** imagePtr, size_t* imageSizeInBytes)
+{
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_plat_imageGetDirectMemAccess(imageId, imagePtr, imageSizeInBytes);
+    return status;
+}
+
+palStatus_t pal_imageReadToBuffer(palImageId_t imageId, size_t offset, palBuffer_t *chunk)
+{
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+
+    status = pal_plat_imageReadToBuffer(imageId,offset,chunk);
+    return status;
+}
+
+palStatus_t pal_imageActivate(palImageId_t imageId)
+{
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_plat_imageActivate(imageId);
+    return status;
+}
+
+palStatus_t pal_imageGetActiveHash(palBuffer_t *hash)
+{
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_plat_imageGetActiveHash(hash);
+    return status;
+}
+
+palStatus_t pal_imageGetActiveVersion(palBuffer_t *version)
+{
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_plat_imageGetActiveVersion(version);
+    return status;
+}
+
+palStatus_t pal_imageWriteDataToMemory(palImagePlatformData_t dataId, const palConstBuffer_t * const dataBuffer)
+{
+    palStatus_t status = PAL_SUCCESS;
+    PAL_MODULE_IS_INIT(palUpdateInitFlag);
+    // this switch is for further use when there will be more options
+    switch(dataId)
+    {
+    case PAL_IMAGE_DATA_HASH:
+        status = pal_plat_imageWriteHashToMemory(dataBuffer);
+        break;
+    default:
+        {
+            PAL_LOG(ERR, "Update write data to mem status %d", (int)dataId);
+            status = PAL_ERR_GENERIC_FAILURE;
+        }
+    }
+    return status;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef _PAL_H
+#define _PAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+//includes for common headers in PAL
+#include "pal_configuration.h"
+#include "pal_macros.h"
+#include "pal_errors.h"
+#include "pal_types.h"
+  
+//includes for modules headers.
+#include "pal_fileSystem.h"
+#include "pal_rtos.h"
+#include "pal_network.h"
+#include "pal_TLS.h"
+#include "pal_Crypto.h"
+#include "pal_update.h"
+#include "pal_internalFlash.h"
+
+/*! \file pal.h
+*  \brief PAL.
+*   This file contains the general API to initiate and destroy the PAL component.
+*   This is part of the PAL service API.
+*/
+
+
+//declarations for global init and destroy of PAL
+
+/*! PAL initialization
+*   This function calls each module's initialization function (if exist)
+*   to allocate required resources and initiate them.
+* \return PAL_SUCCESS(0) in case of success, a negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_init(void);
+
+/*! PAL destruction.
+*   This function calls each module's destroy function (if exist)
+*   to free resources.
+*/
+int32_t pal_destroy(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif //_PAL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_Crypto.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,774 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef _PAL_CRYPTO_H_
+#define _PAL_CRYPTO_H_
+
+
+#ifndef _PAL_H
+    #error "Please do not include this file directly, use pal.h instead"
+#endif
+
+/*! \file pal_Crypto.h
+*  \brief PAL cryptographic.
+*   This file contains cryptographic APIs and is part of the PAL service API.
+*	It contains a variety of cryptographic APIs, such as:
+*		- AES-CTR
+		- AES-DRBG
+		- CMAC
+		- Message Digest
+*/
+
+typedef uintptr_t palAesHandle_t;
+typedef uintptr_t palX509Handle_t;
+typedef uintptr_t palMDHandle_t;
+typedef uintptr_t palCCMHandle_t;
+typedef uintptr_t palCMACHandle_t;
+typedef uintptr_t palCtrDrbgCtxHandle_t;
+typedef uintptr_t palCurveHandle_t;
+typedef uintptr_t palGroupIDHandle_t;
+typedef uintptr_t palECKeyHandle_t;
+typedef uintptr_t palSignatureHandle_t;
+typedef uintptr_t palx509CSRHandle_t;
+
+//! Key types to be set to the AES engine.
+typedef enum palAesKeyType{
+    PAL_KEY_TARGET_ENCRYPTION,
+    PAL_KEY_TARGET_DECRYPTION
+}palAesKeyType_t;
+
+//! Message digest algorithms supported by PAL.
+typedef enum palMDType{
+    PAL_SHA256
+}palMDType_t;
+
+//! AES mode for ECB encryption/decryption.
+typedef enum palAesMode{
+    PAL_AES_ENCRYPT,
+    PAL_AES_DECRYPT
+}palAesMode_t;
+
+//! The supported enum tags by PAL for ASN1.
+typedef enum palASNTag{
+	PAL_ASN1_BOOLEAN                 = 0x01,
+	PAL_ASN1_INTEGER                 = 0x02,
+	PAL_ASN1_BIT_STRING              = 0x03,
+	PAL_ASN1_OCTET_STRING            = 0x04,
+	PAL_ASN1_NULL                    = 0x05,
+	PAL_ASN1_OID                     = 0x06,
+	PAL_ASN1_UTF8_STRING             = 0x0C,
+	PAL_ASN1_SEQUENCE                = 0x10,
+	PAL_ASN1_SET                     = 0x11,
+	PAL_ASN1_PRINTABLE_STRING        = 0x13,
+	PAL_ASN1_T61_STRING              = 0x14,
+	PAL_ASN1_IA5_STRING              = 0x16,
+	PAL_ASN1_UTC_TIME                = 0x17,
+	PAL_ASN1_GENERALIZED_TIME        = 0x18,
+	PAL_ASN1_UNIVERSAL_STRING        = 0x1C,
+	PAL_ASN1_BMP_STRING              = 0x1E,
+	PAL_ASN1_PRIMITIVE               = 0x00,
+	PAL_ASN1_CONSTRUCTED             = 0x20,
+	PAL_ASN1_CONTEXT_SPECIFIC        = 0x80,
+}palASNTag_t;
+
+#define PAL_ASN1_CLASS_BITS 0xC0
+#define PAL_ASN1_TAG_BITS 0x1F
+#define PAL_CRYPT_BLOCK_SIZE 16
+#define PAL_SHA256_SIZE 32
+
+typedef enum palFormat{
+	PAL_POINT_CONVERSION_UNCOMPRESSED
+    /*PAL_POINT_CONVERSION_COMPRESSED*/
+}palFormat_t;
+
+typedef enum palCipherID{
+	PAL_CIPHER_ID_AES
+	/*PAL_CIPHER_ID_DES*/
+}palCipherID_t;
+
+//! Supported curves.
+typedef enum palGroupIndex{
+	PAL_ECP_DP_NONE,
+	PAL_ECP_DP_SECP256R1
+}palGroupIndex_t;
+
+//! Key usage options
+typedef enum palKeyUsage{
+	PAL_X509_KU_DIGITAL_SIGNATURE = 0x1,
+	PAL_X509_KU_NON_REPUDIATION = 0x2,
+	PAL_X509_KU_KEY_CERT_SIGN = 0x4
+}palKeyUsage_t;
+
+//! Extended key usage options
+typedef enum palExtKeyUsage {
+    PAL_X509_EXT_KU_ANY =              (1 << 0),
+    PAL_X509_EXT_KU_SERVER_AUTH =      (1 << 1),
+    PAL_X509_EXT_KU_CLIENT_AUTH =      (1 << 2),
+    PAL_X509_EXT_KU_CODE_SIGNING =     (1 << 3),
+    PAL_X509_EXT_KU_EMAIL_PROTECTION = (1 << 4),
+    PAL_X509_EXT_KU_TIME_STAMPING =    (1 << 8),
+    PAL_X509_EXT_KU_OCSP_SIGNING =     (1 << 9)
+}palExtKeyUsage_t;
+
+//! Key check options.
+typedef enum palKeyToCheck{
+	PAL_CHECK_PRIVATE_KEY = 0x01,
+	PAL_CHECK_PUBLIC_KEY = 0x10,
+	PAL_CHECK_BOTH_KEYS	= 0x11
+}palKeyToCheck_t;
+
+//! Attributes to be retrieved from the x509 cert.
+typedef enum palX509Attr{
+    PAL_X509_ISSUER_ATTR,
+    PAL_X509_SUBJECT_ATTR,
+    PAL_X509_CN_ATTR,
+    PAL_X509_OU_ATTR,
+    PAL_X509_VALID_FROM,
+    PAL_X509_VALID_TO,
+    PAL_X509_CERT_ID_ATTR,
+    PAL_X509_SIGNATUR_ATTR,
+    PAL_X509_L_ATTR
+}palX509Attr_t;
+
+
+/***************************************************/
+/**** PAL Crypto Client APIs ***********************/
+/***************************************************/
+
+/*! Initialize AES context
+ *
+ * @param[in,out] aes: The AES context to be initialized.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_initAes(palAesHandle_t *aes);
+
+/*! Free AES context.
+ *
+ * @param[in,out] aes: The AES context to be deallocated.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_freeAes(palAesHandle_t *aes);
+
+/*! Set AES key context for encryption or decryption.
+ *
+ * @param[in] aes: The AES context.
+ * @param[in] key: The AES key.
+ * @param[in] keybits: The size of the key in bits.
+ * @param[in] keyTarget: The key target (encryption/decryption).
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_setAesKey(palAesHandle_t aes, const unsigned char* key, uint32_t keybits, palAesKeyType_t keyTarget);
+
+/*! AES-CTR buffer encryption/decryption.
+ *
+ * @param[in] aes: The AES context.
+ * @param[in] input: The input data buffer.
+ * @param[out] output: The output data buffer.
+ * @param[in] inLen: The input data length.
+ * @param[in] iv: The initialization vector for AES-CTR.
+ *
+ \note Due to the nature of CTR, you should use the same key schedule for
+ * both encryption and decryption. So before calling this function, you MUST set the key 
+ * by calling `pal_setAesKey()` with key target PAL_KEY_TARGET_ENCRYPTION.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_aesCTR(palAesHandle_t aes, const unsigned char* input, unsigned char* output, size_t inLen, unsigned char iv[16]);
+
+/*! AES-CTR buffer encryption/decryption with zero offset.
+ *
+ * @param[in] aes: The AES context.
+ * @param[in] input: The input data buffer.
+ * @param[out] output: The output data buffer.
+ * @param[in] inLen: The input data length.
+ * @param[in] iv: The initialization vector for AES-CTR.
+ *
+ \note Due to the nature of CTR, you should use the same key schedule for
+ * both encryption and decryption. So before calling this function, you MUST set the key 
+ * by calling `pal_setAesKey()` with key target PAL_KEY_TARGET_ENCRYPTION.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_aesCTRWithZeroOffset(palAesHandle_t aes, const unsigned char* input, unsigned char* output, size_t inLen, unsigned char iv[16]);
+
+
+/*! AES-ECB block encryption/decryption.
+ *
+ * @param[in] aes: The AES context.
+ * @param[in] input: A 16-byte input block.
+ * @param[out] output: A 16-byte output block.
+ * @param[in] mode: PAL_AES_ENCRYPT or PAL_AES_DECRYPT.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_aesECB(palAesHandle_t aes, const unsigned char input[PAL_CRYPT_BLOCK_SIZE], unsigned char output[PAL_CRYPT_BLOCK_SIZE], palAesMode_t mode);
+
+/*! Process SHA256 over the input buffer.
+ *
+ * @param[in] input: A buffer for the input data.
+ * @param[in] inLen: The length of the input data.
+ * @param[out] output: The SHA256 checksum result.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_sha256(const unsigned char* input, size_t inLen, unsigned char output[PAL_SHA256_SIZE]);
+
+/*! Initialize a certificate (chain) context.
+ *
+ * @param[in,out] x509Cert: The certificate chain to initialize.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_x509Initiate(palX509Handle_t* x509Cert);
+
+/*! Parse one or more certificates and add them to the chained list.
+ *
+ * @param[in] x509Cert: The beginning of the chain.
+ * @param[in] input: A buffer holding the certificate data in PEM or DER format.
+ * @param[in] inLen: The size of the input buffer.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_x509CertParse(palX509Handle_t x509Cert, const unsigned char* input, size_t inLen);
+
+/*! Get attributes from the parsed certificate.
+*
+* @param[in] x509Cert: The parsed certificate.
+* @param[in] attr: The required attribute.
+* @param[out] output: A buffer to hold the attribute value.
+* @param[in] outLenBytes: The size of the allocated buffer.
+* @param[out] actualOutLenBytes: The actual size of the attribute.
+*
+\note In case of PAL_ERR_BUFFER_TOO_SMALL, the required size is assigned into the `actualOutLen` parameter.
+\note `PAL_X509_CERT_ID_ATTR` required 33 bytes buffer size.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_x509CertGetAttribute(palX509Handle_t x509Cert, palX509Attr_t attr, void* output, size_t outLenBytes, size_t* actualOutLenBytes);
+
+/*! Verify one or more X509 DER formatted certificates.
+ *
+ * @param[in] x509Cert: A handle holding the parsed certificate.
+ * @param[in] x509Cert: The beginning of the chain to verify the X509 DER certificate with. (Optional)
+ *
+ \return PAL_SUCCESS on success. In case of failure:
+ *		- PAL_ERR_X509_BADCERT_EXPIRED
+ *		- PAL_ERR_X509_BADCERT_FUTURE
+ *		- PAL_ERR_X509_BADCERT_BAD_MD
+ *		- PAL_ERR_X509_BADCERT_BAD_PK
+ *		- PAL_ERR_X509_BADCERT_NOT_TRUSTED
+ *		- PAL_ERR_X509_BADCERT_BAD_KEY
+ */
+palStatus_t pal_x509CertVerify(palX509Handle_t x509Cert, palX509Handle_t x509CertChain);
+
+/*! Verify one or more X509 DER formatted certificates.
+ *
+ * @param[in] x509Cert: A handle holding the parsed certificate.
+ * @param[in] x509Cert: The beginning of the chain to verify the X509 DER certificate with. (Optional)
+ * @param[out] verifyResult: bitmask of errors that cause the failure, this value is 
+ *							relevant ONLY in case that the return value of the function is `PAL_ERR_X509_CERT_VERIFY_FAILED`.
+ *
+ \return PAL_SUCCESS on success. In case of failure returns `PAL_ERR_X509_CERT_VERIFY_FAILED`.
+ */
+palStatus_t pal_x509CertVerifyExtended(palX509Handle_t x509Cert, palX509Handle_t x509CertChain, int32_t* verifyResult);
+
+/*! Deallocate all certificate data.
+ *
+ * @param[in,out] x509Cert: The certificate chain to free.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_x509Free(palX509Handle_t* x509Cert);
+
+/*! Initialize the MD context and set up the required data according to the given algorithm.
+ *
+ * @param[in,out] md: The MD context to be initialized.
+ * @param[in] mdType: The MD algorithm.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_mdInit(palMDHandle_t* md, palMDType_t mdType);
+
+/*! Generic message digest process buffer.
+ *
+ * @param[in] md: The MD context.
+ * @param[in] input: A buffer holding the input data.
+ * @param[in] inLen: The length of the input data.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_mdUpdate(palMDHandle_t md, const unsigned char* input, size_t inLen);
+
+/*! Generic message digest output buffer size getter.
+ *
+ * @param[in] md: The MD context.
+ * @param[out] bufferSize: A pointer to hold the output size of the `pal_mdFinal()` for the given handle. 
+ *
+ \note This function SHOULD be called before calling `pal_mdFinal()`.
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_mdGetOutputSize(palMDHandle_t md, size_t* bufferSize);
+
+/*! Generic message digest final calculation.
+ *
+ * @param[in] md: The MD context.
+ * @param[out] ouput: The checksum result of the generic message digest.
+ *
+ \note `pal_mdGetOutputSize()` SHOULD be called before calling `pal_mdFinal()` to get the needed size for the ouptut.
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_mdFinal(palMDHandle_t md, unsigned char* output);
+
+/*! Free and clear the MD context.
+ *
+ * @param[in,out] md: The MD context to be free.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_mdFree(palMDHandle_t* md);
+
+/*! Verify the signature.
+ *
+ * @param[in] x509: The certificate context that holds the PK data.
+ * @param[in] mdType: The MD algorithm used.
+ * @param[in] hash: The hash of the message to sign.
+ * @param[in] hashLen: The hash length.
+ * @param[in] sig: The signature to verify.
+ * @param[in] sigLen: The signature length.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_verifySignature(palX509Handle_t x509, palMDType_t mdType, const unsigned char *hash, size_t hashLen, const unsigned char *sig, size_t sigLen); 
+
+/*! Get the tag and length of the tag, check for the requested tag. \n
+*   Updates the pointer to immediately after the tag and length.
+ *
+ * @param[in,out] position: The position in the ASN.1 data.
+ * @param[in] end: The end of data.
+ * @param[out] len: The tag length.
+ * @param[in] tag: The expected tag.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_ASN1GetTag(unsigned char **position, const unsigned char *end, size_t *len, uint8_t tag);
+
+/*! CCM initialization.
+*
+* @param[in] ctx: The CCM context to be initialized.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_CCMInit(palCCMHandle_t* ctx);
+
+/*! CCM destruction.
+*
+* @param[in] ctx: The CCM context to destroy.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_CCMFree(palCCMHandle_t* ctx);
+
+/*! CCM set key.
+*
+* @param[in] ctx:       The CCM context to be initialized.
+* @param[in] id:        The cipher to use (a 128-bit block cipher).
+* @param[in] key:       The encryption key.
+* @param[in] keybits:   The key size in bits (must be acceptable by the cipher).
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_CCMSetKey(palCCMHandle_t ctx, const unsigned char *key, uint32_t keybits, palCipherID_t id);
+
+/*! CCM buffer authenticated decryption.
+*
+* @param[in] ctx:       The CCM context to be initialized.
+* @param[in] input      A buffer holding the input data.
+* @param[in] inLen:    	The length of the input data.
+* @param[in] iv:        The initialization vector.
+* @param[in] ivLen:    	The length of IV.
+* @param[in] add:       Additional data.
+* @param[in] addLen:   	The length of additional data.
+* @param[in] tag:      	A buffer holding the tag.
+* @param[in] tag_len:  	The length of the tag.
+* @param[out] output:   A buffer for holding the output data.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_CCMDecrypt(palCCMHandle_t ctx, unsigned char* input, size_t inLen, 
+							unsigned char* iv, size_t ivLen, unsigned char* add, 
+							size_t addLen, unsigned char* tag, size_t tagLen, 
+							unsigned char* output);
+
+/*! CCM buffer encryption.
+*
+* @param[in] ctx:       The CCM context to be initialized.
+* @param[in] input      A buffer holding the input data.
+* @param[in] inLen:    	The length of the input data.
+* @param[in] iv:        The initialization vector.
+* @param[in] ivLen:    	The length of IV.
+* @param[in] add:       Additional data.
+* @param[in] addLen:   	The length of additional data.
+* @param[out] output:   A buffer for holding the output data, must be at least `inLen` bytes wide.
+* @param[out] tag:      A buffer for holding the tag.
+* @param[out] tagLen:   The length of the tag to generate in bytes.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_CCMEncrypt(palCCMHandle_t ctx, unsigned char* input, 
+							size_t inLen, unsigned char* iv, size_t ivLen, 
+							unsigned char* add, size_t addLen, unsigned char* output, 
+							unsigned char* tag, size_t tagLen);
+
+/*! Initiate CTR_DRBG context with given seed.
+*
+* @param[in] ctx:	The CTR_DRBG context to be seeded.
+* @param[in] seed:	The seed data.
+* @param[in] len:	The seed data length..
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_CtrDRBGInit(palCtrDrbgCtxHandle_t* ctx, const void* seed, size_t len);
+
+/*! CTR_DRBG pseudo random generation.
+*
+* @param[in] ctx:	The CTR_DRBG context.
+* @param[out] output:	The buffer to fill.
+* @param[in] len:	The length of the buffer.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_CtrDRBGGenerate(palCtrDrbgCtxHandle_t ctx, unsigned char* out, size_t len);
+
+/*! CTR_DRBG destroy
+*
+* @param[in] ctx:   The CTR_DRBG context to destroy.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_CtrDRBGFree(palCtrDrbgCtxHandle_t* ctx);
+
+
+/*! One shot AES cipher CMAC.
+*
+* @param[in] ctx:               The CMAC context to initialize.
+* @param[in] key:               The encryption key.
+* @param[in] keyLenInBits:      The key size in bits.
+* @param[in] input:             A buffer for the input data.
+* @param[in] inputLenInBytes:   The input data length in bytes.
+* @param[out] output:           The generic CMAC result.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_cipherCMAC(const unsigned char *key, size_t keyLenInBits, const unsigned char *input, size_t inputLenInBytes, unsigned char *output);
+
+/*! Iterative cipher CMAC start
+*
+* @param[in] ctx:        The CMAC context.
+* @param[in] key:        The CMAC key.
+* @param[in] keyLenBits: The key size in bits.
+* @param[in] cipherID:   A buffer for the input data.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_CMACStart(palCMACHandle_t *ctx, const unsigned char *key, size_t keyLenBits, palCipherID_t cipherID);
+
+/*! Iterative cipher CMAC update.
+*
+* @param[in] ctx:   	The CMAC context.
+* @param[in] input:  	A buffer for the input data.
+* @param[in] inputLen:  The input data length.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_CMACUpdate(palCMACHandle_t ctx, const unsigned char *input, size_t inLen);
+
+/*! Iterative cipher CMAC finish.
+*
+* @param[in] ctx:   	The CMAC context.
+* @param[out] output:  	A buffer for the output data.
+* @param[out] outLen:   The output data length.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_CMACFinish(palCMACHandle_t *ctx, unsigned char *output, size_t* outLen);
+
+/*! One shot md HMAC.
+*
+* @param[in] key:               The encryption key.
+* @param[in] keyLenInBytes:   	The key size in bytes.
+* @param[in] input:  	        A buffer for the input data.
+* @param[in] inputLenInBytes:   The input data length in bytes.
+* @param[out] output:           The generic HMAC result.
+* @param[out] outputLenInBytes: Size of the HMAC result (optional).
+*
+\note Expects output to be 32 bytes long
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_mdHmacSha256(const unsigned char *key, size_t keyLenInBytes, const unsigned char *input, size_t inputLenInBytes, unsigned char *output, size_t* outputLenInBytes);
+
+
+/*! Check that the private and/or public key is a valid and the public key is on this curve.
+*
+* @param[in] grp:	The curve/group that the point should belong to.
+* @param[in] key:	A pointer to a struct holding the raw data of the keys to check.
+* @param[in] type:      PAL_CHECK_PRIVATE_KEY/PAL_CHECK_PUBLIC_KEY/PAL_CHECK_BOTH_KEYS from `palKeyToCheck_t`.
+* @param[out] verified:	The result of verification.
+*
+\note	The key can contain only private or public key or both.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_ECCheckKey(palCurveHandle_t grp, palECKeyHandle_t key, uint32_t type, bool *verified);
+
+/*! Allocate key context and initialize a key pair (as an invalid one).
+*
+* @param[in] key: The key to initialize.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_ECKeyNew(palECKeyHandle_t* key);
+
+/*! Release private/public key context related memory.
+*
+* @param[in] key: A handle for the key context to be freed.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_ECKeyFree(palECKeyHandle_t* key);
+
+/*! Parse DER encoded private key.
+*
+* @param[in] prvDERKey:	A buffer that holds the DER encoded private key.
+* @param[in] keyLen:    The key length.
+* @param[out] key:	A handle for the context that holds the parsed key.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_parseECPrivateKeyFromDER(const unsigned char* prvDERKey, size_t keyLen, palECKeyHandle_t key);
+
+/*! Parse DER encoded public key.
+*
+* @param[in] pubDERKey:	A buffer that holds the DER encoded public key.
+* @param[in] keyLen:    The key length.
+* @param[out] key:	A handle for the context that holds the parsed key.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_parseECPublicKeyFromDER(const unsigned char* pubDERKey, size_t keyLen, palECKeyHandle_t key);
+
+/*! Encode given private key from key handle to DER buffer.
+*
+* @param[in] key: 	 A handle to the private key.
+* @param[out] derBuffer: A buffer to hold the result of the DER encoding.
+* @param[in] bufferSize: The size of the allocated buffer.
+* @param[out] actualSize: The actual size of the written data.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_writePrivateKeyToDer(palECKeyHandle_t key, unsigned char* derBuffer, size_t bufferSize, size_t* actualSize);
+
+/*! Encode given public key from key handle to DER buffer.
+*
+* @param[in] key: 		A handle to the public key.
+* @param[out] derBuffer: 	A buffer to hold the result of the DER encoding.
+* @param[in] bufferSize:  	The size of the allocated buffer.
+* @param[out] actualSize:	The actual size of the written data.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_writePublicKeyToDer(palECKeyHandle_t key, unsigned char* derBuffer, size_t bufferSize, size_t* actualSize);
+
+/*! Generate a key pair for a given curve.
+*
+* @param[in] grpID:	The ECP group identifier.
+* @param[in,out] key:	The destination key pair handle.
+*
+\note The `key` parameter must be first allocated by `pal_ECKeyNew()`.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_ECKeyGenerateKey(palGroupIndex_t grpID, palECKeyHandle_t key);
+
+/*! Retrieve the curve ID if it exists in the given key. 
+*
+* @param[in] key: The key to retrieve its curve. 
+* @param[out] grpID: The curve/group ID for the given key. In case of error, this pointer contains PAL_ECP_DP_NONE.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_ECKeyGetCurve(palECKeyHandle_t key, palGroupIndex_t* grpID);
+
+/*! ECP group initialize and set a group using well-known domain parameters.
+*
+* @param[in] grp:	The destination group.
+* @param[in] index:	The index in the list of well-known domain parameters.
+*
+\return PAL_SUCCESS on success, negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_ECGroupInitAndLoad(palCurveHandle_t* grp, palGroupIndex_t index);
+
+/*! Free the ECP group context.
+*
+* @param[in] grp: The curve/group to free.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_ECGroupFree(palCurveHandle_t* grp);
+
+/*! Allocate and initialize x509 CSR context.
+*
+* @param[in] x509CSR:	The CSR context to allocate and initialize. 
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_x509CSRInit(palx509CSRHandle_t *x509CSR);
+
+/*! Set the subject name for a CSR. Subject names should contain a comma-separated list of OIDs and values.
+*
+* @param[in] x509CSR: 	  The CSR context to use.
+* @param[in] subjectName: The subject name to set
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_x509CSRSetSubject(palx509CSRHandle_t x509CSR, const char* subjectName);
+
+/*! Set the MD algorithm to use for the signature.
+*
+* @param[in] x509CSR:   The CSR context to use.
+* @param[in] mdType:    The MD algorithm to use.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_x509CSRSetMD(palx509CSRHandle_t x509CSR, palMDType_t mdType);
+
+/*! Set the key for a CSR.
+*
+* @param[in] x509CSR:   The CSR context to use.
+* @param[in] pubKey:    The public key to include. To use a key pair handle, see the note.
+* @param[in] prvKey:    The public key to sign with.
+*
+\note To use key pair, send it as `pubKey` and NULL as `prvKey`.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_x509CSRSetKey(palx509CSRHandle_t x509CSR, palECKeyHandle_t pubKey, palECKeyHandle_t prvKey);
+
+/*! Set the key usage extension flags.
+*
+* @param[in] x509CSR:   The CSR context to use.
+* @param[in] keyUsage:  The key usage flags, should be taken from `palKeyUsage_t`.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_x509CSRSetKeyUsage(palx509CSRHandle_t x509CSR, uint32_t keyUsage);
+
+/*! Set the extended key usage extension.
+*
+* @param[in] x509CSR:   The CSR context to use.
+* @param[in] extKeyUsage:  The extended key usage flags, should be taken from `palExtKeyUsage_t`.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_x509CSRSetExtendedKeyUsage(palx509CSRHandle_t x509CSR, uint32_t extKeyUsage);
+
+/*! Generic function to add to the CSR.
+*
+* @param[in] x509CSR:   The CSR context to use.
+* @param[in] oid:  	The OID of the extension.
+* @param[in] oidLen: 	The OID length.
+* @param[in] value: 	The value of the extension OCTET STRING.
+* @param[in] valueLen:  The value length.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_x509CSRSetExtension(palx509CSRHandle_t x509CSR,const char* oid, size_t oidLen, 
+									const unsigned char* value, size_t valueLen);
+
+/*! Write a CSR to a DER structure
+*
+* @param[in] x509CSR:   	The CSR context to use.
+* @param[in] derBuf:  		A buffer to write to.
+* @param[in] derBufLen: 	The buffer length.
+* @param[in] actualDerLen: 	The actual length of the written data.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_x509CSRWriteDER(palx509CSRHandle_t x509CSR, unsigned char* derBuf, size_t derBufLen, size_t* actualDerLen);
+
+/*! Free the x509 CSR context.
+*
+* @param[in] x509CSR:	The CSR context to free.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_x509CSRFree(palx509CSRHandle_t *x509CSR);
+
+/*! Compute the shared secret using elliptic curve Diffie–Hellman.
+*
+* @param[in] grp:		The ECP group.
+* @param[in] peerPublicKey:	The public key from a peer.
+* @param[in] key:		The private key.
+* @param[out] out:		The shared secret.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_ECDHComputeKey(const palCurveHandle_t grp, const palECKeyHandle_t peerPublicKey, 
+								const palECKeyHandle_t privateKey, palECKeyHandle_t outKey);
+
+/*! Compute the ECDSA signature of a previously hashed message.
+*
+* @param[in] grp:	The ECP group.
+* @param[in] prvKey:	The private signing key.
+* @param[in] dgst:	The message hash.
+* @param[in] dgstLen:	The length ofthe  message buffer.
+* @param[out] sig:	A buffer to hold the computed signature.
+* @param[out] sigLen:   The length of the computed signature.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_ECDSASign(palCurveHandle_t grp, palMDType_t mdType, palECKeyHandle_t prvKey, unsigned char* dgst, 
+									uint32_t dgstLen, unsigned char *sig, size_t *sigLen);
+
+/*! Verify the ECDSA signature of a previously hashed message.
+*
+* @param[in] pubKey:	The public key for verification.
+* @param[in] dgst:	The message hash.
+* @param[in] dgstLen:	The length of the message buffer.
+* @param[in] sign:	The signature.
+* @param[in] sig:	A buffer to hold the computed signature.
+* @param[in] sigLen:    The length of the computed signature.
+* @param[out] verified: A boolean to hold the verification result.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_ECDSAVerify(palECKeyHandle_t pubKey, unsigned char* dgst, uint32_t dgstLen, 
+									unsigned char* sig, size_t sigLen, bool* verified);
+
+
+/*! Calculate the hash of the To Be Signed part of an X509 certificate.
+* This function may be used to validate a certificate signature: Simply retrieve this hash, verify the signature using this hash, the public key and the signature of the X509
+*
+* @param[in] x509Cert:	        Handle to the certificate to hash the TBS (to be signed part). 
+* @param[in] hash_type:	        The hash type. Currently only PAL_SHA256 supported
+* @param[out] output:	        Pointer to a buffer that will contain the hash digest. This buffer must be at least the size of the digest. If hash_type is PAL_SHA256, then buffer pointed to by output must be at least 32 bytes. 
+* @param[in] outLenBytes:       The size of the buffer pointed to by output. Must be at least the size of the digest
+* @param[out] actualOutLenBytes:    Size of the digest copied to output. In case of success, will always be the length of the hash digest
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+
+palStatus_t pal_x509CertGetHTBS(palX509Handle_t x509Cert, palMDType_t hash_type, unsigned char *output, size_t outLenBytes, size_t* actualOutLenBytes);
+
+#endif //_PAL_CRYPTO_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_TLS.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef _PAL_DTLS_H_
+#define _PAL_DTLS_H_
+
+#ifndef _PAL_H
+    #error "Please do not include this file directly, use pal.h instead"
+#endif
+
+/*! \file pal_TLS.h
+*  \brief PAL TLS/DTLS.
+*   This file contains TLS/DTLS APIs and is a part of the PAL service API.
+*   It provides TLS/DTLS handshake functionalities, read/write from peer in a secure way.
+*/
+
+/***************************************************/
+/**** PAL DTLS data structures *********************/
+/***************************************************/
+
+// Index in the static array of the TLSs.
+typedef uintptr_t palTLSHandle_t;
+typedef uintptr_t palTLSConfHandle_t;
+
+typedef enum palTLSTranportMode{
+#ifdef PAL_NET_TCP_AND_TLS_SUPPORT
+    PAL_TLS_MODE, //(STREAM)
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+    PAL_DTLS_MODE //(DATAGRAM)
+}palTLSTransportMode_t;
+
+typedef struct palTLSSocket{
+    palSocket_t socket;
+    palSocketAddress_t* socketAddress;
+    palSocketLength_t addressLength;
+    palTLSTransportMode_t transportationMode;
+}palTLSSocket_t;
+
+
+typedef struct palTLSBuffer{
+    const void* buffer;
+    uint32_t size;
+}palTLSBuffer_t;
+
+typedef palTLSBuffer_t palX509_t;
+typedef palTLSBuffer_t palX509CRL_t;
+typedef palTLSBuffer_t palPrivateKey_t;
+
+//! This callback is useful ONLY when mbed TLS used as TLS platform library. In other platforms,
+//! you should NOT use this callback in the code. The related function is not supported in other
+//! platforms than mbedTLS.
+typedef int(*palEntropySource_f)(void *data, unsigned char *output, size_t len, size_t *olen);
+
+/***************************************************/
+/**** PAL DTLS Client APIs *************************/
+/***************************************************/
+
+/*!	Initiate the TLS library.
+*
+\note You must call this function in the general PAL initializtion function.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_initTLSLibrary(void);
+
+/*!	Free resources for the TLS library.
+*
+\note You must call this function in the general PAL cleanup function.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_cleanupTLS(void);
+
+/*! Initiate a new TLS context.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[out] palTLSHandle: The index to the TLS context.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_initTLS(palTLSConfHandle_t palTLSConf, palTLSHandle_t* palTLSHandle);
+
+/*! Destroy and free resources for the TLS context.
+*
+* @param[in] palTLSHandle: The index to the TLS context.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_freeTLS(palTLSHandle_t* palTLSHandle);
+
+/*! Add entropy source to the TLS/DTLS library. (This API may NOT be available in all TLS/DTLS platforms, see note.)
+*
+* @param[in] entropyCallback: The entropy callback to be used in TLS/DTLS handshake.
+*
+\note This function is available ONLY when the TLS/DTLS platform supports this functionality. In other platforms,
+      PAL_ERR_NOT_SUPPORTED should be returned.
+\note This function MUST be called (if needed) before calling the `pal_initTLSConfiguration()` function.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure, or PAL_ERR_NOT_SUPPORTED.
+*/
+palStatus_t pal_addEntropySource(palEntropySource_f entropyCallback);
+
+/*! Initiate a new configuration context.
+*
+* @param[out] palTLSConf: The context that holds the TLS configuration.
+* @param[in] transportationMode: The connection type (TLS OR DTLS). See `palTranportVersion_t`.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_initTLSConfiguration(palTLSConfHandle_t* palTLSConf, palTLSTransportMode_t transportationMode);
+
+/*! Destroy and free resources for the TLS configurtion context.
+*
+* @param[in] palTLSConf: The TLS configuration context to free.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_tlsConfigurationFree(palTLSConfHandle_t* palTLSConf);
+
+/*! Set your own certificate chain and private key.
+*
+* @deprecated This function has been splitted into two separate functions, pal_setOwnCertChain() and pal_setOwnPrivateKey().
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] ownCert: Your own public certificate chain.
+* @param[in] privateKey: Your own private key.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_setOwnCertAndPrivateKey(palTLSConfHandle_t palTLSConf, palX509_t* ownCert, palPrivateKey_t* privateKey);
+
+/*! Set your own certificate chain.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] ownCert: Your own public certificate chain.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_setOwnCertChain(palTLSConfHandle_t palTLSConf, palX509_t* ownCert);
+
+/*! Set your own private key.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] privateKey: Your own private key.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_setOwnPrivateKey(palTLSConfHandle_t palTLSConf, palPrivateKey_t* privateKey);
+
+/*! Set the data required to verify the peer certificate.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] caChain: The trusted CA chain.
+* @param[in] caCRL: The trusted CA CRLs.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_setCAChain(palTLSConfHandle_t palTLSConf, palX509_t* caChain, palX509CRL_t* caCRL);
+
+/*! Set the Pre-Shared Key (PSK) and the expected identity name.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] identity: A pointer to the pre-shared key identity.
+* @param[in] maxIdentityLenInBytes: The length of the key identity.
+* @param[in] psk: A pointer to the pre-shared key.
+* @param[in] maxPskLenInBytes: The length of the pre-shared key.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_setPSK(palTLSConfHandle_t palTLSConf, const unsigned char *identity, uint32_t maxIdentityLenInBytes, const unsigned char *psk, uint32_t maxPskLenInBytes);
+
+/*! Set the socket used by the TLS configuration context.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] socket: The socket to be used by the TLS context.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_tlsSetSocket(palTLSConfHandle_t palTLSConf, palTLSSocket_t* socket);
+
+/*! Perform the TLS handshake (blocking).
+*
+* This function sets the TLS configuration context into the TLS context and performs the handshake
+* with the peer.
+* @param[in] palTLSHandle: The TLS context.
+* @param[in] palTLSConf: The TLS configuration context.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_handShake(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSConf);
+
+/*! Set the retransmit timeout values for the DTLS handshake.
+*	(DTLS only, no effect on TLS.)
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] timeoutInMilliSec: The timeout value in seconds.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_setHandShakeTimeOut(palTLSConfHandle_t palTLSConf, uint32_t timeoutInMilliSec);
+
+/*! Return the result of the certificate verification.
+*
+* @param[in] ssl: The SSL context.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_sslGetVerifyResult(palTLSHandle_t palTLSHandle);
+
+/*! Return the result of the certificate verification.
+*
+* @param[in] ssl: The SSL context.
+* @param[out] verifyResult: bitmask of errors that cause the failure, this value is
+*							relevant ONLY in case that the return value of the function is `PAL_ERR_X509_CERT_VERIFY_FAILED`.
+*
+\return PAL_SUCCESS on success. In case of failure returns `PAL_ERR_X509_CERT_VERIFY_FAILED`.
+*/
+palStatus_t pal_sslGetVerifyResultExtended(palTLSHandle_t palTLSHandle, int32_t* verifyResult);
+
+/*! Read the application data bytes (the max number of bytes).
+*
+* @param[in] palTLSHandle: The TLS context.
+* @param[out] buffer: A buffer that holds the data.
+* @param[in] len: The maximum number of bytes to read.
+* @param[out] actualLen: The the actual number of bytes read.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_sslRead(palTLSHandle_t palTLSHandle, void *buffer, uint32_t len, uint32_t* actualLen);
+
+/*! Write the exact length of application data bytes.
+*
+* @param[in] palTLSHandle: The TLS context.
+* @param[in] buffer: A buffer holding the data.
+* @param[in] len: The number of bytes to be written.
+* @param[out] bytesWritten: The number of bytes actually written.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_sslWrite(palTLSHandle_t palTLSHandle, const void *buffer, uint32_t len, uint32_t *bytesWritten);
+
+/*! Turn on/off the TLS library debugging for the given configuration handle. The logs are sent via the mbedTrace.
+*   In case of release mode, an error will be returned.
+*
+* @param[in] palTLSConf : the TLS confuguraiton to modify
+* @param[in] turnOn: if greater than 0 turn on debugging, otherwise turn it off
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_sslSetDebugging(palTLSConfHandle_t palTLSConf,uint8_t turnOn);
+
+
+
+/*! Turn on/off debugging from the TLS library. The logs are sent via the mbedTrace.
+*   In case of release mode, an error will be returned.
+*
+* @param[in] turnOn if greater than 0 turn on debugging, otherwise turn it off
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_sslDebugging(uint8_t turnOn);
+
+#endif // _PAL_DTLS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_configuration.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,472 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef _PAL_COFIGURATION_H
+#define _PAL_COFIGURATION_H
+#include "limits.h"
+
+
+#ifdef PAL_USER_DEFINED_CONFIGURATION
+    #include PAL_USER_DEFINED_CONFIGURATION
+#else
+    #include "sotp_fs.h"
+#endif
+
+
+/*! \brief If needed any board specific configuration please set this define
+*/
+#ifdef PAL_BOARD_SPECIFIC_CONFIG
+    #include PAL_BOARD_SPECIFIC_CONFIG
+#endif
+
+
+/*! \brief let the user choose its platform configuration file.
+    \note if the user does not specify a platform configuration file,
+    \note PAL uses a default configuration set that can be found at \b Configs/pal_config folder
+  */
+
+#ifdef PAL_PLATFORM_DEFINED_CONFIGURATION
+    #include PAL_PLATFORM_DEFINED_CONFIGURATION
+#elif defined(__LINUX__)
+    #include "Linux_default.h"
+#elif defined(__FREERTOS__)
+    #include "FreeRTOS_default.h"
+#elif defined(__MBED__)
+    #include "mbedOS_default.h"
+#else
+    #error "Please specify the platform PAL_PLATFORM_DEFINED_CONFIGURATION"
+#endif
+
+/*! \file pal_configuration.h
+*  \brief PAL Configuration.
+*   This file contains PAL configuration information including the following:
+*       1. The flags to enable or disable features.
+*       2. The configuration of the number of objects provided by PAL (such as the number of threads supported) or their sizes.
+*       3. The configuration of supported cipher suites.
+*       4. The configuration for flash memory usage.
+*       5. The configuration for the root of trust.
+*/
+
+
+/*
+ * Network configuration
+ */
+//! PAL configuration options
+#ifndef PAL_NET_TCP_AND_TLS_SUPPORT
+    #define PAL_NET_TCP_AND_TLS_SUPPORT         true/* Add PAL support for TCP. */
+#endif
+
+#ifndef PAL_NET_ASYNCHRONOUS_SOCKET_API
+    #define PAL_NET_ASYNCHRONOUS_SOCKET_API     true/* Add PAL support for asynchronous sockets. */
+#endif
+
+#ifndef PAL_NET_DNS_SUPPORT
+    #define PAL_NET_DNS_SUPPORT                 true/* Add PAL support for DNS lookup. */
+#endif
+
+#if (PAL_NET_DNS_SUPPORT == true) && !(defined(PAL_DNS_API_VERSION))
+#define PAL_DNS_API_VERSION 1
+#endif
+
+#if (PAL_DNS_API_VERSION == 2)
+#define PAL_DNS_API_V2
+#endif
+
+#ifndef PAL_SUPPORT_IP_V4
+    #define PAL_SUPPORT_IP_V4                 true /* support IPV4 as default*/
+#endif
+#ifndef PAL_SUPPORT_IP_V6
+    #define PAL_SUPPORT_IP_V6                 true /* support IPV6 as default*/
+#endif
+
+//values for PAL_NET_DNS_IP_SUPPORT
+#define PAL_NET_DNS_ANY          0    /* if PAL_NET_DNS_IP_SUPPORT is set to PAL_NET_DNS_ANY pal_getAddressInfo will return the first available IPV4 or IPV6 address*/
+#define PAL_NET_DNS_IPV4_ONLY    2    /* if PAL_NET_DNS_IP_SUPPORT is set to PAL_NET_DNS_IPV4_ONLY pal_getAddressInfo will return the first available IPV4 address*/
+#define PAL_NET_DNS_IPV6_ONLY    4    /* if PAL_NET_DNS_IP_SUPPORT is set to PAL_NET_DNS_IPV6_ONLY pal_getAddressInfo will return the first available IPV6 address*/
+
+
+#ifndef PAL_NET_DNS_IP_SUPPORT
+#if PAL_SUPPORT_IP_V6 == true && PAL_SUPPORT_IP_V4 == true
+    #define PAL_NET_DNS_IP_SUPPORT  0 /* sets the type of IP addresses returned by  pal_getAddressInfo*/
+#elif PAL_SUPPORT_IP_V6 == true
+    #define PAL_NET_DNS_IP_SUPPORT  4 /* sets the type of IP addresses returned by  pal_getAddressInfo*/
+#else 
+    #define PAL_NET_DNS_IP_SUPPORT  2 /* sets the type of IP addresses returned by  pal_getAddressInfo*/
+#endif
+
+#endif
+
+//! The maximum number of interfaces that can be supported at a time.
+#ifndef PAL_MAX_SUPORTED_NET_INTERFACES
+    #define PAL_MAX_SUPORTED_NET_INTERFACES 10
+#endif
+
+//!< Stack size for thread created when calling pal_getAddressInfoAsync
+#ifndef PAL_NET_ASYNC_DNS_THREAD_STACK_SIZE
+    #define PAL_NET_ASYNC_DNS_THREAD_STACK_SIZE (1024 * 2)
+#endif
+
+
+//! If you want PAL Not to perform a rollback/cleanup although main PAL init failed, please set this flag to `false`
+#ifndef PAL_CLEANUP_ON_INIT_FAILURE
+	#define PAL_CLEANUP_ON_INIT_FAILURE true
+#endif
+
+/*
+ * RTOS configuration
+ */
+//! This flag determines if PAL moudles are thread safe. 1 - thread safety is enabled, 0 - thread safety is disabled
+#ifndef PAL_THREAD_SAFETY
+	#define PAL_THREAD_SAFETY 1
+#endif
+
+//! initial time until thread stack cleanup (mbedOs only). This is the amount of time we wait before checking that a thread has completed so we can free it's stack.
+#ifndef PAL_RTOS_THREAD_CLEANUP_TIMER_MILISEC
+    #define PAL_RTOS_THREAD_CLEANUP_TIMER_MILISEC 200
+#endif
+
+//! This define is used to determine the size of the initial random buffer (in bytes) held by PAL for random the algorithm.
+#ifndef PAL_INITIAL_RANDOM_SIZE
+    #define PAL_INITIAL_RANDOM_SIZE 48
+#endif
+
+#ifndef PAL_RTOS_WAIT_FOREVER
+    #define PAL_RTOS_WAIT_FOREVER UINT_MAX
+#endif
+
+/*
+ * TLS configuration
+ */
+
+//! The maximum number of supported cipher suites.
+#ifndef PAL_MAX_ALLOWED_CIPHER_SUITES
+    #define PAL_MAX_ALLOWED_CIPHER_SUITES 1
+#endif
+
+//! This value is in milliseconds. 1000 = 1 second.
+#ifndef PAL_DTLS_PEER_MIN_TIMEOUT
+    #define PAL_DTLS_PEER_MIN_TIMEOUT 1000
+#endif
+
+//! The debug threshold for TLS API.
+#ifndef PAL_TLS_DEBUG_THRESHOLD
+    #define PAL_TLS_DEBUG_THRESHOLD 5
+#endif
+
+//! 32 or 48 (depends on the curve) bytes for the X,Y coordinates and 1 for the normalized/non-normalized
+#ifndef PAL_CERT_ID_SIZE
+    #define PAL_CERT_ID_SIZE 33 
+#endif
+
+
+#ifndef PAL_ENABLE_PSK
+	#define PAL_ENABLE_PSK 0
+#endif
+
+#ifndef PAL_ENABLE_X509
+	#define PAL_ENABLE_X509 1
+#endif 
+
+//! Define the cipher suites for TLS (only one cipher suite per device available).
+#define PAL_TLS_PSK_WITH_AES_128_CBC_SHA256_SUITE               0x01
+#define PAL_TLS_PSK_WITH_AES_128_CCM_8_SUITE                    0x02
+#define PAL_TLS_PSK_WITH_AES_256_CCM_8_SUITE                    0x04
+#define PAL_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8_SUITE            0x08
+#define PAL_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_SUITE       0x10
+#define PAL_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_SUITE       0x20
+#define PAL_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256_SUITE      0x40
+#define PAL_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256_SUITE      0x80
+
+//! Use the default cipher suite for TLS/DTLS operations
+#if (PAL_ENABLE_X509 == 1)
+    #ifndef PAL_TLS_CIPHER_SUITE
+        #define PAL_TLS_CIPHER_SUITE PAL_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8_SUITE
+    #endif
+#elif (PAL_ENABLE_PSK == 1)
+    #ifndef PAL_TLS_CIPHER_SUITE
+        #define PAL_TLS_CIPHER_SUITE PAL_TLS_PSK_WITH_AES_128_CCM_8_SUITE
+    #endif
+#endif
+
+#ifndef PAL_CMAC_SUPPORT
+	#define PAL_CMAC_SUPPORT true
+#endif
+
+//! Enable the CMAC functionality (This flag was targeted to let the bootloader to be compiled without CMAC)
+#ifndef PAL_CMAC_SUPPORT
+        #define PAL_CMAC_SUPPORT 1
+#endif //PAL_CMAC_SUPPORT
+
+/*
+ * UPDATE configuration
+ */
+
+#define PAL_UPDATE_USE_FLASH 1
+#define PAL_UPDATE_USE_FS    2
+
+#ifndef PAL_UPDATE_IMAGE_LOCATION
+	#define PAL_UPDATE_IMAGE_LOCATION PAL_UPDATE_USE_FS     //!< Choose the storage correct Storage option, File System or Flash
+#endif
+
+//! Certificate date validation in Unix time format.
+#ifndef PAL_CRYPTO_CERT_DATE_LENGTH
+    #define PAL_CRYPTO_CERT_DATE_LENGTH sizeof(uint64_t)
+#endif
+
+/*
+ * FS configuration
+ */
+
+/* !\brief file system configurations
+ * PAL_NUMBER_OF_PARTITIONS
+ * 0 - Default behavior for the platform (Described by either 1 or 2 below).
+ * 1 - There is a single partition in which the ARM client applications create and remove files (but do not format it).
+ * 2 - There are two partitions in which ARM client applications may format or create and remove files,
+ *     depending on PAL_PRIMARY_PARTITION_PRIVATE and PAL_SECONDARY_PARTITION_PRIVATE
+ */
+#ifndef PAL_NUMBER_OF_PARTITIONS
+    #define PAL_NUMBER_OF_PARTITIONS 1 // Default partitions
+#endif
+
+#if (PAL_NUMBER_OF_PARTITIONS > 2)
+#error "PAL_NUMBER_OF_PARTITIONS cannot be more then 2"
+#endif
+
+// PAL_PRIMARY_PARTITION_PRIVATE
+// 1 if the primary partition is exclusively dedicated to the ARM client applications.
+// 0 if the primary partition is used for storing other files as well.
+#ifndef PAL_PRIMARY_PARTITION_PRIVATE
+    #define PAL_PRIMARY_PARTITION_PRIVATE 0
+#endif
+
+//! PAL_SECONDARY_PARTITION_PRIVATE
+//! 1 if the secondary partition is exclusively dedicated to the ARM client applications.
+//! 0 if the secondary partition is used for storing other files as well.
+#ifndef PAL_SECONDARY_PARTITION_PRIVATE
+    #define PAL_SECONDARY_PARTITION_PRIVATE 0
+#endif
+
+//! This define is the location of the primary mount point for the file system
+#ifndef PAL_FS_MOUNT_POINT_PRIMARY
+    #define PAL_FS_MOUNT_POINT_PRIMARY  ""
+#endif
+
+//! This define is the location of the secondary mount point for the file system
+#ifndef PAL_FS_MOUNT_POINT_SECONDARY
+    #define PAL_FS_MOUNT_POINT_SECONDARY ""
+#endif
+
+// Update
+
+#ifndef PAL_UPDATE_FIRMWARE_MOUNT_POINT
+    #define PAL_UPDATE_FIRMWARE_MOUNT_POINT PAL_FS_MOUNT_POINT_PRIMARY
+#endif
+//! The location of the firmware update folder
+#ifndef PAL_UPDATE_FIRMWARE_DIR
+    #define PAL_UPDATE_FIRMWARE_DIR PAL_UPDATE_FIRMWARE_MOUNT_POINT "/firmware"
+#endif
+
+/*\brief If flash existed set to 1 else 0, the flash is used for none volatile backup*/
+#ifndef PAL_USE_INTERNAL_FLASH 
+    #define PAL_USE_INTERNAL_FLASH  0
+#endif
+
+#ifndef PAL_INT_FLASH_NUM_SECTIONS
+    #define PAL_INT_FLASH_NUM_SECTIONS 0
+#endif
+
+#ifndef PAL_USE_HW_ROT 
+    #define PAL_USE_HW_ROT     1
+#endif
+
+#ifndef PAL_USE_HW_RTC
+    #define PAL_USE_HW_RTC    1
+#endif
+
+#ifndef PAL_USE_HW_TRNG
+    #define PAL_USE_HW_TRNG    1
+#endif
+
+//! The number of valid priorities limits the number of concurrent running threads.
+#ifndef PAL_MAX_NUMBER_OF_THREADS
+    #if PAL_USE_HW_TRNG
+        #define PAL_MAX_NUMBER_OF_THREADS 9    
+    #else
+        #define PAL_MAX_NUMBER_OF_THREADS 8
+    #endif
+#endif
+
+#if PAL_USE_HW_TRNG
+    //! Delay for TRNG noise collecting thread used between calls to TRNG
+    #ifndef PAL_NOISE_TRNG_THREAD_DELAY_MILLI_SEC
+        #define PAL_NOISE_TRNG_THREAD_DELAY_MILLI_SEC (1000 * 60) // one minute
+    #endif
+    //! Stack size for TRNG noise collecting thread
+    #ifndef PAL_NOISE_TRNG_THREAD_STACK_SIZE
+        #define PAL_NOISE_TRNG_THREAD_STACK_SIZE 1536 // 1.5K
+    #endif
+#endif
+
+#ifndef PAL_USE_SECURE_TIME
+    #define PAL_USE_SECURE_TIME 1
+#endif
+
+#ifndef PAL_DEVICE_KEY_DERIVATION_BACKWARD_COMPATIBILITY_CALC
+    #define PAL_DEVICE_KEY_DERIVATION_BACKWARD_COMPATIBILITY_CALC 0
+#endif    
+
+/*\brief  Starting Address for  section 1 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_ADDRESS
+    #define PAL_INTERNAL_FLASH_SECTION_1_ADDRESS    0
+#endif
+/*\brief  Starting Address for  section 2 Minimum requirement size is 1KB and section must be consecutive sectors*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_ADDRESS
+    #define PAL_INTERNAL_FLASH_SECTION_2_ADDRESS    0
+#endif
+/*\brief  Size for  section 1*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_1_SIZE
+    #define PAL_INTERNAL_FLASH_SECTION_1_SIZE       0
+#endif
+/*\brief  Size for  section 2*/
+#ifndef PAL_INTERNAL_FLASH_SECTION_2_SIZE
+    #define PAL_INTERNAL_FLASH_SECTION_2_SIZE       0
+#endif
+
+#ifndef PAL_SIMULATOR_TEST_ENABLE
+    #define PAL_SIMULATOR_TEST_ENABLE    0
+#endif
+
+
+
+#if (PAL_SIMULATOR_TEST_ENABLE == 1) 
+
+    #undef PAL_SIMULATE_RTOS_REBOOT
+    #define PAL_SIMULATE_RTOS_REBOOT 1
+
+    #undef PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+    #define PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM    1
+
+/*\brief overwrite format command with remove all file and directory only for Linux*/
+    #undef PAL_SIMULATOR_FS_RM_INSTEAD_OF_FORMAT
+    #define PAL_SIMULATOR_FS_RM_INSTEAD_OF_FORMAT 1
+#endif //PAL_SIMULATOR_TEST_ENABLE
+
+#ifndef PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+    #define PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM    0
+#endif
+
+
+
+#if PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+
+
+    #undef PAL_USE_INTERNAL_FLASH 
+    #define PAL_USE_INTERNAL_FLASH  1
+
+    #undef PAL_INT_FLASH_NUM_SECTIONS
+    #define PAL_INT_FLASH_NUM_SECTIONS 2
+
+    #ifndef PAL_SIMULATOR_SOTP_AREA_SIZE
+        #define PAL_SIMULATOR_SOTP_AREA_SIZE    4096 /*\brief must be power of two the can be divded to page size without reminder and must be a multiple of sector size*/
+    #endif
+
+    #ifndef SIMULATE_FLASH_SECTOR_SIZE
+        #define SIMULATE_FLASH_SECTOR_SIZE	    4096 /*\brief  Flash Sector size*/
+    #endif
+
+    #ifndef SIMULATE_FLASH_DIR
+        #define SIMULATE_FLASH_DIR			    "" /*\brief Directory that holds the flash simulator file*/
+    #endif
+
+    #ifndef SIMULATE_FLASH_FILE_NAME
+        #define SIMULATE_FLASH_FILE_NAME	    SIMULATE_FLASH_DIR"/flashSim" /*\brief File name and path to the flash simulator file*/
+    #endif
+
+    #ifndef SIMULATE_FLASH_PAGE_SIZE
+        #define SIMULATE_FLASH_PAGE_SIZE	    8 /*\brief Minumum writing uint to flash (2, 4, 8, 16)*/
+    #endif
+
+    #if PAL_SIMULATOR_SOTP_AREA_SIZE < 4096
+        #error Minimum Size of 4K
+    #endif
+
+    /*\brief  Note - In simulator mode all flash areas are overriden with the simulation sizes and address*/
+
+    #undef PAL_INTERNAL_FLASH_SECTION_1_SIZE
+    /*\brief  Size for section 1*/
+    #define PAL_INTERNAL_FLASH_SECTION_1_SIZE       PAL_SIMULATOR_SOTP_AREA_SIZE
+
+    #undef PAL_INTERNAL_FLASH_SECTION_2_SIZE
+    /*\brief  Size for section 2*/
+    #define PAL_INTERNAL_FLASH_SECTION_2_SIZE       PAL_SIMULATOR_SOTP_AREA_SIZE
+
+    #undef PAL_INTERNAL_FLASH_SECTION_1_ADDRESS
+    /*\brief  Starting Address for section 1 Minimum requirement size is 1KB and section must be consecutive sectors*/
+    #define PAL_INTERNAL_FLASH_SECTION_1_ADDRESS    0
+
+    #undef PAL_INTERNAL_FLASH_SECTION_2_ADDRESS
+    /*\brief  Starting Address for section 2 Minimum requirement size is 1KB and section must be consecutive sectors*/
+    #define PAL_INTERNAL_FLASH_SECTION_2_ADDRESS    PAL_INTERNAL_FLASH_SECTION_1_SIZE
+
+#endif //PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM
+
+
+#define VALUE_TO_STRING(x) #x
+#define VALUE(x) VALUE_TO_STRING(x)
+#define VAR_NAME_VALUE(var) #var " = "  VALUE(var)
+
+#if ((!PAL_USE_INTERNAL_FLASH && (!PAL_USE_HW_ROT || !PAL_USE_HW_RTC || !PAL_USE_HW_TRNG))  \
+        || ((PAL_INT_FLASH_NUM_SECTIONS == 1) && PAL_USE_INTERNAL_FLASH && (!PAL_USE_HW_RTC || !PAL_USE_HW_TRNG)))
+        #pragma message(VAR_NAME_VALUE(PAL_USE_INTERNAL_FLASH))
+        #pragma message(VAR_NAME_VALUE(PAL_USE_HW_ROT))
+        #pragma message(VAR_NAME_VALUE(PAL_USE_HW_RTC))
+        #pragma message(VAR_NAME_VALUE(PAL_USE_HW_TRNG))
+        #pragma message(VAR_NAME_VALUE(PAL_INT_FLASH_NUM_SECTIONS))
+    #error Minimum configuration setting does not meet the requirements     
+#endif
+
+#if (((PAL_ENABLE_PSK == 1) && (PAL_ENABLE_X509 == 1)) && !(defined(__LINUX__)))
+    #error "Please select only one option PSK/X509"
+#endif
+
+#if ((PAL_ENABLE_PSK == 0) && (PAL_ENABLE_X509 == 0))
+    #error "Please select one option PSK/X509"
+#endif
+
+
+
+#if ((PAL_ENABLE_PSK == 1) && (PAL_USE_SECURE_TIME == 1))
+    #error "PSK feature cannot be configured along with secure time"
+#endif
+
+
+
+//! Delay (in milliseconds) between calls to TRNG random buffer in case only partial data (PAL_ERR_RTOS_TRNG_PARTIAL_DATA) was generated for the function call
+#ifndef PAL_TRNG_COLLECT_DELAY_MILLI_SEC
+    #define PAL_TRNG_COLLECT_DELAY_MILLI_SEC 1000
+#endif // !PAL_TRNG_COLLECT_DELAY_MILLI_SEC
+
+//! define the number of images
+#ifndef IMAGE_COUNT_MAX
+	#define IMAGE_COUNT_MAX             1
+#endif
+
+#define PAL_NOISE_SIZE_BYTES 48 // max number of bytes for noise
+#define PAL_NOISE_SIZE_BITS (PAL_NOISE_SIZE_BYTES * CHAR_BIT) // max number of bits for noise
+#define PAL_NOISE_BUFFER_LEN (PAL_NOISE_SIZE_BYTES / sizeof(int32_t)) // length of the noise buffer
+
+#endif //_PAL_COFIGURATION_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_errors.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef _PAL_ERRORS_H
+#define _PAL_ERRORS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pal_types.h"
+
+/*! \file pal_errors.h
+ *  \brief PAL errors.
+ *   This file contains PAL errors enumeration. These errors are returned to the service layer.
+ */
+
+#define PAL_ERR_MODULE_GENERAL_BASE     ((int32_t)0xFFFFFFF0) // -1 << 0x4
+#define PAL_ERR_MODULE_PAL_BASE         ((int32_t)0xFFFFFFC0) // -1 << 0x6
+#define PAL_ERR_MODULE_C_BASE           ((int32_t)0xFFFFFF00) // -1 << 0x8,
+#define PAL_ERR_MODULE_RTOS_BASE        ((int32_t)0xFFFFF000) // -1 << 0xC,
+#define PAL_ERR_MODULE_NET_BASE         ((int32_t)0xFFFF0000) // -1 << 0x10,
+#define PAL_ERR_MODULE_TLS_BASE         ((int32_t)0xFFF00000) // -1 << 0x14,
+#define PAL_ERR_MODULE_CRYPTO_BASE      ((int32_t)0xFF000000) // -1 << 0x18,
+#define PAL_ERR_MODULE_FILESYSTEM_BASE  ((int32_t)0xFC000000)
+#define PAL_ERR_MODULE_INTERNAL_FLASH_BASE     ((int32_t)0xFC000500)
+#define PAL_ERR_MODULE_UPDATE_BASE      ((int32_t)0xF0000000) // -1 << 0x1C,
+#define PAL_ERR_MODULE_BITMASK_BASE      ((int32_t)0xE0000000)
+
+
+typedef enum {
+	//Success Codes are positive
+	PAL_SUCCESS = 0,
+
+	//All errors are Negative
+	// generic errors
+	PAL_ERR_GENERAL_BASE =          PAL_ERR_MODULE_GENERAL_BASE,
+	PAL_ERR_GENERIC_FAILURE =       PAL_ERR_GENERAL_BASE,       /*! Generic failure*/ // Try to use a more specific error message whenever possible. */
+	PAL_ERR_INVALID_ARGUMENT =      PAL_ERR_GENERAL_BASE + 0x01,   /*! One or more of the function arguments is invalid. */
+	PAL_ERR_NO_MEMORY =             PAL_ERR_GENERAL_BASE + 0x02,   /*! Failure due to a failed attempt to allocate memory. */
+	PAL_ERR_BUFFER_TOO_SMALL =      PAL_ERR_GENERAL_BASE + 0x03,   /*! The buffer given is too small. */
+	PAL_ERR_NOT_SUPPORTED =         PAL_ERR_GENERAL_BASE + 0x04,   /*! The operation is not supported by PAL for the current configuration. */
+	PAL_ERR_TIMEOUT_EXPIRED =       PAL_ERR_GENERAL_BASE + 0x05,   /*! The timeout for the operation has expired. */
+	PAL_ERR_NOT_INITIALIZED =       PAL_ERR_GENERAL_BASE + 0x06,   /*! Component is not initialized */
+	PAL_ERR_NULL_POINTER     =      PAL_ERR_GENERAL_BASE + 0x07,   /*! Received a null pointer when it should be initialized. */
+	PAL_ERR_CREATION_FAILED =       PAL_ERR_GENERAL_BASE + 0x08,   /*! Failure in creation of the given type, such as mutex or thread. */
+	PAL_ERR_END_OF_FILE =           PAL_ERR_GENERAL_BASE + 0x09,   /*! The reading process finished since end of file reached. */
+	PAL_ERR_INVALID_TIME =          PAL_ERR_GENERAL_BASE + 0x0A,  /*! Invalid time value. */
+	PAL_ERR_GET_DEV_KEY =           PAL_ERR_GENERAL_BASE + 0x0B,  /*! Failure deriving the key from RoT. */
+	PAL_ERR_TIME_TRANSLATE =        PAL_ERR_GENERAL_BASE + 0x0C,  /*! Failure to translate the time from "struct tm" to epoch time. */
+	PAL_ERR_SYSCALL_FAILED =		PAL_ERR_GENERAL_BASE + 0x0D,  /*! Failure of calling a system call using system, popen, exec and ect.*/
+
+	// pal errors
+	PAL_ERR_NOT_IMPLEMENTED =                               PAL_ERR_MODULE_PAL_BASE, /*! Currently not implemented. */
+	// c errors
+	// RTOS errors
+	PAL_ERR_RTOS_ERROR_BASE =                               PAL_ERR_MODULE_RTOS_BASE,      /*! A generic failure in the RTOS module*/ // Try to use a more specific error message whenever possible. */
+	PAL_ERR_RTOS_TRNG_FAILED =                              PAL_ERR_MODULE_RTOS_BASE + 1,  /*! failed to get all the required random data */
+	PAL_ERR_RTOS_TRNG_PARTIAL_DATA =                        PAL_ERR_MODULE_RTOS_BASE + 2,  /*! get partial random data, instead of getting the full length */
+	PAL_ERR_RTOS_PARAMETER =                                PAL_ERR_RTOS_ERROR_BASE + 0x80,/*! PAL mapping of CMSIS error `osErrorParameter`: A parameter error: A mandatory parameter was missing or specified an incorrect object. */
+	PAL_ERR_RTOS_RESOURCE =                                 PAL_ERR_RTOS_ERROR_BASE + 0x81,/*! PAL mapping of CMSIS error `osErrorResource`: Resource not available: The specified resource was not available. */
+	PAL_ERR_RTOS_TIMEOUT =                                  PAL_ERR_RTOS_ERROR_BASE + 0xC1,/*! PAL mapping of CMSIS error `osErrorTimeoutResource`: Resource not available within the given time: A specified resource was not available within the timeout period. */
+	PAL_ERR_RTOS_ISR =                                      PAL_ERR_RTOS_ERROR_BASE + 0x82,/*! PAL mapping of CMSIS error `osErrorISR`: Not allowed in ISR context: The function cannot be called from interrupt service routines. */
+	PAL_ERR_RTOS_ISR_RECURSIVE =                            PAL_ERR_RTOS_ERROR_BASE + 0x83,/*! PAL mapping of CMSIS error `osErrorISRRecursive`: Function called multiple times from ISR with same `object.c` */
+	PAL_ERR_RTOS_PRIORITY =                                 PAL_ERR_RTOS_ERROR_BASE + 0x84,/*! PAL mapping of CMSIS error `osErrorPriority`: The system cannot determine the priority or the thread has illegal priority. */
+	PAL_ERR_RTOS_NO_MEMORY =                                PAL_ERR_RTOS_ERROR_BASE + 0x85,/*! PAL mapping of CMSIS error `osErrorNoMemory`: The system is out of memory: It was impossible to allocate or reserve memory for the operation. */
+	PAL_ERR_RTOS_VALUE =                                    PAL_ERR_RTOS_ERROR_BASE + 0x86,/*! PAL mapping of CMSIS error `osErrorValue`: The value of a parameter is out of range. */
+	PAL_ERR_RTOS_TASK =                                     PAL_ERR_RTOS_ERROR_BASE + 0x87,/*! PAL mapping - Cannot kill own task. */
+	PAL_ERR_RTOS_RECEIVED_LENGTH_IS_TOO_SHORT =             PAL_ERR_RTOS_ERROR_BASE + 0x88,/*! Key received by SOTP is not long enough. */
+	PAL_ERR_RTOS_BUFFER_NOT_ALIGNED =                       PAL_ERR_RTOS_ERROR_BASE + 0x89,/*! Buffer not aligned to 32 bits*/
+	PAL_ERR_RTOS_RTC_SET_TIME_ERROR =                       PAL_ERR_RTOS_ERROR_BASE + 0x8A,
+	PAL_ERR_RTOS_RTC_OPEN_DEVICE_ERROR =                    PAL_ERR_RTOS_ERROR_BASE + 0x8B,
+	PAL_ERR_RTOS_RTC_GET_TIME_ERROR =                       PAL_ERR_RTOS_ERROR_BASE + 0x8C,
+	PAL_ERR_RTOS_NO_PRIVILEGED =   		                    PAL_ERR_RTOS_ERROR_BASE + 0x8D,/*! Insufficient privilege*/
+	PAL_ERR_RTOS_RTC_OPEN_IOCTL_ERROR =                     PAL_ERR_RTOS_ERROR_BASE + 0x8E,
+	PAL_ERR_NO_HIGH_RES_TIMER_LEFT =                        PAL_ERR_RTOS_ERROR_BASE + 0x8F,/*! only one high resolution timer at a time is supported by pal  */
+    PAL_ERR_RTOS_NOISE_BUFFER_FULL =                        PAL_ERR_RTOS_ERROR_BASE + 0x90,/*! Noise buffer is full. */
+    PAL_ERR_RTOS_NOISE_BUFFER_IS_READING =                  PAL_ERR_RTOS_ERROR_BASE + 0x91,/*! Noise buffer is currently being read and writes are not allowed while reading. */
+    PAL_ERR_RTOS_NOISE_BUFFER_EMPTY =                       PAL_ERR_RTOS_ERROR_BASE + 0x92,/*! Noise buffer is empty. */
+    PAL_ERR_RTOS_NOISE_BUFFER_NOT_FULL =                    PAL_ERR_RTOS_ERROR_BASE + 0x93,/*! Noise buffer is not full. */
+	PAL_ERR_RTOS_OS =                                       PAL_ERR_RTOS_ERROR_BASE + 0xFF,/*! PAL mapping of CMSIS error `osErrorOS`: An unspecified RTOS error: Run-time error but no other error message fits. */
+
+
+	// Network errors.
+	PAL_ERR_SOCKET_ERROR_BASE =                             PAL_ERR_MODULE_NET_BASE,                /*! Generic socket error. */
+	PAL_ERR_SOCKET_GENERIC =                                PAL_ERR_SOCKET_ERROR_BASE,              /*! Generic socket error */
+	PAL_ERR_SOCKET_NO_BUFFERS =                             PAL_ERR_SOCKET_ERROR_BASE + 1,          /*! No buffers - PAL mapping of Posix error ENOBUFS. */
+	PAL_ERR_SOCKET_HOST_UNREACHABLE =                       PAL_ERR_SOCKET_ERROR_BASE + 2,          /*! Host unreachable (routing error) - PAL mapping of Posix error EHOSTUNREACH. */
+	PAL_ERR_SOCKET_IN_PROGRES =                             PAL_ERR_SOCKET_ERROR_BASE + 3,          /*! In progress - PAL mapping of Posix error EINPROGRESS. */
+	PAL_ERR_SOCKET_INVALID_VALUE =                          PAL_ERR_SOCKET_ERROR_BASE + 4,          /*! Invalid value - PAL mapping of Posix error EINVAL*/
+	PAL_ERR_SOCKET_WOULD_BLOCK =                            PAL_ERR_SOCKET_ERROR_BASE + 5,          /*! Would block - PAL mapping of Posix error EWOULDBLOCK. */
+	PAL_ERR_SOCKET_ADDRESS_IN_USE =                         PAL_ERR_SOCKET_ERROR_BASE + 6,          /*! Address in use - PAL mapping of Posix error EADDRINUSE. */
+	PAL_ERR_SOCKET_ALREADY_CONNECTED =                      PAL_ERR_SOCKET_ERROR_BASE + 7,          /*! Already connected - PAL mapping of Posix error EALREADY. */
+	PAL_ERR_SOCKET_CONNECTION_ABORTED =                     PAL_ERR_SOCKET_ERROR_BASE + 8,          /*! Connection aborted - PAL mapping of Posix error ECONNABORTED. */
+	PAL_ERR_SOCKET_CONNECTION_RESET =                       PAL_ERR_SOCKET_ERROR_BASE + 9,          /*! Connection reset - PAL mapping of Posix error ECONNRESET. */
+	PAL_ERR_SOCKET_NOT_CONNECTED =                          PAL_ERR_SOCKET_ERROR_BASE + 10,         /*! Not connected - PAL mapping of Posix error ENOTCONN. */
+	PAL_ERR_SOCKET_INPUT_OUTPUT_ERROR =                     PAL_ERR_SOCKET_ERROR_BASE + 11,         /*! I/O error - PAL mapping of Posix error EIO. */
+	PAL_ERR_SOCKET_CONNECTION_CLOSED =                      PAL_ERR_SOCKET_ERROR_BASE + 12,         /*! Connection closed. */
+	PAL_ERR_SOCKET_FAILED_TO_SET_SOCKET_TO_NON_BLOCKING =   PAL_ERR_SOCKET_ERROR_BASE + 13,         /*! Failed to set the socket to non-blocking. */
+	PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY =                 PAL_ERR_SOCKET_ERROR_BASE + 14,         /*! Invalid Address family field. */
+	PAL_ERR_SOCKET_INVALID_ADDRESS =                        PAL_ERR_SOCKET_ERROR_BASE + 15,         /*! Address given was not valid/found. */
+	PAL_ERR_SOCKET_DNS_ERROR =                              PAL_ERR_SOCKET_ERROR_BASE + 16,         /*! DNS lookup error. */
+	PAL_ERR_SOCKET_HDCP_ERROR =                             PAL_ERR_SOCKET_ERROR_BASE + 17,         /*! HDCP error. */
+	PAL_ERR_SOCKET_AUTH_ERROR =                             PAL_ERR_SOCKET_ERROR_BASE + 18,         /*! Authentication error. */
+	PAL_ERR_SOCKET_OPTION_NOT_SUPPORTED =                   PAL_ERR_SOCKET_ERROR_BASE + 19,         /*! Socket option not supported. */
+	PAL_ERR_SOCKET_SEND_BUFFER_TOO_BIG =                    PAL_ERR_SOCKET_ERROR_BASE + 20,         /*! Buffer sent too large (over supported MTU). */
+	PAL_ERR_SOCKET_ALLOCATION_FAILED =                      PAL_ERR_SOCKET_ERROR_BASE + 21,         /*! Failed to allocate the socket. */
+	PAL_ERR_SOCKET_OPERATION_NOT_PERMITTED =                PAL_ERR_SOCKET_ERROR_BASE + 22,         /*! operation not permitted */
+	PAL_ERR_SOCKET_MAX_NUMBER_OF_INTERFACES_REACHED =       PAL_ERR_SOCKET_ERROR_BASE + 23,         /*! Failed to register the new interface. */
+	PAL_ERR_SOCKET_INTERRUPTED  =                           PAL_ERR_SOCKET_ERROR_BASE + 24,         /*! Function call interrupted. */
+	//TLS Errors
+	PAL_ERR_TLS_ERROR_BASE =                                PAL_ERR_MODULE_TLS_BASE,
+	PAL_ERR_TLS_INIT =                                      PAL_ERR_TLS_ERROR_BASE,
+	PAL_ERR_TLS_RESOURCE =                                  PAL_ERR_TLS_ERROR_BASE + 1,
+	PAL_ERR_TLS_CONFIG_INIT =                               PAL_ERR_TLS_ERROR_BASE + 2,
+	PAL_ERR_TLS_CONTEXT_NOT_INITIALIZED =                   PAL_ERR_TLS_ERROR_BASE + 3,
+	PAL_ERR_TLS_INVALID_CIPHER =                            PAL_ERR_TLS_ERROR_BASE + 4,
+	PAL_ERR_TLS_WANT_READ =                                 PAL_ERR_TLS_ERROR_BASE + 5,
+	PAL_ERR_TLS_WANT_WRITE =                                PAL_ERR_TLS_ERROR_BASE + 6,
+	PAL_ERR_TLS_CLIENT_RECONNECT =                          PAL_ERR_TLS_ERROR_BASE + 7,
+	PAL_ERR_TLS_BAD_INPUT_DATA =                            PAL_ERR_TLS_ERROR_BASE + 8,
+	PAL_ERR_TLS_HELLO_VERIFY_REQUIRED =                     PAL_ERR_TLS_ERROR_BASE + 9,
+	PAL_ERR_TLS_FAILED_TO_PARSE_CERT =                      PAL_ERR_TLS_ERROR_BASE + 10,
+	PAL_ERR_TLS_FAILED_TO_PARSE_KEY =                       PAL_ERR_TLS_ERROR_BASE + 11,
+	PAL_ERR_TLS_FAILED_TO_SET_CERT =                        PAL_ERR_TLS_ERROR_BASE + 12,
+	PAL_ERR_TLS_PEER_CLOSE_NOTIFY =                         PAL_ERR_TLS_ERROR_BASE + 13,
+	PAL_ERR_TLS_MULTIPLE_HANDSHAKE =                   		PAL_ERR_TLS_ERROR_BASE + 14,
+	//update Error
+	PAL_ERR_UPDATE_ERROR_BASE =                             PAL_ERR_MODULE_UPDATE_BASE,             /*! Generic error. */
+	PAL_ERR_UPDATE_ERROR =                                  PAL_ERR_UPDATE_ERROR_BASE,              /*! Unknown error. */
+	PAL_ERR_UPDATE_BUSY =                                   PAL_ERR_UPDATE_ERROR_BASE + 1,          /*! Unknown error. */
+	PAL_ERR_UPDATE_TIMEOUT =                                PAL_ERR_UPDATE_ERROR_BASE + 2,          /*! Unknown error. */
+	PAL_ERR_UPDATE_OUT_OF_BOUNDS =                          PAL_ERR_UPDATE_ERROR_BASE + 3,          /*! Unknown error. */
+	PAL_ERR_UPDATE_PALFROM_API =                            PAL_ERR_UPDATE_ERROR_BASE + 4,          /*! Unknown error. */
+	PAL_ERR_UPDATE_PALFROM_IO =                             PAL_ERR_UPDATE_ERROR_BASE + 5,          /*! Unknown error. */
+	PAL_ERR_UPDATE_END_OF_IMAGE =                           PAL_ERR_UPDATE_ERROR_BASE + 6,          /*! Unknown error. */
+	PAL_ERR_UPDATE_CHUNK_TO_SMALL =                         PAL_ERR_UPDATE_ERROR_BASE + 7,          /*! Unknown error. */
+	//Crypto Errors
+	PAL_ERR_CRYPTO_ERROR_BASE =                             PAL_ERR_MODULE_CRYPTO_BASE,
+	PAL_ERR_AES_INVALID_KEY_LENGTH =                        PAL_ERR_CRYPTO_ERROR_BASE,
+	PAL_ERR_CERT_PARSING_FAILED =                           PAL_ERR_CRYPTO_ERROR_BASE + 1,
+	PAL_ERR_INVALID_MD_TYPE =                               PAL_ERR_CRYPTO_ERROR_BASE + 2,
+	PAL_ERR_MD_BAD_INPUT_DATA =                             PAL_ERR_CRYPTO_ERROR_BASE + 3,
+	PAL_ERR_PK_SIG_VERIFY_FAILED =                          PAL_ERR_CRYPTO_ERROR_BASE + 4,
+	PAL_ERR_ASN1_UNEXPECTED_TAG =                           PAL_ERR_CRYPTO_ERROR_BASE + 5,
+	PAL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED =                PAL_ERR_CRYPTO_ERROR_BASE + 6,
+	PAL_ERR_CTR_DRBG_REQUEST_TOO_BIG =                      PAL_ERR_CRYPTO_ERROR_BASE + 7,
+	PAL_ERR_ECP_BAD_INPUT_DATA =                            PAL_ERR_CRYPTO_ERROR_BASE + 8,
+	PAL_ERR_MPI_ALLOC_FAILED =                              PAL_ERR_CRYPTO_ERROR_BASE + 9,
+	PAL_ERR_ECP_FEATURE_UNAVAILABLE =                       PAL_ERR_CRYPTO_ERROR_BASE + 10,
+	PAL_ERR_ECP_BUFFER_TOO_SMALL =                          PAL_ERR_CRYPTO_ERROR_BASE + 11,
+	PAL_ERR_MPI_BUFFER_TOO_SMALL =                          PAL_ERR_CRYPTO_ERROR_BASE + 12,
+	PAL_ERR_CMAC_GENERIC_FAILURE =                          PAL_ERR_CRYPTO_ERROR_BASE + 13,
+	PAL_ERR_NOT_SUPPORTED_ASN_TAG =                         PAL_ERR_CRYPTO_ERROR_BASE + 14,
+	PAL_ERR_PRIVATE_KEY_BAD_DATA =                          PAL_ERR_CRYPTO_ERROR_BASE + 15,
+	PAL_ERR_PRIVATE_KEY_VARIFICATION_FAILED =               PAL_ERR_CRYPTO_ERROR_BASE + 16,
+	PAL_ERR_PUBLIC_KEY_BAD_DATA =                           PAL_ERR_CRYPTO_ERROR_BASE + 17,
+	PAL_ERR_PUBLIC_KEY_VARIFICATION_FAILED =                PAL_ERR_CRYPTO_ERROR_BASE + 18,
+	PAL_ERR_NOT_SUPPORTED_CURVE =                           PAL_ERR_CRYPTO_ERROR_BASE + 19,
+	PAL_ERR_GROUP_LOAD_FAILED =                             PAL_ERR_CRYPTO_ERROR_BASE + 20,
+	PAL_ERR_PARSING_PRIVATE_KEY  =                          PAL_ERR_CRYPTO_ERROR_BASE + 21,
+	PAL_ERR_PARSING_PUBLIC_KEY   =                          PAL_ERR_CRYPTO_ERROR_BASE + 22,
+	PAL_ERR_KEYPAIR_GEN_FAIL     =                          PAL_ERR_CRYPTO_ERROR_BASE + 23,
+	PAL_ERR_X509_UNKNOWN_OID     =                          PAL_ERR_CRYPTO_ERROR_BASE + 24,
+	PAL_ERR_X509_INVALID_NAME    =                          PAL_ERR_CRYPTO_ERROR_BASE + 25,
+	PAL_ERR_FAILED_TO_SET_KEY_USAGE =                       PAL_ERR_CRYPTO_ERROR_BASE + 26,
+	PAL_ERR_INVALID_KEY_USAGE    =                          PAL_ERR_CRYPTO_ERROR_BASE + 27,
+	PAL_ERR_SET_EXTENSION_FAILED =                          PAL_ERR_CRYPTO_ERROR_BASE + 28,
+	PAL_ERR_CSR_WRITE_DER_FAILED =                          PAL_ERR_CRYPTO_ERROR_BASE + 29,
+	PAL_ERR_FAILED_TO_COPY_KEYPAIR =                        PAL_ERR_CRYPTO_ERROR_BASE + 30,
+	PAL_ERR_FAILED_TO_COPY_GROUP =                          PAL_ERR_CRYPTO_ERROR_BASE + 31,
+	PAL_ERR_FAILED_TO_WRITE_SIGNATURE =                     PAL_ERR_CRYPTO_ERROR_BASE + 32,
+	PAL_ERR_FAILED_TO_VERIFY_SIGNATURE =                    PAL_ERR_CRYPTO_ERROR_BASE + 33,
+	PAL_ERR_FAILED_TO_WRITE_PRIVATE_KEY =                   PAL_ERR_CRYPTO_ERROR_BASE + 34,
+	PAL_ERR_FAILED_TO_WRITE_PUBLIC_KEY  =                   PAL_ERR_CRYPTO_ERROR_BASE + 35,
+	PAL_ERR_FAILED_TO_COMPUTE_SHRED_KEY =                   PAL_ERR_CRYPTO_ERROR_BASE + 36,
+	PAL_ERR_INVALID_X509_ATTR =                             PAL_ERR_CRYPTO_ERROR_BASE + 37,
+	PAL_ERR_INVALID_CIPHER_ID =                             PAL_ERR_CRYPTO_ERROR_BASE + 38,
+	PAL_ERR_CMAC_START_FAILED =                             PAL_ERR_CRYPTO_ERROR_BASE + 39,
+	PAL_ERR_CMAC_UPDATE_FAILED =                            PAL_ERR_CRYPTO_ERROR_BASE + 40,
+	PAL_ERR_CMAC_FINISH_FAILED =                            PAL_ERR_CRYPTO_ERROR_BASE + 41,
+	PAL_ERR_INVALID_IOD =                                   PAL_ERR_CRYPTO_ERROR_BASE + 42,
+	PAL_ERR_PK_UNKNOWN_PK_ALG =                             PAL_ERR_CRYPTO_ERROR_BASE + 43,
+	PAL_ERR_PK_KEY_INVALID_VERSION =                        PAL_ERR_CRYPTO_ERROR_BASE + 44,
+	PAL_ERR_PK_KEY_INVALID_FORMAT =                         PAL_ERR_CRYPTO_ERROR_BASE + 45,
+	PAL_ERR_PK_PASSWORD_REQUIRED =                          PAL_ERR_CRYPTO_ERROR_BASE + 46,
+	PAL_ERR_PK_INVALID_PUBKEY_AND_ASN1_LEN_MISMATCH =       PAL_ERR_CRYPTO_ERROR_BASE + 47,
+	PAL_ERR_ECP_INVALID_KEY =                               PAL_ERR_CRYPTO_ERROR_BASE + 48,
+	PAL_ERR_FAILED_SET_TIME_CB =                            PAL_ERR_CRYPTO_ERROR_BASE + 49,
+	PAL_ERR_HMAC_GENERIC_FAILURE =                          PAL_ERR_CRYPTO_ERROR_BASE + 50,
+	PAL_ERR_X509_CERT_VERIFY_FAILED =                       PAL_ERR_CRYPTO_ERROR_BASE + 51,
+    PAL_ERR_FAILED_TO_SET_EXT_KEY_USAGE =                   PAL_ERR_CRYPTO_ERROR_BASE + 52,
+	PAL_ERR_X509_BADCERT_EXPIRED =                          PAL_ERR_MODULE_BITMASK_BASE + 0x01, //! Value must not be changed in order to be able to create bit mask
+	PAL_ERR_X509_BADCERT_FUTURE =                           PAL_ERR_MODULE_BITMASK_BASE + 0x02, //! Value must not be changed in order to be able to create bit mask
+	PAL_ERR_X509_BADCERT_BAD_MD =                           PAL_ERR_MODULE_BITMASK_BASE + 0x04, //! Value must not be changed in order to be able to create bit mask
+	PAL_ERR_X509_BADCERT_BAD_PK =                           PAL_ERR_MODULE_BITMASK_BASE + 0x08, //! Value must not be changed in order to be able to create bit mask
+	PAL_ERR_X509_BADCERT_NOT_TRUSTED =                      PAL_ERR_MODULE_BITMASK_BASE + 0x10, //! Value must not be changed in order to be able to create bit mask
+	PAL_ERR_X509_BADCERT_BAD_KEY =                          PAL_ERR_MODULE_BITMASK_BASE + 0x20, //! Value must not be changed in order to be able to create bit mask
+
+	PAL_ERR_FILESYSTEM_ERROR_BASE = 						PAL_ERR_MODULE_FILESYSTEM_BASE,
+	PAL_ERR_FS_OFFSET_ERROR =								PAL_ERR_FILESYSTEM_ERROR_BASE + 1,		//!< Offset given is greater than the EOF.
+	PAL_ERR_FS_ACCESS_DENIED =								PAL_ERR_FILESYSTEM_ERROR_BASE + 2,		//!< No permission to execute the command due to Permission, file in use.
+	PAL_ERR_FS_NAME_ALREADY_EXIST =							PAL_ERR_FILESYSTEM_ERROR_BASE + 3,		//!< Pathname or filename already exists.
+	PAL_ERR_FS_INSUFFICIENT_SPACE =							PAL_ERR_FILESYSTEM_ERROR_BASE + 4,		//!< Insufficient space to execute the command.
+	PAL_ERR_FS_INVALID_FILE_NAME =							PAL_ERR_FILESYSTEM_ERROR_BASE + 5,		//!< File name not valid.
+	PAL_ERR_FS_BAD_FD =										PAL_ERR_FILESYSTEM_ERROR_BASE + 6,		//!< Bad file descriptor pointer.
+	PAL_ERR_FS_INVALID_ARGUMENT =							PAL_ERR_FILESYSTEM_ERROR_BASE + 7,		//!< Invalid argument in calling function.
+	PAL_ERR_FS_NO_FILE =									PAL_ERR_FILESYSTEM_ERROR_BASE + 8,		//!< Could not find the file.
+	PAL_ERR_FS_NO_PATH =									PAL_ERR_FILESYSTEM_ERROR_BASE + 9,		//!< Could not find the path.
+	PAL_ERR_FS_DIR_NOT_EMPTY =								PAL_ERR_FILESYSTEM_ERROR_BASE + 10,		//!< Directory not empty.
+	PAL_ERR_FS_INVALID_FS =									PAL_ERR_FILESYSTEM_ERROR_BASE + 11,		//!< Invalid file system mounting or drive.
+	PAL_ERR_FS_TOO_MANY_OPEN_FD =							PAL_ERR_FILESYSTEM_ERROR_BASE + 12,		//!< Too many open file descriptors simultaneously.
+	PAL_ERR_FS_FILENAME_LENGTH =							PAL_ERR_FILESYSTEM_ERROR_BASE + 13,		//!< File name is too long or invalid.
+	PAL_ERR_FS_LENGTH_ERROR =								PAL_ERR_FILESYSTEM_ERROR_BASE + 14,		//!< Given length to read/write is wrong.
+	PAL_ERR_FS_BUFFER_ERROR =								PAL_ERR_FILESYSTEM_ERROR_BASE + 15,		//!< Given buffer is not initialized.
+	PAL_ERR_FS_ERROR =										PAL_ERR_FILESYSTEM_ERROR_BASE + 16,		//!< Generic file system error.
+	PAL_ERR_FS_BUSY =										PAL_ERR_FILESYSTEM_ERROR_BASE + 17,		//!< File/directory is open.
+	PAL_ERR_FS_INVALID_OPEN_FLAGS =							PAL_ERR_FILESYSTEM_ERROR_BASE + 18,		//!< File open mode is invalid.
+	PAL_ERR_FS_FILE_IS_DIR =								PAL_ERR_FILESYSTEM_ERROR_BASE + 19,		//!< File path given is a directory, not a file.
+	PAL_ERR_FS_ERROR_IN_SEARCHING =							PAL_ERR_FILESYSTEM_ERROR_BASE + 20, 	//!< Next file in directory could not be found.
+    PAL_ERR_FS_DISK_ERR =                                   PAL_ERR_FILESYSTEM_ERROR_BASE + 21, 	//!< A hard error occurred in the low level disk I/O layer.
+
+
+	PAL_ERR_INTERNAL_FLASH_ERROR_BASE =						PAL_ERR_MODULE_INTERNAL_FLASH_BASE,
+	PAL_ERR_INTERNAL_FLASH_GENERIC_FAILURE =				PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x01,
+	PAL_ERR_INTERNAL_FLASH_SECTOR_NOT_ALIGNED =				PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x02,
+	PAL_ERR_INTERNAL_FLASH_ADDRESS_NOT_ALIGNED =			PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x03,
+	PAL_ERR_INTERNAL_FLASH_CROSSING_SECTORS =	 			PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x04,
+	PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED =	 			PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x05,
+	PAL_ERR_INTERNAL_FLASH_WRONG_SIZE =	 					PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x06,
+	PAL_ERR_INTERNAL_FLASH_BUFFER_ADDRESS_NOT_ALIGNED =		PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x07,
+	PAL_ERR_INTERNAL_FLASH_INIT_ERROR =                     PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x08,
+	PAL_ERR_INTERNAL_FLASH_WRITE_ERROR =                    PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x09,
+	PAL_ERR_INTERNAL_FLASH_BUFFER_SIZE_NOT_ALIGNED =        PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x0A,
+	PAL_ERR_INTERNAL_FLASH_ERASE_ERROR =                    PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x0B,
+    PAL_ERR_INTERNAL_FLASH_NOT_INIT_ERROR =                 PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x0C,
+    PAL_ERR_INTERNAL_FLASH_MUTEX_RELEASE_ERROR =            PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x0D,  //!< Mutex release  or/and read/write/erase commands failed
+    PAL_ERR_INTERNAL_FLASH_FLASH_ZERO_SIZE     =            PAL_ERR_MODULE_INTERNAL_FLASH_BASE + 0x0E,
+
+} palError_t; /*! errors returned by the pal service API  */
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif //_PAL_ERRORS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_fileSystem.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,456 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#ifndef PAL_FILE_SYSTEM_H
+#define PAL_FILE_SYSTEM_H
+
+#ifndef _PAL_H
+    #error "Please do not include this file directly, use pal.h instead"
+#endif
+
+/*! \file pal_fileSystem.h
+ *  \brief PAL pal_fileSystem.
+*   This file contains the file system APIs. This is part of the PAL service API.
+*	It provides APIs to create/remove directories and open/read/write to files. 
+ */
+
+/*! \mainpage
+ *
+ *\section file_sec File System
+ *
+ *\subsection rev_hist Revision History
+ *     19-Jan-2017    Created and First Draft\n
+ *     25-Jan-2017    Updated Design according to DR meeting \n
+ *    02-Jan-2017 Minor implementation Changes \n
+ *
+ *
+ *
+ * \subsection int_sec Introduction
+* This file gives the user an abstraction layer for POSIX like file systems.
+ *
+ *
+ * \subsection req_sec Requirements
+ * The requirements for PAL Version 1.2 are to support the following POSIX like APIs:
+ *
+ *
+ *
+ *\b Folder \b Operations \n
+ *    -# mkdir        <a href="linkURL"> http://man7.org/linux/man-pages/man2/mkdir.2.html</a> \n
+ *    -# rmdir()        <a href="linkURL"> http://man7.org/linux/man-pages/man2/rmdir.2.html</a> \n
+ *
+ *
+ *\b File \b Operations \n
+ *    -# fopen()      <a href="linkURL"> http://man7.org/linux/man-pages/man3/fopen.3.html</a> \n
+ *    -# fclose()     <a href="linkURL"> http://man7.org/linux/man-pages/man3/fclose.3.html</a> \n
+ *    -# fread()      <a href="linkURL"> http://man7.org/linux/man-pages/man3/fwrite.3.html</a> \n
+ *    -# fwrite()     <a href="linkURL"> http://man7.org/linux/man-pages/man3/fwrite.3.html</a> \n
+ *    -# fseek()      <a href="linkURL"> http://man7.org/linux/man-pages/man3/fseek.3.html</a> \n
+ *    -# ftell()      <a href="linkURL"> http://man7.org/linux/man-pages/man3/fseek.3.html</a> \n
+ *    -# unlink()     <a href="linkURL"> http://man7.org/linux/man-pages/man2/unlink.2.html</a> \n
+ *
+ *
+ *\b Special \b Operations\n
+
+*	-# rmfiles()	Delete folder content (files only) (flat deletion).
+*	-# cpfiles()	Copy all files in folder to a different folder (flat copy).
+ *
+ *
+ * \subsection Prerequisites
+* 	User need to set up the file system on your project and mount the proper drive if needed. \n
+ *
+ *
+ * \subsection Limitations
+*	-# File size: Up to 2 GiB.\n
+*	-# Filename length: PAL_MAX_FILE_NAME_SIZE.\n
+*	-# Legal characters for object name: (file/directory name) are, (0-9), (a-z), (A - Z) (_ . # ). \n
+*	-# System is case-insensitive. \n
+*	-# The root folder can manage a maximum of 512 entries
+*	-# Max path length is 66 Characters.
+*	-# Folder shall be separated with "/"
+*	-# All folder Paths shall end with "/"
+
+ *
+ *
+ * \subsection  References
+ *      PAL_FileSystemSpecification.doc
+ */
+
+/*!  @defgroup PAL_GROUP_FS
+ *
+ *
+ */
+/**
+ @defgroup PAL_DEFINES  PAL Services Defined Symbols & Macros
+ @ingroup PAL_GROUP_FS
+ */
+
+/**
+ @defgroup PAL_ENUM  PAL Services Enumerated Data Types
+ @ingroup PAL_GROUP_FS
+ */
+
+/**
+ @defgroup PAL_PUBLIC_FUNCTION  PAL Services Public Functions
+ @ingroup PAL_GROUP_FS
+ */
+
+/**
+ @addtogroup PAL_DEFINES
+ @{*/
+
+
+#define PAL_MAX_FILE_NAME_SIZE		8				//!< Max length for file name received by user.
+#define PAL_MAX_FILE_NAME_SUFFIX	3				//!< Max length for file name suffix.
+#define PAL_MAX_FOLDER_DEPTH_CHAR	66				//!< Max folder length in chars.
+#define PAL_MAX_FILE_AND_FOLDER_LENGTH	(PAL_MAX_FILE_NAME_SIZE + PAL_MAX_FILE_NAME_SUFFIX + PAL_MAX_FOLDER_DEPTH_CHAR + 1) //plus 1 is for "."
+#define PAL_MAX_FULL_FILE_NAME	(PAL_MAX_FILE_NAME_SUFFIX + PAL_MAX_FOLDER_DEPTH_CHAR + 1) //plus 1 is for ".")
+
+typedef uintptr_t palFileDescriptor_t; //!< Pointer to a generic File Descriptor object
+
+/**
+ @} */
+/**
+ @addtogroup PAL_ENUM
+ @{*/
+
+/** \brief Enum for `fseek()` relative options. */
+typedef enum {
+	PAL_FS_OFFSET_KEEP_FIRST = 0,
+	PAL_FS_OFFSET_SEEKSET,		//!< Relative to the start of the file.
+	PAL_FS_OFFSET_SEEKCUR,		//!< The current position indicator.
+	PAL_FS_OFFSET_SEEKEND,		//!< End-of-file.
+	PAL_FS_OFFSET_KEEP_LAST,
+
+} pal_fsOffset_t;
+
+/** \brief Enum for fopen() permission options*/
+typedef enum {
+	PAL_FS_FLAG_KEEP_FIRST = 0,
+	PAL_FS_FLAG_READONLY,			//!< Open file for reading. The stream is positioned at the beginning of the file (file must exist), same as "r".\n
+	PAL_FS_FLAG_READWRITE,			//!< Open for reading and writing. The stream is positioned at the beginning of the file (file must exist), same as "r+ ".\n
+	PAL_FS_FLAG_READWRITEEXCLUSIVE,	//!< Open for reading and writing exclusively. If the file already exists, `fopen()` fails. The stream is positioned at the beginning of the file. same as "w+x"\n
+	PAL_FS_FLAG_READWRITETRUNC,		//!< Open for reading and writing exclusively. If the file already exists, truncate file. The stream is positioned at the beginning of the file. same as "w+"\n
+  PAL_FS_FLAG_KEEP_LAST,
+} pal_fsFileMode_t;
+/**
+ @} */
+
+
+/** \brief Enum for partition access. */
+typedef enum {
+    PAL_FS_PARTITION_PRIMARY = 0,        //!< Primary partition.\n
+    PAL_FS_PARTITION_SECONDARY,  		 //!< Secondary partition.\n
+    PAL_FS_PARTITION_LAST				 //!< Must be last value.\n
+} pal_fsStorageID_t;
+
+
+/**
+ @addtogroup PAL_PUBLIC_FUNCTION
+ @{*/
+
+/*! \brief     This function attempts to create a directory named \c pathName.
+ *
+
+* @param[in]	*pathName A pointer to the null-terminated string that specifies the directory name to create.
+
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t.
+ *
+* \note To remove a directory, use \c PAL_ERR_FS_rmdir.
+ *
+ *\b Example
+ \code{.cpp}
+ palStatus_t ret;
+ ret = PAL_ERR_FS_mkdir("Dir1");
+ if(!ret)
+ {
+ //Error
+ }
+ \endcode
+ */
+palStatus_t pal_fsMkDir(const char *pathName);
+
+/*! \brief This function deletes a directory
+ *
+
+* @param[in]	*pathName A pointer to the null-terminated string that specifies the directory name to be deleted.
+
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t.
+ *
+
+* \note The deleted directory \b must \b be \b empty and \b closed and the
+*		folder path shall end with "/".
+
+ *
+ *\b Example
+ \code{.cpp}
+ palStatus_t ret;
+ ret = PAL_ERR_FS_mkdir("Dir1"); //Create folder name "Dir1"
+ if(!ret)
+ {
+ //Error
+ }
+ ret = PAL_ERR_FS_rmdir("Dir1); //Remove directory from partition
+ if(!ret)
+ {
+ //Error
+ }
+ \endcode
+ */
+palStatus_t pal_fsRmDir(const char *pathName);
+
+
+/*!\brief This function opens the file whose name is specified in the parameter `pathName` and associates it with a stream
+*		   that can be identified in future operations by the `fd` pointer returned.
+ *
+* @param[out]	fd The file descriptor to the file entered in the `pathName`.
+* @param[in]	*pathName A pointer to the null-terminated string that specifies the file name to open or create.
+* @param[in]	mode A mode flag that specifies the type of access and open method for the file.
+
+ *
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t.
+ *
+
+* \note	  The folder path shall end with "/".
+
+ *
+ *\b Example
+ \code{.cpp}
+ //Copy File from "File1" to "File2"
+ palStatus_t ret;
+ palFileDescriptor_t fd1 = NULL,fd2 = NULL ; // File Object 1 & 2
+ uint8 buffer[1024];
+ size_t bytes_read = 0, Bytes_wrote = 0;
+
+ //Open first file with Read permission
+ ret = PAL_ERR_FS_fopen(&fd1, "File1", PAL_ERR_FS_READWRITEEXCLUSIVE);
+ if(ret)    {//Error}
+
+ //Create second file with Read/Write permissions
+ ret = PAL_ERR_FS_fopen(&fd2, "File2", PAL_ERR_FS_READWRITEEXCLUSIVE);
+ if(ret)    {//Error}
+
+ //    Copy source to destination
+ for (;;)
+ {
+ ret = PAL_ERR_FS_read(&fd1, buffer, sizeof(buffer), &bytes_read);    // Read a chunk of source file
+ if (ret || bytes_read == 0) break;    // error or EOF
+ ret = PAL_ERR_FS_write(&fd2, buffer, sizeof(buffer), &Bytes_wrote);    // Write it to the destination file
+ if (ret || Bytes_wrote < bytes_read) break;    // error or disk full
+ }
+
+ PAL_ERR_FS_close(&fd1);
+ PAL_ERR_FS_close(&fd2);
+ }
+ \endcode
+ */
+palStatus_t pal_fsFopen(const char *pathName, pal_fsFileMode_t mode,
+        palFileDescriptor_t *fd);
+
+/*! \brief This function closes an open file object.
+ *
+* @param[in] fd A pointer to the open file object structure to be closed.
+ *
+ *
+* \return PAL_SUCCESS upon successful operation. \n
+*         PAL_FILE_SYSTEM_ERROR - see error code \c palError_t.
+ *
+* \note When the function has completed successfully, the file object is no longer valid and it can be discarded.
+ *
+ */
+palStatus_t pal_fsFclose(palFileDescriptor_t *fd);
+
+
+/*! \brief This function reads an array of bytes from the stream and stores it in the block of memory
+*			specified by buffer. The position indicator of the stream is advanced by the total amount of bytes read.
+ *
+* @param[in]	fd A pointer to the open file object structure.
+* @param[in]	buffer The buffer to store the read data.
+* @param[in]	numOfBytes The number of bytes to read.
+* @param[out]	numberOfBytesRead The number of bytes read.
+
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t.
+ *
+* \note	When the function has completed successfully,
+*		`numberOfBytesRead` should be checked to detect end of the file.
+*		If `numberOfBytesRead` is less than `numOfBytes`,
+*		the read/write pointer has reached the end of the file during the read operation or there is an error.
+ *
+ */
+palStatus_t pal_fsFread(palFileDescriptor_t *fd, void * buffer,
+        size_t numOfBytes, size_t *numberOfBytesRead);
+
+/*! \brief This function starts to write data from \c buffer to the file at the position pointed by the read/write pointer.
+ *
+
+* @param[in]	fd A pointer to the open file object structure.
+* @param[in]	buffer A pointer to the data to be written.
+* @param[in]	numOfBytes The number of bytes to write.
+* @param[out]	numberOfBytesWritten The number of bytes written.
+ *
+* \return PAL_SUCCESS upon successful operation. \n
+*           PAL_FILE_SYSTEM_ERROR - see error code \c palError_t.
+ *
+* \note The read/write pointer advances as number of bytes written. When the function has completed successfully,
+* \note `numberOfBytesWritten` should be checked to detect the whether the disk is full.
+*		If `numberOfBytesWritten` is less than `numOfBytes`, the volume got full during the write operation.
+
+ *
+ */
+palStatus_t pal_fsFwrite(palFileDescriptor_t *fd, const void * buffer,
+        size_t numOfBytes, size_t *numberOfBytesWritten);
+
+
+/*! \brief This function moves the file read/write pointer without any read/write operation to the file.
+ *
+* @param[in]	fd A pointer to the open file object structure.
+* @param[in]	offset The byte offset from the top of the file to set the read/write pointer.
+* @param[out]   whence Where the offset is relative to.
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t.
+ *
+* \note The `whence` options are: \n
+* 		 -# PAL_ERR_FS_SEEKSET - Relative to the start of the file.
+*  		 -# PAL_ERR_FS_SEEKCUR - The current position indicator.
+* 		 -# PAL_ERR_FS_SEEKEND - End-of-file.
+ *
+ *\b Example
+ \code{.cpp}
+ palStatus_t ret;
+ palFileDescriptor_t fd1 = NULL; // File Object 1
+ uint8 buffer[1024];
+ size_t bytes_read = 0, Bytes_wrote = 0;
+
+ //Open file with Read permission
+ ret = PAL_ERR_FS_fopen(&fd1, "File1", PAL_ERR_FS_READ);
+ if(ret)    {//Error}
+
+ ret = PAL_ERR_FS_fseek(&fd1, 500, PAL_ERR_FS_SEEKSET)
+
+ \endcode
+ */
+palStatus_t pal_fsFseek(palFileDescriptor_t *fd, int32_t offset,
+        pal_fsOffset_t whence);
+
+/*! \brief This function gets the current read/write pointer of a file.
+ *
+* @param[in]	fd A pointer to the open file object structure.
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t.
+ *
+ */
+palStatus_t pal_fsFtell(palFileDescriptor_t *fd, int32_t *pos);
+
+/*! \brief This function deletes a \b single file from the file system.
+ *
+* @param[in]  pathName A pointer to a null-terminated string that specifies the \b file to be removed.
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t.
+ *
+* \note The file \b must \b not \b be \b open.
+ *
+ */
+palStatus_t pal_fsUnlink(const char *pathName);
+
+/*! \brief This function deletes \b all files and folders in a folder from the file system (FLAT remove only).
+ *
+* @param[in]  pathName A pointer to a null-terminated string that specifies the folder.
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t.
+ *
+* \note The folder \b must \b not \b be \b open and the folder path must end with "/".
+ */
+palStatus_t pal_fsRmFiles(const char *pathName);
+
+/*! \brief This function copies \b all files from the source folder to the destination folder (FLAT copy only).
+ *
+* @param[in]  pathNameSrc A pointer to a null-terminated string that specifies the source folder.
+* @param[in]  pathNameDest A pointer to a null-terminated string that specifies the destination folder (MUST exist).
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t.
+ *
+* \note Both folders \b must \b not \b be \b open. If the folders do not exist, the function fails.
+ *
+ *
+ */
+palStatus_t pal_fsCpFolder(const char *pathNameSrc, char *pathNameDest);
+
+/*! \brief This function sets the mount directory for the given storage ID (primary or secondary), 
+ *
+* @param[in]  Path A pointer to a null-terminated string that specifies the root folder.
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t.
+ *
+*\note	If called with NULL, the ESFS root folder is set to default PAL_SOURCE_FOLDER.
+*\note	The folder path must end with "/".
+ */
+palStatus_t pal_fsSetMountPoint(pal_fsStorageID_t dataID, const char *Path);
+
+/*! \brief This function gets the mount directory for the given storage ID (primary or secondary), The function copies the path to the user pre allocated buffer.
+ *
+* @param[in]   length The length of the buffer.
+* @param[out]  Path A pointer to \b pre-allocated \b buffer with \b size \c PAL_MAX_FOLDER_DEPTH_CHAR + 1 chars.
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t.
+ *
+* \note The plus 1 is for the '\0' terminator at the end of the buffer.
+ */
+palStatus_t pal_fsGetMountPoint(pal_fsStorageID_t dataID, size_t length, char *Path);
+
+
+/*! \brief This function formats the SD partition indentified by the `partitionID` parameter.
+ *
+* @param[in] partitionID The ID of the partition to be formatted. (**Note:** The actual partition values mapped to the IDs is determined by the porting layer.)
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t. \n
+*         PAL_ERR_INVALID_ARGUMENT - an invalid `partitionID`.
+ */
+palStatus_t pal_fsFormat(pal_fsStorageID_t dataID);
+
+
+/*! \brief This function will return if the partition used by pal only or not
+ *
+ * @param[in]   dataID - the ID of the data to be cleared (Note: the actual partition values mapped the IDs will be determined by the porting layer)
+ *
+ * \return true  - if partition is used only by pal.\n
+ *         false - if partition is used by other component then pal.\n
+ */
+bool pal_fsIsPrivatePartition(pal_fsStorageID_t dataID);
+
+
+/*! \brief This function will clean all file system resources 
+ */
+void pal_fsCleanup(void);
+
+
+/**
+ @} */
+
+#endif//test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_internalFlash.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#ifndef PAL_FLASH_H
+#define PAL_FLASH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifndef _PAL_H
+    #error "Please do not include this file directly, use pal.h instead"
+#endif
+
+
+
+#define PAL_INT_FLASH_BLANK_VAL 0xFF
+
+
+/*! \brief This function initialized the flash API module,
+ * 			And should be called prior flash APIs calls
+ *
+ * \return   PAL_SUCCESS upon successful operation. \n
+ *           PAL_FILE_SYSTEM_ERROR - see error code \c palError_t.
+ *
+ * \note should be called only once unless \c pal_internalFlashDeinit function is called
+ * \note This function is Blocking till completion!!
+ *
+ */
+palStatus_t pal_internalFlashInit(void);
+
+/*! \brief This function destroy the flash module
+ *
+ * \return PAL_SUCCESS upon successful operation. \n
+ *         PAL_ERR_INTERNAL_FLASH_ERROR - see error code \c palError_t.
+ *
+ * \note Should be called only after \c pal_internalFlashinit() is called.
+ * \note Flash APIs will not work after calling this function
+ * \note This function is Blocking till completion!!
+ *
+ */
+palStatus_t pal_internalFlashDeInit(void);
+
+/*! \brief This function writes to the internal flash
+*
+* @param[in]	buffer - pointer to the buffer to be written
+* @param[in]	size - the size of the buffer in bytes.
+* @param[in]	address - the address of the internal flash, must be aligned to minimum writing unit (page size).
+*
+* \return PAL_SUCCESS upon successful operation. \n
+*         PAL_ERR_INTERNAL_FLASH_ERROR - see error code \c palError_t.
+*
+* \note ALL address can be written to!! No protection to boot loader, program or other...
+* \note This function is Blocking till completion!!
+* \note This function is Thread Safe!!
+*/
+palStatus_t pal_internalFlashWrite(const size_t size, const uint32_t address, const uint32_t * buffer);
+
+/*! \brief This function copies the memory data into the user given buffer
+*
+* @param[in]	size - the size of the buffer in bytes.
+* @param[in]	address - the address of the internal flash.
+* @param[out]	buffer - pointer to the buffer to write to
+*
+* \return PAL_SUCCESS upon successful operation. \n
+*         PAL_ERR_INTERNAL_FLASH_ERROR - see error code \c palError_t.
+* \note This function is Blocking till completion!!
+* \note This function is Thread Safe!!
+*
+*/
+palStatus_t pal_internalFlashRead(const size_t size, const uint32_t address, uint32_t * buffer);
+
+/*! \brief This function Erase the sector
+*
+* @param[in]	size - the size to be erased
+* @param[in]	address - sector start address to be erased, must be align to sector.
+*
+* \return PAL_SUCCESS upon successful operation. \n
+*         PAL_ERR_INTERNAL_FLASH_ERROR - see error code \c palError_t.
+*
+* \note ALL sectors can be erased!! No protection to bootloader, program or other...
+* \note This function is Blocking till completion!!
+* \note Only one sector can be erased in each function call
+* \note This function is Thread Safe!!
+*/
+palStatus_t pal_internalFlashErase(uint32_t address, size_t size);
+
+
+/*! \brief This function returns the minimum writing unit to the flash
+*
+* \return size_t the 2, 4, 8....
+*/
+size_t pal_internalFlashGetPageSize(void);
+
+
+/*! \brief This function returns the sector size for the given address
+ *
+* @param[in]	the starting address of the sector is question
+*
+* \return size of sector, 0 if error
+*/
+size_t pal_internalFlashGetSectorSize(uint32_t address);
+
+
+///////////////////////////////////////////////////////////////
+////-------------------SOTP functions------------------------//
+///////////////////////////////////////////////////////////////
+
+/*! \brief This function return the SOTP section data
+*
+* @param[in]	section - the section number (0 or 1)
+* @param[out]	data - the information about the section
+*
+* \return PAL_SUCCESS upon successful operation. \n
+*         PAL_ERR_INTERNAL_FLASH_ERROR - see error code \c palError_t.
+*
+*/
+palStatus_t pal_internalFlashGetAreaInfo(uint8_t section, palSotpAreaData_t *data);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //PAL_FLASH_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_macros.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,294 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef _PAL_MACROS_H
+#define _PAL_MACROS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//for PAL_LOG prints
+#include "pal.h"
+#include "mbed-trace/mbed_trace.h"
+#include "assert.h"
+#include <limits.h>
+/*! \file pal_macros.h
+*  \brief PAL macros.
+*   This file contains macros defined by PAL for constant values and network purposes.
+*/
+
+// Maximum integer types.
+#define PAL_MAX_UINT8       0xFFU
+#define PAL_MAX_UINT16      0xFFFFU
+#define PAL_MAX_UINT32      0xFFFFFFFFUL
+#define PAL_MAX_INT32       0x7FFFFFFFL
+#define PAL_MIN_INT32       0x80000000L
+#define PAL_MAX_UINT64      0xFFFFFFFFFFFFFFFFULL
+#define PAL_MAX_INT64       0x7FFFFFFFFFFFFFFFLL
+
+// Useful macros.
+
+
+
+#if defined(__arm__) || defined(__IAR_SYSTEMS_ICC__) // Compile with ARMCC, GCC_ARM or IAR compilers.
+    #define PAL_TARGET_POINTER_SIZE __sizeof_ptr
+    #ifdef __BIG_ENDIAN
+        #define PAL_COMPILATION_ENDIANITY 1 // Define PAL compilation endian (0 is little endian, 1 is big endian).
+    #else
+        #define PAL_COMPILATION_ENDIANITY 0 // Define PAL compilation endian (0 is little endian, 1 is big endian).
+    #endif
+#elif defined(__GNUC__) // Compiling with GCC.
+    #define PAL_TARGET_POINTER_SIZE __SIZEOF_POINTER__
+    #ifdef __BYTE_ORDER
+        #if __BYTE_ORDER == __BIG_ENDIAN // If both are not defined it is TRUE!
+            #define PAL_COMPILATION_ENDIANITY 1 // Define PAL compilation endian (0 is little endian, 1 is big endian).
+        #elif __BYTE_ORDER == __LITTLE_ENDIAN
+            #define PAL_COMPILATION_ENDIANITY 0// Define PAL compilation endian (0 is little endian, 1 is big endian).
+        #else
+            #error missing endiantiy defintion for GCC
+        #endif
+    #endif
+#else
+    #error neither ARM target compilers nor GCC used for compilation - not supported
+#endif
+
+
+
+
+#define PAL_MAX(a,b)            ((a) > (b) ? (a) : (b))
+
+#define PAL_MIN(a,b)            ((a) < (b) ? (a) : (b))
+
+#define PAL_DIVIDE_ROUND_UP(num, divider)           (((num) + (divider) - 1) / (divider))
+
+#if PAL_COMPILATION_ENDIANITY == 1
+#define BIG__ENDIAN 1
+#elif PAL_COMPILATION_ENDIANITY == 0
+#define LITTLE__ENDIAN 1
+#else 
+#error neither BIG__ENDIAN nor LITTLE__ENDIAN defined, cannot compile
+#endif
+
+
+// Endianity macros.
+#ifdef LITTLE__ENDIAN
+
+#define PAL_HTONS(x) (((((unsigned short)(x)) >> 8) & 0xff) | \
+            ((((unsigned short)(x)) & 0xff) << 8))
+#define PAL_NTOHS(x) (((((unsigned short)(x)) >> 8) & 0xff) | \
+            ((((unsigned short)(x)) & 0xff) << 8) )
+#define PAL_HTONL(x) ((((x)>>24) & 0xffL) | (((x)>>8) & 0xff00L) | \
+            (((x)<<8) & 0xff0000L) | (((x)<<24) & 0xff000000L))
+#define PAL_NTOHL(x) ((((x)>>24) & 0xffL) | (((x)>>8) & 0xff00L) | \
+            (((x)<<8) & 0xff0000L) | (((x)<<24) & 0xff000000L))
+
+#elif defined(BIG__ENDIAN)
+
+#define PAL_HTONS(x) (x)
+#define PAL_NTOHS(x) (x)
+#define PAL_HTONL(x) (x)
+#define PAL_NTOHL(x) (x)
+#else
+#error neither BIG__ENDIAN nor LITTLE__ENDIAN defined, cannot compile
+#endif
+
+
+#define PAL_GET_LOWER_8BITS(x) (x & 0xFF)
+
+#define PAL_INVERSE_UINT16_BYTES( val ) \
+    ( ((val) << 8) | (((val) & 0x0000FF00) >> 8))
+
+#define PAL_INVERSE_UINT32_BYTES( val ) \
+   ( ((val) >> 24) | (((val) & 0x00FF0000) >> 8) | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24) )
+
+#define PAL_INVERSE_UINT64_BYTES( val ) \
+    ((PAL_INVERSE_UINT32_BYTES( ((val >> 16) >> 16)) &0xffffffff)  | ((((uint64_t)PAL_INVERSE_UINT32_BYTES(val & 0xffffffff))<<16)<<16)) 
+
+/* Set of Macros similar to the HTONS/L, NTOHS/L ones but converting to/from little endian instead of big endian. */
+#ifdef LITTLE__ENDIAN 
+#define PAL_LITTLE_ENDIAN_TO_HOST_16BIT(x) (x)
+#define PAL_LITTLE_ENDIAN_TO_HOST_32BIT(x) (x)
+#define PAL_LITTLE_ENDIAN_TO_HOST_64BIT(x) (x)
+#define PAL_HOST_TO_LITTLE_ENDIAN_16BIT(x) (x)
+#define PAL_HOST_TO_LITTLE_ENDIAN_32BIT(x) (x)
+#define PAL_HOST_TO_LITTLE_ENDIAN_64BIT(x) (x)
+
+
+
+
+#elif defined(BIG__ENDIAN)
+#define PAL_LITTLE_ENDIAN_TO_HOST_16BIT(x) (PAL_INVERSE_UINT16_BYTES(((uint16_t)x)))
+#define PAL_LITTLE_ENDIAN_TO_HOST_32BIT(x) (PAL_INVERSE_UINT32_BYTES(((uint32_t)x)))
+#define PAL_LITTLE_ENDIAN_TO_HOST_64BIT(x) (PAL_INVERSE_UINT64_BYTES(((uint64_t)x)))
+#define PAL_HOST_TO_LITTLE_ENDIAN_16BIT(x) (PAL_INVERSE_UINT16_BYTES(((uint16_t)x)))
+#define PAL_HOST_TO_LITTLE_ENDIAN_32BIT(x) (PAL_INVERSE_UINT32_BYTES(((uint32_t)x)))
+#define PAL_HOST_TO_LITTLE_ENDIAN_64BIT(x) (PAL_INVERSE_UINT64_BYTES(((uint64_t)x)))
+
+#else
+#error neither BIG__ENDIAN nor LITTLE__ENDIAN defined, cannot compile
+#endif
+
+
+#define PAL_MODULE_INIT(INIT) INIT= 1
+#define PAL_MODULE_DEINIT(INIT) INIT= 0
+
+//!< Time utility values
+#define PAL_MILISEC_TO_SEC(milisec) (milisec/1000)
+#define PAL_ONE_SEC                   1
+#define PAL_SECONDS_PER_MIN           60
+#define PAL_MINUTES_PER_HOUR          60
+#define PAL_HOURS_PER_DAY              24
+#define PAL_SECONDS_PER_HOUR          PAL_MINUTES_PER_HOUR * PAL_SECONDS_PER_MIN
+#define PAL_SECONDS_PER_DAY           PAL_HOURS_PER_DAY * PAL_SECONDS_PER_HOUR
+#define PAL_DAYS_IN_A_YEAR            (365U)
+#define PAL_RATIO_SECONDS_PER_DAY     480
+#define PAL_MINIMUM_RTC_LATENCY_SEC       100
+#define PAL_MINIMUM_STORAGE_LATENCY_SEC   500000
+#define PAL_MINIMUM_SOTP_FORWARD_LATENCY_SEC      100000
+#define PAL_MINIMUM_SOTP_BACKWARD_LATENCY_SEC      100
+#define PAL_FEB_MONTH 2
+#define PAL_MILLI_PER_SECOND 1000
+#define PAL_NANO_PER_MILLI 1000000L
+#define PAL_NANO_PER_SECOND 1000000000L
+#define PAL_MILLI_TO_NANO(x) (((x) % PAL_MILLI_PER_SECOND) * PAL_NANO_PER_MILLI)
+#define PAL_MILISEC_TO_SEC(milisec) (milisec/1000)
+#define PAL_MIN_SEC_FROM_EPOCH   1487015542 ////at least 47 years passed from 1.1.1970 in seconds
+#define PAL_MIN_RTC_SET_TIME    PAL_MIN_SEC_FROM_EPOCH
+#define PAL_LAST_SAVED_TIME_LATENCY_SEC     2500000
+
+//!< Define static function and inline function.
+#if defined (__CC_ARM)          /* ARM compiler. */
+	#define PAL_INLINE  __inline
+#elif defined (__GNUC__)        /* GNU compiler. */
+	#define PAL_INLINE  __attribute__((always_inline)) __inline
+#else
+	#define PAL_INLINE	//!< User should provide the compiler inline function command.
+#endif
+
+#define PAL_PRIVATE static
+
+#if defined (__CC_ARM)          /* ARM compiler. */
+#define PAL_PRAGMA(x)
+#define PAL_DEPRECATED(x)
+#else
+#define PAL_PRAGMA(x) _Pragma (#x)
+#define PAL_DEPRECATED(x) PAL_PRAGMA(message ("!!! PAL DEPRECATED CODE- " #x))
+#endif
+
+#ifdef DEBUG
+
+#define PAL_MODULE_IS_INIT(INIT) if(!INIT) return PAL_ERR_NOT_INITIALIZED;
+
+
+#else
+#define PAL_MODULE_IS_INIT(INIT) (void)INIT
+
+#endif //DEBUG
+
+// Compile time assert.
+#define PAL_ASSERT_STATIC(e) \
+   do { \
+      enum { assert_static__ = 1/(e) }; \
+      } while (0)
+
+#define PAL_UNUSED_ARG(x) (void)(x)
+
+
+
+
+
+//for non recoverable errors
+#define PAL_LOG_ASSERT( ARGS...) \
+{ \
+    tr_err(ARGS); \
+	assert(0);\
+}
+
+
+
+#define PAL_LOG_ERR_FUNC  tr_err
+#define PAL_LOG_WARN_FUNC tr_warn
+#define PAL_LOG_INFO_FUNC tr_info
+#define PAL_LOG_DBG_FUNC  tr_debug
+
+// Little trick with mbed-trace error level is equal to function name handling the same level of log output
+#define PAL_LOG_LEVEL_ERR  TRACE_LEVEL_ERROR
+#define PAL_LOG_LEVEL_WARN TRACE_LEVEL_WARN
+#define PAL_LOG_LEVEL_INFO TRACE_LEVEL_INFO
+#define PAL_LOG_LEVEL_DBG  TRACE_LEVEL_DEBUG
+
+#define PAL_LOG_ERR( ARGS...)   PAL_LOG_ERR_FUNC(ARGS);
+#define PAL_LOG_WARN( ARGS...)  PAL_LOG_WARN_FUNC(ARGS);
+#define PAL_LOG_INFO( ARGS...)  PAL_LOG_INFO_FUNC(ARGS);
+#define PAL_LOG_DBG( ARGS...)   PAL_LOG_DBG_FUNC(ARGS);
+
+
+#define PAL_LOG(LOG_LEVEL, ARGS...)  tracef(PAL_LOG_LEVEL_##LOG_LEVEL, "PAL" , ARGS);
+
+
+#ifdef DEBUG
+#ifdef VERBOSE
+#define PAL_PRINTF( ARGS...) \
+        #define PAL_PRINTF(fmt, ...) PAL_LOG(DBG, "%s:%d: " fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__);
+#else
+#define PAL_PRINTF( ARGS...) \
+		PAL_LOG(DBG, ARGS);
+#endif
+#else
+	#define PAL_PRINTF( ARGS...)
+#endif
+
+#define DEBUG_PRINT(ARGS...) PAL_PRINTF(ARGS)
+
+#define PAL_PTR_ADDR_ALIGN_UINT8_TO_UINT32 __attribute__((aligned(4)))
+
+#define PAL_INT32_BITS (sizeof(int32_t) * CHAR_BIT)
+
+#ifdef DEBUG
+
+
+#define PAL_VALIDATE_CONDITION_WITH_ERROR(condition, error) \
+    {\
+        if ((condition)) \
+        { \
+            PAL_LOG(ERR,"(%s,%d): Parameters  values is illegal\r\n",__FUNCTION__,__LINE__); \
+            return error; \
+        } \
+    }
+#define PAL_VALIDATE_ARGUMENTS(condition) PAL_VALIDATE_CONDITION_WITH_ERROR(condition,PAL_ERR_INVALID_ARGUMENT)
+
+#else
+    #define PAL_VALIDATE_ARGUMENTS(condition) 
+    #define PAL_VALIDATE_CONDITION_WITH_ERROR(condition, error) 
+#endif
+
+
+#define PAL_VALIDATE_ARG_RLZ(condition, error) \
+{\
+	if ((condition)) \
+	{ \
+		return error; \
+	} \
+}
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif //_PAL_MACROS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_network.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,396 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef _PAL_SOCKET_H
+#define _PAL_SOCKET_H
+
+#ifndef _PAL_H
+    #error "Please do include call this file directly, use pal.h instead"
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! \file pal_network.h
+*  \brief PAL network.
+*   This file contains the network APIs and it is a part of the PAL service API.
+*   It provides network functionalities for UDP and TCP sockets and connections.
+*/
+
+//! PAL network socket API \n
+//! PAL network sockets configurations options: \n
+//! Set PAL_NET_TCP_AND_TLS_SUPPORT to true if TCP is supported by the platform and is required. \n
+//! Set PAL_NET_ASYNCHRONOUS_SOCKET_API to true if asynchronous socket API is supported by the platform and is required: Currently MANDATORY.
+//! Set PAL_NET_DNS_SUPPORT to true if DNS URL lookup API is supported.
+
+typedef uint32_t palSocketLength_t; /*! The length of data. */
+typedef void* palSocket_t; /*! PAL socket handle type. */
+
+#define  PAL_NET_MAX_ADDR_SIZE 32 // check if we can make this more efficient
+
+typedef struct palSocketAddress {
+    unsigned short    addressType;    /*! Address family for the socket. */
+    char              addressData[PAL_NET_MAX_ADDR_SIZE];  /*! Address (based on protocol). */
+} palSocketAddress_t; /*! Address data structure with enough room to support IPV4 and IPV6. */
+
+typedef struct palNetInterfaceInfo{
+    char interfaceName[16]; //15 + ‘\0’
+    palSocketAddress_t address;
+    uint32_t addressSize;
+} palNetInterfaceInfo_t;
+
+typedef enum {
+    PAL_AF_UNSPEC = 0,
+    PAL_AF_INET = 2,    /*! Internet IP Protocol.   */
+    PAL_AF_INET6 = 10, /*! IP version 6.    */
+} palSocketDomain_t;/*! Network domains supported by PAL. */
+
+typedef enum {
+#if PAL_NET_TCP_AND_TLS_SUPPORT
+    PAL_SOCK_STREAM = 1,    /*! Stream socket.   */
+    PAL_SOCK_STREAM_SERVER = 99,    /*! Stream socket.   */
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+    PAL_SOCK_DGRAM = 2  /*! Datagram socket.     */
+} palSocketType_t;/*! Socket types supported by PAL. */
+
+
+typedef enum {
+    PAL_SO_REUSEADDR = 0x0004,  /*! Allow local address reuse. */
+#if PAL_NET_TCP_AND_TLS_SUPPORT // Socket options below supported only if TCP is supported.
+    PAL_SO_KEEPALIVE = 0x0008, /*! Keep TCP connection open even if idle using periodic messages. */
+    PAL_SO_KEEPIDLE = 0x0009,  /*! The time (in seconds) the connection needs to remain idle before TCP starts sending keepalive probes, if the socket option SO_KEEPALIVE has been set on this socket. */
+    PAL_SO_KEEPINTVL = 0x0010, /*! The time (in seconds) between individual keepalive probes */
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+    PAL_SO_SNDTIMEO = 0x1005,  /*! Send timeout. */
+    PAL_SO_RCVTIMEO = 0x1006,  /*! Receive timeout. */
+} palSocketOptionName_t;/*! Socket options supported by PAL. */
+
+#define PAL_NET_DEFAULT_INTERFACE 0xFFFFFFFF
+
+#define PAL_IPV4_ADDRESS_SIZE 4
+#define PAL_IPV6_ADDRESS_SIZE 16
+
+typedef uint8_t palIpV4Addr_t[PAL_IPV4_ADDRESS_SIZE];
+typedef uint8_t palIpV6Addr_t[PAL_IPV6_ADDRESS_SIZE];
+
+
+/*! Register a network interface for use with PAL sockets. Must be called before other socket functions. Most APIs will not work before a single interface is added.
+* @param[in] networkInterfaceContext The network interface to be added ( this is an OS specific value). In mbed OS the networkInterfaceContext is the `NetworkInterface` object pointer for the network adapter [**Note:** We assume that connect has already been called on this interface object]. In Linux the networkInterfaceContext is the string name of the network interface (e.g. "eth0"). For more examples see the PAL palTestGetNetWorkInterfaceContext function implementations in the platform bring-up examples (found in Examples\PlatformBSP). The palTestGetNetWorkInterfaceContext function illustrates the expected value for networkInterfaceContext for that target. If a context is not applicable on a target configuration use NULL.
+* @param[out] interfaceIndex Contains the index assigned to the interface in case it has been assigned successfully. This index can be used, when creating a socket, to bind the socket to the interface.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_registerNetworkInterface(void* networkInterfaceContext, uint32_t* interfaceIndex);
+
+/*! Set a port to `palSocketAddress_t`. \n
+* You can set it either directly or via the `palSetSockAddrIPV4Addr` or `palSetSockAddrIPV6Addr` functions.
+* @param[in,out] address The address to set.
+* @param[in] port The port number to set.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+\note To set the socket correctly, the `addressType` field of the address must be set correctly.
+*/
+palStatus_t pal_setSockAddrPort(palSocketAddress_t* address, uint16_t port);
+
+
+/*! Set an IPv4 address to `palSocketAddress_t` and `addressType` to IPv4.
+* @param[in,out] address The address to set.
+* @param[in] ipV4Addr The address value to set.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_setSockAddrIPV4Addr(palSocketAddress_t* address, palIpV4Addr_t ipV4Addr);
+
+/*! Get an IPv4 address from `palSocketAddress_t`.
+* @param[in] address The address to set.
+* @param[out] ipV4Addr The address that is set in `address`.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_getSockAddrIPV4Addr(const palSocketAddress_t* address, palIpV4Addr_t ipV4Addr);
+
+
+/*! Set an IPv6 address to `palSocketAddress_t` and the `addressType` to IPv6.
+* @param[in,out] address The address to set.
+* @param[in] ipV6Addr The address value to set.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_setSockAddrIPV6Addr(palSocketAddress_t* address, palIpV6Addr_t ipV6Addr);
+
+/*! Get an IPv6 address from `palSocketAddress_t`.
+* @param[in] address The address to set.
+* @param[out] ipV6Addr The address that is set in `address`.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_getSockAddrIPV6Addr(const palSocketAddress_t* address, palIpV6Addr_t ipV6Addr);
+
+
+/*! Get a port from `palSocketAddress_t`.
+* @param[in] address The address to set.
+* @param[out] port The port that is set in `address`.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_getSockAddrPort(const palSocketAddress_t* address, uint16_t* port);
+
+/*! Get a network socket.
+* @param[in] domain The domain for the created socket (see `palSocketDomain_t` for supported types).
+* @param[in] type The type of the created socket (see `palSocketType_t` for supported types).
+* @param[in] nonBlockingSocket If true, the socket is created as non-blocking (with O_NONBLOCK set).
+* @param[in] interfaceNum The number of the network interface used for this socket (info in interfaces supported via `pal_getNumberOfNetInterfaces` and `pal_getNetInterfaceInfo`). Select PAL_NET_DEFAULT_INTERFACE for the default interface.
+* @param[out] socket The socket is returned through this output parameter.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_socket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palSocket_t* socket);
+
+/*!  Set the value for a given socket option on a given network socket.
+* @param[in] socket The socket for which to get options.
+* @param[in] optionName The identification of the socket option for which we are getting the value (see enum palSocketOptionName_t for supported types).
+* @param[in] optionValue The buffer holding the option value to set for the given option.
+* @param[in] optionLength  The size of the buffer provided for `optionValue`.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_setSocketOptions(palSocket_t socket, int optionName, const void* optionValue, palSocketLength_t optionLength);
+
+/*! Check if a given socket is non-blocking.
+* @param[in] socket The socket to check.
+* @param[out] isNonBlocking True if the socket is non-blocking, otherwise false.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_isNonBlocking(palSocket_t socket, bool* isNonBlocking);
+
+/*! Bind a given socket to a local address.
+* @param[in] socket The socket to bind.
+* @param[in] myAddress The address to bind to.
+* @param[in] addressLength The length of the address passed in `myAddress`.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_bind(palSocket_t socket, palSocketAddress_t* myAddress, palSocketLength_t addressLength);
+
+/*! Receive a payload from the given socket.
+* @param[in] socket The socket to receive from. [The sockets passed to this function should be of type PAL_SOCK_DGRAM (the implementation may support other types as well).]
+* @param[out] buffer The buffer for the payload data.
+* @param[in] length The length of the buffer for the payload data.
+* @param[out] from The address that sent the payload.
+* @param[in, out] fromLength The length of the `from` address. Contains the amount of data actually written to the `from` address.
+* @param[out] bytesReceived The actual amount of payload data received in the buffer.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_receiveFrom(palSocket_t socket, void* buffer, size_t length, palSocketAddress_t* from, palSocketLength_t* fromLength, size_t* bytesReceived);
+
+/*! Send a payload to the given address using the given socket.
+* @param[in] socket The socket to use for sending the payload. [The sockets passed to this function should be of type PAL_SOCK_DGRAM (the implementation may support other types as well).]
+* @param[in] buffer The buffer for the payload data.
+* @param[in] length The length of the buffer for the payload data.
+* @param[in] to The address to which the payload should be sent.
+* @param[in] toLength The length of the `to` address.
+* @param[out] bytesSent The actual amount of payload data sent.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_sendTo(palSocket_t socket, const void* buffer, size_t length, const palSocketAddress_t* to, palSocketLength_t toLength, size_t* bytesSent);
+
+/*! Close a network socket.
+* @param[in,out] The socket to be closed.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+\note Receives `palSocket_t*`, NOT `palSocket_t`, so that it can zero the socket to avoid re-use.
+*/
+palStatus_t pal_close(palSocket_t* socket);
+
+/*! Get the number of current network interfaces.
+* @param[out] numInterfaces The number of interfaces.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_getNumberOfNetInterfaces(uint32_t* numInterfaces);
+
+/*! Get information regarding the socket at the index/interface number given (this number is returned when registering the socket).
+* @param[in] interfaceNum The number of the interface to get information for.
+* @param[out] interfaceInfo Set to the information for the given interface number.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t* interfaceInfo);
+
+
+#define PAL_NET_SOCKET_SELECT_MAX_SOCKETS 8
+#define PAL_NET_SOCKET_SELECT_RX_BIT (1)
+#define PAL_NET_SOCKET_SELECT_TX_BIT (2)
+#define PAL_NET_SOCKET_SELECT_ERR_BIT (4)
+
+#define PAL_NET_SELECT_IS_RX(socketStatus, index)   ((socketStatus[index] & PAL_NET_SOCKET_SELECT_RX_BIT) != 0) /*! Check if RX bit is set in select result for a given socket index. */
+#define PAL_NET_SELECT_IS_TX(socketStatus, index)   ((socketStatus[index] & PAL_NET_SOCKET_SELECT_TX_BIT) != 0) /*! Check if TX bit is set in select result for a given socket index. */
+#define PAL_NET_SELECT_IS_ERR(socketStatus, index)  ((socketStatus[index] & PAL_NET_SOCKET_SELECT_ERR_BIT) != 0) /*! Check if ERR bit is set in select result for a given socket index. */
+
+#if PAL_NET_TCP_AND_TLS_SUPPORT // The functionality below is supported only if TCP is supported.
+
+
+/*! Use the given socket to listen for incoming connections. This may also limit the queue of incoming connections.
+* @param[in] socket The socket to listen to. [The sockets passed to this function should be of type PAL_SOCK_STREAM_SERVER (the implementation may support other types as well).]
+* @param[in] backlog The amount of pending connections that can be saved for the socket.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_listen(palSocket_t socket, int backlog);
+
+/*! Accept a connection on the given socket.
+* @param[in] socket The socket on which to accept the connection. (The socket must be already created and bound and listen has must have been called on it.) [The sockets passed to this function should be of type PAL_SOCK_STREAM_SERVER (the implementation may support other types as well).]
+* @param[out] address The source address of the incoming connection.
+* @param[in, out] addressLen The length of the address field on input, the length of the data returned on output.
+* @param[out] acceptedSocket The socket of the accepted connection.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_accept(palSocket_t socket, palSocketAddress_t* address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket);
+
+/*! Open a connection from the given socket to the given address.
+* @param[in] socket The socket to use for connection to the given address. [The sockets passed to this function should be of type PAL_SOCK_STREAM (the implementation may support other types as well).]
+* @param[in] address The destination address of the connection.
+* @param[in] addressLen The length of the address field.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_connect(palSocket_t socket, const palSocketAddress_t* address, palSocketLength_t addressLen);
+
+/*! Receive data from the given connected socket.
+* @param[in] socket The connected socket on which to receive data. [The sockets passed to this function should be of type PAL_SOCK_STREAM (the implementation may support other types as well).]
+* @param[out] buf The output buffer for the message data.
+* @param[in] len The length of the input data buffer.
+* @param[out] recievedDataSize The length of the data actually received.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_recv(palSocket_t socket, void* buf, size_t len, size_t* recievedDataSize);
+
+/*! Send a given buffer via the given connected socket.
+* @param[in] socket The connected socket on which to send data. [The sockets passed to this function should be of type PAL_SOCK_STREAM (the implementation may support other types as well).]
+* @param[in] buf The output buffer for the message data.
+* @param[in] len The length of the input data buffer.
+* @param[out] sentDataSize The length of the data sent.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_send(palSocket_t socket, const void* buf, size_t len, size_t* sentDataSize);
+
+
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+
+/*! The type of the callback funciton passed when creating asynchronous sockets.
+* @param[in] argument The user provided argument passed to the callback function.
+*/
+typedef void(*palAsyncSocketCallback_t)(void*);
+
+/*! Get an asynchronous network socket.
+* @param[in] domain The domain for the created socket (see enum `palSocketDomain_t` for supported types).
+* @param[in] type The type for the created socket (see enum `palSocketType_t` for supported types).
+* @param[in] nonBlockingSocket If true, the socket is created as non-blocking (with O_NONBLOCK set).
+* @param[in] interfaceNum The number of the network interface used for this socket (info in interfaces supported via `pal_getNumberOfNetInterfaces` and `pal_getNetInterfaceInfo`). Select PAL_NET_DEFAULT_INTERFACE for the default interface.
+* @param[in] callback A callback function that is called when any supported event happens in the given asynchronous socket (see `palAsyncSocketCallbackType` enum for the types of events supported).
+* @param[out] socket The socket is returned through this output parameter.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_asynchronousSocket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, palSocket_t* socket);
+
+/*! Get an asynchronous network socket that passes the provided `callbackArgument` to the provided callback on callback events.
+* @param[in] domain The domain for the created socket (see enum `palSocketDomain_t` for supported types).
+* @param[in] type The type for the created socket (see enum `palSocketType_t` for supported types).
+* @param[in] nonBlockingSocket If true, the socket is created as non-blocking (with O_NONBLOCK set).
+* @param[in] interfaceNum The number of the network interface used for this socket (info in interfaces supported via `pal_getNumberOfNetInterfaces` and `pal_getNetInterfaceInfo`). Select PAL_NET_DEFAULT_INTERFACE for the default interface.
+* @param[in] callback A callback function that is called when any supported event happens in the given asynchronous socket.
+* @param[in] callbackArgument The argument with which the callback function is called when any supported event happens in the given asynchronous socket.
+* @param[out] socket The socket is returned through this output parameter.
+\return PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure.
+*/
+palStatus_t pal_asynchronousSocketWithArgument(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback,void* callbackArgument, palSocket_t* socket);
+
+
+
+#endif
+
+#if PAL_NET_DNS_SUPPORT
+
+/*! This function translates from a URL to `palSocketAddress_t` which can be used with PAL sockets. It supports both IP address as strings and URLs (using DNS lookup).
+* @param[in] url The URL (or IP address string) to be translated to a `palSocketAddress_t`.
+* @param[out] address The address for the output of the translation.
+*/
+palStatus_t pal_getAddressInfo(const char* url, palSocketAddress_t* address, palSocketLength_t* addressLength);
+
+/*! Prototype of the callback function invoked when querying address info asynchronously (pal_getAddressInfoAsync).
+* @param[in] url The user provided url (or IP address string) that was requested to be translated
+* @param[in] address The address for the output of the translation
+* @param[in] addressLength The length of the address for the output of the translation in bytes
+* @param[in] status The status of the operation - PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure
+* @param[in] callbackArgument The user callback argument
+*/
+#ifndef PAL_DNS_API_V2
+typedef void(*palGetAddressInfoAsyncCallback_t)(const char* url, palSocketAddress_t* address, palSocketLength_t* addressLength, palStatus_t status, void* callbackArgument);
+
+/*! This function translates from a URL to `palSocketAddress_t` which can be used with PAL sockets. It supports both IP address as strings and URLs (using DNS lookup). \n
+\note The function is a non-blocking function.
+* @param[in] url The user provided url (or IP address string) to be translated
+* @param[out] address The address for the output of the translation
+* @param[out] addressLength The length of the address for the output of the translation in bytes
+* @param[in] callback The user provided callback to be invoked once the function has completed
+* @param[in] callbackArgument The user provided callback argument which will be passed back to the (user provided) callback function
+*/
+palStatus_t pal_getAddressInfoAsync(const char* url, palSocketAddress_t* address, palSocketLength_t* addressLength, palGetAddressInfoAsyncCallback_t callback, void* callbackArgument);
+#else
+typedef int32_t palDNSQuery_t; /*! PAL DNS query handle, may be used to cancel the asynchronous DNS query. */
+
+/*! Prototype of the callback function invoked when querying address info asynchronously (pal_getAddressInfoAsync).
+* @param[in] url The user provided url (or IP address string) that was requested to be translated
+* @param[out] address The address for the output of the translation
+* @param[out] status The status of the operation - PAL_SUCCESS (0) in case of success or a specific negative error code in case of failure
+* @param[in] callbackArgument The user callback argument
+*/
+typedef void(*palGetAddressInfoAsyncCallback_t)(const char* url, palSocketAddress_t* address, palStatus_t status, void* callbackArgument);
+
+/*! structure used by pal_getAddressInfoAsync
+* @param[in] url The user provided url (or IP address string) that was requested to be translated
+* @param[out] address The address for the output of the translation
+* @param[in] callback address of palGetAddressInfoAsyncCallback_t.
+* @param[in] callbackArgument The user callback argument of palGetAddressInfoAsyncCallback_t
+* @param[out] queryHandle handler ID, which can be used for calcel request.
+*/
+typedef struct pal_asyncAddressInfo
+{
+    char* url;
+    palSocketAddress_t* address;
+    palGetAddressInfoAsyncCallback_t callback;
+    void* callbackArgument;
+    palDNSQuery_t *queryHandle;
+} pal_asyncAddressInfo_t;
+
+/*! This function translates from a URL to `palSocketAddress_t` which can be used with PAL sockets. It supports both IP address as strings and URLs (using DNS lookup). \n
+\note The function is a non-blocking function.
+* @param[in] url The user provided url (or IP address string) to be translated
+* @param[out] address The address for the output of the translation
+* @param[in] callback The user provided callback to be invoked once the function has completed
+* @param[out] queryHandle DNS query handler. Caller must take of care allocation. If not used then use NULL.
+*/
+palStatus_t pal_getAddressInfoAsync(const char* url, 
+                                     palSocketAddress_t* address, 
+                                     palGetAddressInfoAsyncCallback_t callback, 
+                                     void* callbackArgument, 
+                                     palDNSQuery_t* queryHandle);
+
+/*! This function is cancelation for pal_getAddressInfoAsync. 
+* @param[in] queryHandle Id of ongoing DNS query.
+*/
+palStatus_t pal_cancelAddressInfoAsync(palDNSQuery_t queryHandle);
+#endif  // #ifndef PAL_DNS_API_V2
+
+#endif  // PAL_NET_DNS_SUPPORT
+
+#ifdef __cplusplus
+}
+#endif
+#endif //_PAL_SOCKET_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_rtos.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,437 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef _PAL_RTOS_H
+#define _PAL_RTOS_H
+
+#ifndef _PAL_H
+    #error "Please do not include this file directly, use pal.h instead"
+#endif
+
+#include <stdint.h>
+#include <string.h> //memcpy
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pal.h" //added for PAL_INITIAL_RANDOM_SIZE value
+
+/*! \file pal_rtos.h
+*  \brief PAL RTOS.
+*   This file contains the real-time OS APIs and is a part of the PAL service API.
+*   It provides thread, timers, semaphores, mutexes and memory pool management APIs.
+*   Random API and ROT (root of trust) are also provided.  
+*/
+
+
+//! Wait forever define. Used for semaphores and mutexes.
+#define PAL_TICK_TO_MILLI_FACTOR 1000
+
+//! Primitive ID type declarations.
+typedef uintptr_t palThreadID_t;
+typedef uintptr_t palTimerID_t;
+typedef uintptr_t palMutexID_t;
+typedef uintptr_t palSemaphoreID_t;
+typedef uintptr_t palMemoryPoolID_t;
+typedef uintptr_t palMessageQID_t;
+
+//! Timer types supported in PAL.
+typedef enum  palTimerType {
+    palOsTimerOnce = 0, /*! One shot timer. */
+	palOsTimerPeriodic = 1 /*! Periodic (repeating) timer. */
+} palTimerType_t;
+
+
+
+//! Device key types supported in PAL.
+typedef enum  palDeviceKeyType {
+    palOsStorageEncryptionKey128Bit = 0, /*! 128bit storage encryption key derived from RoT. */
+    palOsStorageSignatureKey128Bit = 1, /*! 128bit storage signature key derived from RoT. */
+    palOsStorageHmacSha256 = 2
+} palDevKeyType_t;
+
+//! PAL timer function prototype.
+typedef void(*palTimerFuncPtr)(void const *funcArgument);
+
+//! PAL thread function prototype.
+typedef void(*palThreadFuncPtr)(void const *funcArgument); 
+
+//! Available priorities in PAL implementation, each priority can appear only once.
+typedef enum pal_osPriority {
+    PAL_osPriorityFirst = 0,
+    PAL_osPriorityIdle = PAL_osPriorityFirst,
+    PAL_osPriorityLow = 1,
+    PAL_osPriorityReservedTRNG = 2,
+    PAL_osPriorityBelowNormal = 3,
+    PAL_osPriorityNormal = 4,
+    PAL_osPriorityAboveNormal = 5,
+    PAL_osPriorityReservedDNS = 6, /*! Reserved for PAL's internal use */
+    PAL_osPriorityReservedSockets = 7, /*! Reserved for PAL's internal use */
+    PAL_osPriorityHigh = 8,
+    PAL_osPriorityReservedHighResTimer = 9, /*! Reserved for PAL's internal use */
+    PAL_osPriorityRealtime = 10,
+    PAL_osPrioritylast = PAL_osPriorityRealtime,
+    PAL_osPriorityError = 0x84
+} palThreadPriority_t; /*! Thread priority levels for PAL threads - each thread must have a different priority. */
+
+//! Thread local store struct.
+//! Can be used to hold for example state and configurations inside the thread.
+typedef struct pal_threadLocalStore{
+    void* storeData;
+} palThreadLocalStore_t;
+
+typedef struct pal_timeVal{
+    int32_t    pal_tv_sec;      /*! Seconds. */
+    int32_t    pal_tv_usec;     /*! Microseconds. */
+} pal_timeVal_t;
+
+
+//------- system general functions
+/*! Initiates a system reboot.
+* Application can provide their own implementation by defining PAL_USE_APPLICATION_REBOOT and
+* providing implementation for pal_plat_osApplicationReboot() function.
+*/
+void pal_osReboot(void);
+
+//------- system tick functions
+/*! Get the RTOS kernel system timer counter.
+* \note The system needs to supply a 64-bit tick counter. If only a 32-bit counter is supported,
+* \note the counter wraps around very often (for example, once every 42 sec for 100Mhz).
+* \return The RTOS kernel system timer counter.
+*/
+uint64_t pal_osKernelSysTick(void);
+
+
+/*! Converts a value from microseconds to kernel system ticks.
+*
+* @param[in] microseconds The number of microseconds to convert into system ticks.
+*
+* \return Converted value in system ticks.
+*/
+uint64_t pal_osKernelSysTickMicroSec(uint64_t microseconds);
+
+/*! Converts value from kernel system ticks to milliseconds.
+*
+* @param[in] sysTicks The number of kernel system ticks to convert into milliseconds.
+*
+* \return Converted value in system milliseconds.
+*/
+uint64_t pal_osKernelSysMilliSecTick(uint64_t sysTicks);
+
+/*! Get the system tick frequency.
+* \return The system tick frequency.
+*
+* \note The system tick frequency MUST be more than 1KHz (at least one tick per millisecond).
+*/
+uint64_t pal_osKernelSysTickFrequency(void);
+
+
+/*! Get the system time.
+* \return The system 64-bit counter indicating the current system time in seconds on success.
+*         Zero value when the time is not set in the system.
+* \note If the delta between secure time value previously set in the system and current system time is greater than PAL_LAST_SAVED_TIME_LATENCY_SEC
+* then secure time value will be overridden with current system time
+*/
+uint64_t pal_osGetTime(void);
+
+/*! \brief Set the current system time by accepting seconds since January 1st 1970 UTC+0.
+*
+* @param[in] seconds Seconds from January 1st 1970 UTC+0.
+*
+* \return PAL_SUCCESS when the time was set successfully. \n
+*         PAL_ERR_INVALID_TIME when there is a failure setting the system time.
+*/
+palStatus_t pal_osSetTime(uint64_t seconds);
+
+/*! \brief  Initialization the time module
+*   After boot, the time in RAM will be initialized with the max value between RTC and SOTP SAVED_TIME. If no RTC is present, RTC time is zero.
+*   After initialization the time module will start counting ticks.
+*   The answer to get_time should be calculated by the sum of the initial value (RTC or SOTP) + the number of ticks converted into seconds.
+*
+* \return PAL_SUCCESS when initialization succeed. \n
+*
+* \note
+*/
+palStatus_t pal_initTime(void);
+
+/*! \brief save weak time according to design
+*   Time Forward (a)
+*   set the time (in RAM) unconditionally. Save the new time in SOTP if the change (between new time and current time in RAM) is greater than 24 hours.
+*   Set the time to RTC if the change is greater than 100 seconds. This limitation is to avoid multiple writes to the SOTP and RTC and not related to security.
+*   Time Forward (b)
+*   If (a) did not happen, save the time into SOTP if new time is greater from SAVED_TIME by a week (604800 seconds).
+*   Time Backwards
+*   set the device time on the device (RAM) and save the time in SOTP only if the change
+*   (between new time and current time in RAM) is smaller than 3 minutes for each day lapsed from the last change
+*   done via pal_osWeakSetTime. RTC is never set backwards by pal_osWeakSetTime().
+*
+* @param[in] uint64_t setTimeInSeconds  Seconds from January 1st 1970 UTC+0.
+*
+* \return PAL_SUCCESS when set weak  succeed. \n
+*
+* \note To implement this, when the new time is saved in SOTP by the function pal_osWeakSetTime two records with different types must be saved in SOTP:
+* \note 1.- The new time (the same record as in factory setup)
+* \note 2.- The time this action was performed, in order to enforce the 24 hours limitation. Record LAST_TIME_BACK.
+*/
+palStatus_t pal_osSetWeakTime(uint64_t setTimeInSeconds);
+
+/*! \brief save strong time according to design
+*   Set the time (in RAM) unconditionally. Save in SOTP or/and RTC the new time under the following conditions:
+•	Time forward – if time difference between current time in SOTP (not device time) and new time is greater than a day
+•	Time backward – if time difference between current time and new time is greater than one minute.
+*   If the time is saved in SOTP (forward or backwards), the record LAST_TIME_BACK must be saved.
+*
+** @param[in] uint64_t setTimeInSeconds - Seconds from January 1st 1970 UTC+0.
+**
+* \return PAL_SUCCESS when set strong succeed. \n
+*
+* \note   The limitations are aimed to reduce the number of write operations to the SOTP and not related to security.
+*   This function will be called when receiving time from a server that is completely trusted.
+*/
+palStatus_t pal_osSetStrongTime(uint64_t setTimeInSeconds);
+
+/*! \brief Allocates memory for the thread stack, creates and starts the thread function (inside the PAL platform wrapper function).
+*
+* @param[in] function A function pointer to the thread callback function.
+* @param[in] funcArgument An argument for the thread function.
+* @param[in] priority The priority of the thread.
+* @param[in] stackSize The stack size of the thread, can NOT be 0.
+* @param[in] store MUST be NULL - this functionality is not supported.
+* @param[out] threadID: The created thread ID handle. In case of error, this value is NULL.
+*
+* \return PAL_SUCCESS when the thread was created successfully. \n
+*
+* \note When the priority of the created thread function is higher than the current running thread, the
+*       created thread function starts instantly and becomes the new running thread.
+* \note Calling \c pal_osThreadTerminate() releases the thread stack.
+*/
+palStatus_t pal_osThreadCreateWithAlloc(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, palThreadLocalStore_t* store, palThreadID_t* threadID);
+
+/*! Terminate and free allocated data for the thread.
+*
+* @param[in] threadID The thread ID to stop and terminate.
+*
+* \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure. \n
+*
+* \note  pal_osThreadTerminate is a non blocking operation, pal_osThreadTerminate sends cancellation request to the thread, 
+*        usually the thread exits immediately, but the system does not always guarantee this
+*/
+palStatus_t pal_osThreadTerminate(palThreadID_t* threadID);
+
+/*! Get the ID of the current thread.
+* \return The ID of the current thread. In case of error, return PAL_MAX_UINT32.
+*/
+palThreadID_t pal_osThreadGetId(void);
+
+/*! Wait for a specified time period in milliseconds.
+*
+* @param[in] milliseconds The number of milliseconds to wait before proceeding.
+*
+* \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_osDelay(uint32_t milliseconds);
+
+/*! Create a timer.
+*
+* @param[in] function A function pointer to the timer callback function.
+* @param[in] funcArgument An argument for the timer callback function.
+* @param[in] timerType The timer type to be created, periodic or oneShot.
+* @param[out] timerID The created timer ID handle. In case of error, this value is NULL.
+*
+* \return PAL_SUCCESS when the timer was created successfully. \n
+*         PAL_ERR_NO_MEMORY when there is no memory resource available to create a timer object.
+*
+* \note The timer function runs according to the platform resources of stack-size and priority.
+*/
+palStatus_t pal_osTimerCreate(palTimerFuncPtr function, void* funcArgument, palTimerType_t timerType, palTimerID_t* timerID);
+
+/*! Start or restart a timer.
+*
+* @param[in] timerID The handle for the timer to start.
+* @param[in] millisec The amount of time in milliseconds to set the timer to. MUST be larger than 0.
+*                      In case of 0 value, the error PAL_ERR_RTOS_VALUE is returned.
+*
+* \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_osTimerStart(palTimerID_t timerID, uint32_t millisec);
+
+/*! Stop a timer.
+* @param[in] timerID The handle for the timer to stop.
+* \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_osTimerStop(palTimerID_t timerID);
+
+/*! Delete the timer object.
+*
+* @param[inout] timerID The handle for the timer to delete. In success, `*timerID` = NULL.
+*
+* \return PAL_SUCCESS when timer was deleted successfully. \n
+*         PAL_ERR_RTOS_PARAMETER when the `timerID` is incorrect.
+*/
+palStatus_t pal_osTimerDelete(palTimerID_t* timerID);
+
+/*! Create and initialize a mutex object.
+*
+* @param[out] mutexID The created mutex ID handle. In case of error, this value is NULL.
+*
+* \return PAL_SUCCESS when the mutex was created successfully. \n
+*         PAL_ERR_NO_MEMORY when there is no memory resource available to create a mutex object.
+*/
+palStatus_t pal_osMutexCreate(palMutexID_t* mutexID);
+
+/*! Wait until a mutex becomes available.
+*
+* @param[in] mutexID The handle for the mutex.
+* @param[in] millisec The timeout for waiting to the mutex to be available. PAL_RTOS_WAIT_FOREVER can be used as a parameter.
+*
+* \return PAL_SUCCESS(0) in case of success or one of the following error codes in case of failure: \n
+*         PAL_ERR_RTOS_RESOURCE - mutex was not availabe but no timeout was set. \n
+*         PAL_ERR_RTOS_TIMEOUT - mutex was not available until the timeout. \n
+*         PAL_ERR_RTOS_PARAMETER - mutex ID is invalid. \n
+*         PAL_ERR_RTOS_ISR - cannot be called from the interrupt service routines.
+*/
+palStatus_t pal_osMutexWait(palMutexID_t mutexID, uint32_t millisec);
+
+/*! Release a mutex that was obtained by `osMutexWait`.
+*
+* @param[in] mutexID The handle for the mutex.
+* \return PAL_SUCCESS(0) in case of success and another negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_osMutexRelease(palMutexID_t mutexID);
+
+/*!Delete a mutex object.
+*
+* @param[inout] mutexID The mutex handle to delete. In success, `*mutexID` = NULL.
+*
+* \return PAL_SUCCESS when the mutex was deleted successfully. \n
+*         PAL_ERR_RTOS_RESOURCE - mutex is already released. \n
+*         PAL_ERR_RTOS_PARAMETER - mutex ID is invalid. \n
+*         PAL_ERR_RTOS_ISR - cannot be called from the interrupt service routines. \n
+* \note After this call, the `mutex_id` is no longer valid and cannot be used.
+*/
+palStatus_t pal_osMutexDelete(palMutexID_t* mutexID);
+
+/*! Create and initialize a semaphore object.
+*
+* @param[in] count The number of available resources.
+* @param[out] semaphoreID The created semaphore ID handle. In case of error, this value is NULL.
+*
+* \return PAL_SUCCESS when the semaphore was created successfully. \n
+*         PAL_ERR_NO_MEMORY when there is no memory resource available to create a semaphore object.
+*/
+palStatus_t pal_osSemaphoreCreate(uint32_t count, palSemaphoreID_t* semaphoreID);
+
+/*! Wait until a semaphore token becomes available.
+*
+* @param[in] semaphoreID The handle for the semaphore.
+* @param[in] millisec The timeout for the waiting operation if the timeout 
+                       expires before the semaphore is released and error is 
+                       returned from the function. PAL_RTOS_WAIT_FOREVER can be used.
+* @param[out] countersAvailable The number of semaphores available at the call if a
+                                  semaphore is available. If the semaphore is not available (timeout/error) zero is returned. This parameter can be NULL 
+* \return PAL_SUCCESS(0) in case of success and one of the following error codes in case of failure: \n
+*       PAL_ERR_RTOS_TIMEOUT - the semaphore was not available until timeout. \n
+*       PAL_ERR_RTOS_PARAMETER - the semaphore ID is invalid.
+*/
+palStatus_t pal_osSemaphoreWait(palSemaphoreID_t semaphoreID, uint32_t millisec, int32_t* countersAvailable);
+
+/*! Release a semaphore token.
+*
+* @param[in] semaphoreID The handle for the semaphore
+*
+* \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_osSemaphoreRelease(palSemaphoreID_t semaphoreID);
+
+/*! Delete a semaphore object.
+*
+* @param[inout] semaphoreID The semaphore handle to delete. In success, `*semaphoreID` = NULL.
+*
+* \return PAL_SUCCESS when the semaphore was deleted successfully. \n
+*         PAL_ERR_RTOS_RESOURCE - the semaphore was already released. \n
+*         PAL_ERR_RTOS_PARAMETER - the semaphore ID is invalid.
+* \note After this call, the `semaphore_id` is no longer valid and cannot be used.
+*/
+palStatus_t pal_osSemaphoreDelete(palSemaphoreID_t* semaphoreID);
+
+/*! Perform an atomic increment for a signed 32-bit value.
+*
+* @param[in,out] valuePtr The address of the value to increment.
+* @param[in] increment The number by which to increment.
+*
+* \return The value of `valuePtr` after the increment operation.
+*/
+int32_t pal_osAtomicIncrement(int32_t* valuePtr, int32_t increment);
+
+
+/*! Generate random number into given buffer with given size in bytes.
+*
+* @param[out] randomBuf A buffer to hold the generated number.
+* @param[in] bufSizeBytes The size of the buffer and the size of the required random number to generate.
+*
+\note `pal_init()` MUST be called before this function
+\return PAL_SUCCESS on success, a negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_osRandomBuffer(uint8_t *randomBuf, size_t bufSizeBytes);
+
+
+/*! Return a device unique key derived from the root of trust.
+*
+* @param[in] keyType The type of key to derive.
+* @param[in,out] key A 128-bit OR 256-bit buffer to hold the derived key, size is defined according to the `keyType`.
+* @param[in] keyLenBytes The size of buffer to hold the 128-bit OR 256-bit key.
+* \return PAL_SUCCESS in case of success and one of the following error codes in case of failure: \n
+* PAL_ERR_GET_DEV_KEY - an error in key derivation.
+*/
+palStatus_t pal_osGetDeviceKey(palDevKeyType_t keyType, uint8_t *key, size_t keyLenBytes);
+
+
+/*! Initialize the RTOS module for PAL.
+ * This function can be called only once before running the system.
+ * To remove PAL from the system, call `pal_RTOSDestroy`.
+ * After calling `pal_RTOSDestroy`, you can call `pal_RTOSInitialize` again.
+*
+* @param[in] opaqueContext: context to be passed to the platform if needed.
+*
+* \return PAL_SUCCESS upon success.
+*/
+palStatus_t pal_RTOSInitialize(void* opaqueContext);
+
+
+/*! This function removes PAL from the system and can be called after `pal_RTOSInitialize`.
+**
+* \return PAL_SUCCESS upon success. \n
+* 		  PAL_ERR_NOT_INITIALIZED - if the user did not call `pal_RTOSInitialize()` first.
+*/
+palStatus_t pal_RTOSDestroy(void);
+
+/*! Generate a 32-bit random number.
+*
+* @param[out] random A 32-bit buffer to hold the generated number.
+*
+\note `pal_init()` MUST be called before this function.
+\return PAL_SUCCESS on success, a negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_osRandom32bit(uint32_t *random);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif //_PAL_RTOS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_types.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef _PAL_TYPES_H
+#define _PAL_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#if defined __cplusplus && !defined __STDC_FORMAT_MACROS
+    #define UNDEF__STDC_FORMAT_MACROS
+    #define __STDC_FORMAT_MACROS
+#endif
+#include <inttypes.h>
+#ifdef UNDEF__STDC_FORMAT_MACROS
+    #undef UNDEF__STDC_FORMAT_MACROS
+    #undef __STDC_FORMAT_MACROS
+#endif
+#include <stdlib.h>
+
+/*! \file pal_types.h
+*  \brief PAL types.
+*   This file contains PAL generic types.
+*/
+
+
+#define NULLPTR 0
+
+#define TRUE	1
+#define FALSE	0
+
+#define PAL_INVALID_THREAD	0xFFFFFFFF
+
+typedef int32_t palStatus_t;
+
+typedef struct _palBuffer_t
+{
+    uint32_t  maxBufferLength;
+    uint32_t  bufferLength;
+    uint8_t *buffer;
+} palBuffer_t;
+
+typedef struct _palConstBuffer_t
+{
+    const uint32_t  maxBufferLength;
+    const uint32_t  bufferLength;
+    const uint8_t *buffer;
+} palConstBuffer_t;
+
+typedef struct sotpAreaData
+{
+	uint32_t address;   /*\brief  the address of the starting sector for the given area*/
+	size_t	 size;		/*\brief  the size of the area*/
+}palSotpAreaData_t;
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif //_PAL_TYPES_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/Services-API/pal_update.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef SOURCE_PAL_IMPL_SERVICES_API_PAL_UPDATE_H_
+#define SOURCE_PAL_IMPL_SERVICES_API_PAL_UPDATE_H_
+
+#ifndef _PAL_H
+    #error "Please do not include this file directly, use pal.h instead"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! \file pal_update.h
+*  \brief PAL update.
+*   This file contains the firmware update APIs and is a part of the PAL service API.
+*   It provides the read/write and activation functionalities for the firmware.
+*/
+
+
+typedef uint32_t palImageId_t;
+
+typedef struct _palImageHeaderDeails_t
+{
+    size_t imageSize;
+    palBuffer_t hash;
+    uint64_t version;
+} palImageHeaderDeails_t;
+
+typedef enum _palImagePlatformData_t
+{
+    PAL_IMAGE_DATA_FIRST = 0,
+    PAL_IMAGE_DATA_HASH = PAL_IMAGE_DATA_FIRST,
+    PAL_IMAGE_DATA_LAST
+} palImagePlatformData_t;
+
+typedef enum _palImageEvents_t
+{
+    PAL_IMAGE_EVENT_FIRST = -1,
+    PAL_IMAGE_EVENT_ERROR = PAL_IMAGE_EVENT_FIRST,
+    PAL_IMAGE_EVENT_INIT ,
+    PAL_IMAGE_EVENT_PREPARE,
+    PAL_IMAGE_EVENT_WRITE,
+    PAL_IMAGE_EVENT_FINALIZE,
+    PAL_IMAGE_EVENT_READTOBUFFER,
+    PAL_IMAGE_EVENT_ACTIVATE,
+    PAL_IMAGE_EVENT_ACTIVATE_ERROR,
+    PAL_IMAGE_EVENT_GETACTIVEHASH,
+    PAL_IMAGE_EVENT_GETACTIVEVERSION,
+    PAL_IMAGE_EVENT_WRITEDATATOMEMORY,
+    PAL_IMAGE_EVENT_LAST
+} palImageEvents_t;
+
+typedef void (*palImageSignalEvent_t)( palImageEvents_t event);
+
+#define SIZEOF_SHA256               256/8
+#define FIRMWARE_HEADER_MAGIC       0x5a51b3d4UL
+#define FIRMWARE_HEADER_VERSION     1
+#define ACTIVE_IMAGE_INDEX          0xFFFFFFFF
+
+typedef struct FirmwareHeader {
+    uint32_t magic;                         /** Metadata-header specific magic code. */
+    uint32_t version;                       /** Revision number for this generic metadata header. */
+    uint32_t checksum;                      /** A checksum of this header. This field should be considered to be zeroed out for
+                                             *  the sake of computing the checksum. */
+    uint32_t totalSize;                     /** Total space (in bytes) occupied by the firmware BLOB, including headers and any padding. */
+    uint64_t firmwareVersion;               /** Version number for the accompanying firmware. Larger numbers imply more preferred (recent)
+                                             *  versions. This defines the selection order when multiple versions are available. */
+    uint8_t  firmwareSHA256[SIZEOF_SHA256]; /** A SHA-2 using a block-size of 256-bits of the firmware, including any firmware-padding. */
+} FirmwareHeader_t;
+
+
+typedef FirmwareHeader_t palFirmwareHeader_t;
+/*! Sets the callback function that is called before the end of each API (except `imageGetDirectMemAccess`).
+ *
+ * WARNING: Do not change this function!
+ * This function loads a callback function received from the upper layer (service).
+ * The callback should be called at the end of each function (except `pal_plat_imageGetDirectMemAccess`).
+ * The callback receives the event type that just occurred, defined by the ENUM `palImageEvents_t`.
+ *
+ * If you do not call the callback at the end, the service behaviour will be undefined.
+ * The function must call `g_palUpdateServiceCBfunc` before completing an event.
+ *
+ * @param[in] CBfunction A pointer to the callback function.
+ * \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_imageInitAPI(palImageSignalEvent_t CBfunction);
+
+
+/*! Clears all the resources used by the `pal_update` APIs.
+ * \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_imageDeInit(void);
+
+/*! Prepares to write an image with an ID (`imageId`) and size (`imageSize`) in a suitable memory region. The space available is verified and reserved.
+ * The function must call `g_palUpdateServiceCBfunc` before completing an event.
+ * @param[in] imageId The image ID.
+ * @param[in] headerDetails The size of the image.
+ * \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_imagePrepare(palImageId_t imageId, palImageHeaderDeails_t* headerDetails);
+
+/*! Writes the data to the chunk buffer with the chunk `bufferLength` in the location of `imageId` adding the relative offset.
+ * The function must call `g_palUpdateServiceCBfunc` before completing an event.
+ * @param[in] imageId The image ID.
+ * @param[in] offset The offset to write the data into.
+ * @param[in] chunk A pointer to struct containing the data and the data length to write.
+ * \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_imageWrite (palImageId_t imageId, size_t offset, palConstBuffer_t *chunk);
+
+/*! Flushes the image data and sets the version of `imageId` to `imageVersion`.
+ * The function must call `g_palUpdateServiceCBfunc` before completing an event.
+ * @param[in] imageId The image ID.
+ * \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_imageFinalize(palImageId_t imageId);
+
+/*! Verifies whether the image (`imageId`) is readable and sets `imagePtr` to point to the beginning of the image in the memory and `imageSizeInBytes` to the image size.
+ * In case of failure, sets `imagePtr` to NULL and returns the relevant `palStatus_t` error.
+ * @param[in] imageId The image ID.
+ * @param[out] imagePtr A pointer to the beginning of the image.
+ * @param[out] imageSizeInBytes The size of the image.
+ * \return PAL_SUCCESS(0) in case of success and a negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_imageGetDirectMemoryAccess(palImageId_t imageId, void** imagePtr, size_t *imageSizeInBytes);
+
+/*! Reads the maximum of chunk (`maxBufferLength`) bytes from the image (`imageId`) with relative offset and stores it in the chunk buffer.
+ * Also sets the chunk `bufferLength` value to the actual number of bytes read.
+ * \note Use this API in the case image is not directly accessible via the `imageGetDirectMemAccess` function.
+ *
+ * The function must call `g_palUpdateServiceCBfunc` before completing an event.
+ *
+ * @param[in] imageId The image ID.
+ * @param[in] offset The offset to start reading from.
+ * @param[out] chunk A struct containing the data and actual bytes read.
+ */
+palStatus_t pal_imageReadToBuffer(palImageId_t imageId, size_t offset, palBuffer_t* chunk);
+
+/*! Sets an image (`imageId`) as the active image (after the device reset).
+ * The function must call `g_palUpdateServiceCBfunc` before completing an event.
+ *
+ * @param[in] imageId The image ID.
+ */
+palStatus_t pal_imageActivate(palImageId_t imageId);
+
+/*! Retrieves the hash value of the active image to the hash buffer with the max size hash (`maxBufferLength`) and sets the hash size to hash `bufferLength`.
+ * The function must call `g_palUpdateServiceCBfunc` before completing an event.
+ * @param[out] hash A struct containing the hash and actual size of hash read.
+ */
+palStatus_t pal_imageGetActiveHash(palBuffer_t* hash);
+
+
+/*! Retrieves the data value of the image header.
+ * The function must call `g_palUpdateServiceCBfunc` before completing an event.
+ * @param[in] imageId The image ID.
+ * @param[out] headerData A struct containing the headerData and actual size of header.
+ */
+palStatus_t pal_imageGetFirmwareHeaderData(palImageId_t imageId, palBuffer_t *headerData);
+
+
+/*! Retrieves the version of the active image to the version buffer with the size set to version `bufferLength`.
+ * The function must call `g_palUpdateServiceCBfunc` before completing an event.
+ * @param[out] version A struct containing the version and actual size of version read.
+ */
+palStatus_t pal_imageGetActiveVersion(palBuffer_t* version);
+
+/*! Writes the data of `dataId` stored in `dataBuffer` to a memory accessible to the bootloader. Currently, only hash is available.
+ * The function must call `g_palUpdateServiceCBfunc` before completing an event.
+ * @param[in] dataId One of the members of the `palImagePlatformData_t` enum.
+ * @param[in] dataBuffer A struct containing the data and actual bytes to be written.
+ */
+palStatus_t pal_imageWriteDataToMemory(palImagePlatformData_t dataId, const palConstBuffer_t* const dataBuffer);
+
+
+/*! \brief This function gets the firmware working directory.
+ *
+ * \return full path of the firmware working folder
+ */
+char* pal_imageGetFolder(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* SOURCE_PAL_IMPL_SERVICES_API_PAL_UPDATE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/PAL-Impl/pal_init.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#include "pal.h"
+#include "pal_plat_network.h"
+#include "pal_plat_TLS.h"
+#include "pal_plat_Crypto.h"
+#include "pal_macros.h"
+#include "sotp.h"
+
+
+//this variable must be a int32_t for using atomic increment
+PAL_PRIVATE int32_t g_palIntialized = 0;
+
+
+PAL_PRIVATE void pal_modulesCleanup(void)
+{
+    DEBUG_PRINT("Destroying modules\r\n");
+    pal_plat_socketsTerminate(NULL);
+    sotp_deinit();
+    pal_plat_cleanupCrypto();
+    pal_cleanupTLS();
+    pal_fsCleanup();
+    #if PAL_USE_INTERNAL_FLASH
+        pal_internalFlashDeInit();
+    #endif
+    pal_RTOSDestroy();
+}
+
+
+
+palStatus_t pal_init(void)
+{
+
+    palStatus_t status = PAL_SUCCESS;
+    sotp_result_e sotpStatus = SOTP_SUCCESS;
+    int32_t currentInitValue;
+    //  get the return value of g_palIntialized+1 to save it locally
+    currentInitValue = pal_osAtomicIncrement(&g_palIntialized,1);
+    // if increased for the 1st time
+    if (1 == currentInitValue)
+    {
+        DEBUG_PRINT("\nInit for the 1st time, initializing the modules\r\n");
+        status = pal_RTOSInitialize(NULL);
+        if (PAL_SUCCESS == status)
+        {
+            DEBUG_PRINT("Network init\r\n");
+            status = pal_plat_socketsInit(NULL);
+            if (PAL_SUCCESS != status)
+            {
+                DEBUG_PRINT("init of network module has failed with status %" PRIx32 "\r\n",status);
+            }
+            else //socket init succeeded
+            {
+                DEBUG_PRINT("TLS init\r\n");
+                status = pal_initTLSLibrary();
+                if (PAL_SUCCESS != status)
+                {
+                    DEBUG_PRINT("init of tls module has failed with status %" PRIx32 "\r\n",status);
+                }
+                else
+                {
+                    DEBUG_PRINT("Crypto init\r\n");
+                    status = pal_plat_initCrypto();
+                    if (PAL_SUCCESS != status)
+                    {
+                        DEBUG_PRINT("init of crypto module has failed with status %" PRIx32 "\r\n",status);
+                    }
+                    else
+                    {
+                        DEBUG_PRINT("Internal Flash init\r\n");
+                        #if PAL_USE_INTERNAL_FLASH
+                            status = pal_internalFlashInit();
+                        #endif
+                        if (PAL_SUCCESS != status)
+                        {
+                            DEBUG_PRINT("init of Internal Flash module has failed with status %" PRIx32 "\r\n",status);
+                        }
+
+                        else
+                        {
+                            DEBUG_PRINT("SOTP init\r\n");
+                            sotpStatus = sotp_init();
+                            if (SOTP_SUCCESS != sotpStatus)
+                            {
+                                DEBUG_PRINT("init of SOTP module has failed with status %" PRIx32 "\r\n", (int32_t)sotpStatus);
+                                status = PAL_ERR_NOT_INITIALIZED;
+                            }
+                            if (PAL_SUCCESS == status)
+                            {
+                                status = pal_initTime();
+                                if (PAL_SUCCESS != status)
+                                {
+                                    DEBUG_PRINT("init of Time module has failed with status %" PRIx32 "\r\n",status);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        else
+        {
+            DEBUG_PRINT("init of RTOS module has failed with status %" PRIx32 "\r\n",status);
+        }
+
+        // if failed decrease the value of g_palIntialized
+        if (PAL_SUCCESS != status)
+        {
+#if PAL_CLEANUP_ON_INIT_FAILURE           
+            pal_modulesCleanup();
+            pal_osAtomicIncrement(&g_palIntialized, -1);
+#endif
+            PAL_LOG(ERR,"\nInit failed\r\n");
+        }
+    }
+
+    DEBUG_PRINT("FINISH PAL INIT\r\n");
+    return status;
+}
+
+
+int32_t  pal_destroy(void)
+{
+    int32_t currentInitValue;
+    // get the current value of g_palIntialized locally
+    currentInitValue = pal_osAtomicIncrement(&g_palIntialized, 0);
+    if(currentInitValue != 0)
+    {
+        currentInitValue = pal_osAtomicIncrement(&g_palIntialized, -1);
+        if (0 == currentInitValue)
+        {
+            pal_modulesCleanup();
+        }
+    }
+    return currentInitValue;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_Crypto.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,643 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef _PAL_PLAT_CRYPTO_H_
+#define _PAL_PLAT_CRYPTO_H_
+
+#include "pal_Crypto.h"
+
+/*! \file pal_plat_Crypto.h
+*  \brief PAL cryptographic - platform.
+*   This file contains cryptographic APIs that need to be implemented in the platform layer.
+*/
+
+/*!	Initiate the Crypto library. Initialization may not be required for some crypto libraries. In such
+ * cases, the implementation may be empty.
+ *
+\note This function must be called in the general PAL initializtion function.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_initCrypto(void);
+
+/*!	Free resources for the Crypto library.
+*
+\note This function must be called in the general PAL cleanup function.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_cleanupCrypto(void);
+
+/*! Initialize AES context.
+ *
+ * @param[in,out] aes: AES context to be initialized.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_initAes(palAesHandle_t *aes);
+
+/*! Free AES context.
+ *
+ * @param[in,out] aes: AES context to be deallocated.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_freeAes(palAesHandle_t *aes);
+
+/*! Set AES key context for encryption or decryption.
+ *
+ * @param[in] aes: AES context.
+ * @param[in] key: AES key.
+ * @param[in] keybits: The size of the key in bits.
+ * @param[in] keyTarget: The key target (encryption/decryption).
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_setAesKey(palAesHandle_t aes, const unsigned char* key, uint32_t keybits, palAesKeyType_t keyTarget);
+
+/*! AES-CTR buffer encryption/decryption.
+ *
+ * @param[in] aes: AES context.
+ * @param[in] input: The input data buffer.
+ * @param[out] output: The output data buffer.
+ * @param[in] inLen: The length of the input data.
+ * @param[in] iv: The initialization vector for AES-CTR.
+ * @param[in] zeroOffset: Send offset value zero to platform function.
+ *
+ \note Due to the nature of CTR you should use the same key schedule for both encryption and decryption. 
+ * So before calling this function you MUST call `pal_setAesKey()` with the key target PAL_KEY_TARGET_ENCRYPTION to set the key.
+ * 
+ * \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_aesCTR(palAesHandle_t aes, const unsigned char* input, unsigned char* output, size_t inLen, unsigned char iv[16], bool zeroOffset);
+
+/*! AES-ECB block encryption/decryption.
+ *
+ * @param[in] aes: AES context.
+ * @param[in] input: A 16-byte input block.
+ * @param[out] output: A 16-byte output block.
+ * @param[in] mode: PAL_AES_ENCRYPT or PAL_AES_DECRYPT
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_aesECB(palAesHandle_t aes, const unsigned char input[PAL_CRYPT_BLOCK_SIZE], unsigned char output[PAL_CRYPT_BLOCK_SIZE], palAesMode_t mode);
+
+/*! Process SHA256 over the input buffer.
+ *
+ * @param[in] input: A buffer for the input data.
+ * @param[in] inLen: The length of the input data.
+ * @param[out] output: SHA256 checksum result.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_sha256(const unsigned char* input, size_t inLen, unsigned char* output);
+
+/*! Initialize a certificate (chain) context.
+ *
+ * @param[in,out] x509Cert: The certificate chain to initialize.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_x509Initiate(palX509Handle_t* x509);
+
+/*! Parse one or more certificates and add them to the chained list.
+ *
+ * @param[in] x509Cert: The start of the chain.
+ * @param[in] input: A buffer holding the certificate data in PEM or DER format.
+ * @param[in] inLen: The size of the input buffer.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_x509CertParse(palX509Handle_t x509, const unsigned char* input, size_t inLen);
+
+/*! Get attributes from the parsed certificate.
+*
+* @param[in] x509Cert: The parsed certificate.
+* @param[in] attr: The required attribute.
+* @param[out] output: A buffer to hold the attribute value.
+* @param[in] outLenBytes: The size of the allocated buffer.
+* @param[out] actualOutLenBytes: The actual size of the attribute.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_x509CertGetAttribute(palX509Handle_t x509Cert, palX509Attr_t attr, void* output, size_t outLenBytes, size_t* actualOutLenBytes);
+
+/*! Verify one or more X509 DER formatted certificates.
+ *
+ * @param[in] x509Cert: A handle holding the parsed certificate.
+ * @param[in] x509CertChain: The start of the chain to verify the X509 DER certificate with. (Optional) 
+ * @param[out] verifyResult: bitmask of errors that cause the failure, this value is 
+*							relevant ONLY in case that the return value of the function is `PAL_ERR_X509_CERT_VERIFY_FAILED`.
+*
+\note In case platform doesn't support multipule errors for certificate verification, please return `PAL_ERR_X509_CERT_VERIFY_FAILED` and the reason should be specified in the `verifyResult`
+\return PAL_SUCCESS on success. In case of failure returns `PAL_ERR_X509_CERT_VERIFY_FAILED`.
+*/
+palStatus_t pal_plat_x509CertVerifyExtended(palX509Handle_t x509Cert, palX509Handle_t x509CertChain, int32_t* verifyResult);
+
+/*! Deallocate all certificate data.
+ *
+ * @param[in,out] x509: The certificate chain to free. 
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_x509Free(palX509Handle_t* x509);
+
+/*! Initialize an MD context and set up the required data according to the given algorithm.
+ *
+ * @param[in,out] md: The MD context to be initialized.
+ * @param[in] mdType: The MD algorithm.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_mdInit(palMDHandle_t* md, palMDType_t mdType);
+
+/*! Generic message digest process buffer.
+ *
+ * @param[in] md: The MD context.
+ * @param[in] input: A buffer holding the input data.
+ * @param[in] inLen: The length of the input data.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_mdUpdate(palMDHandle_t md, const unsigned char* input, size_t inLen);
+
+/*! Generic message digest output buffer size getter.
+ *
+ * @param[in] md: The MD context.
+ * @param[out] bufferSize: A pointer to hold the output size of the` pal_mdFinal()` for the given handle. 
+ *
+ \note You SHOULD call this function before calling `pal_mdFinal()`.
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_mdGetOutputSize(palMDHandle_t md, size_t* bufferSize);
+
+/*! Generic message digest final digest.
+ *
+ * @param[in] md: The MD context.
+ * @param[in] output: The generic message digest checksum result.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_mdFinal(palMDHandle_t md, unsigned char* output);
+
+/*! Free and clear the MD context.
+ *
+ * @param[in,out] md: The AES context to be freed.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_mdFree(palMDHandle_t* md);
+
+/*! Verify the signature.
+ *
+ * @param[in] x509: The certificate context that holds the PK data.
+ * @param[in] mdType: The MD algorithm used.
+ * @param[in] hash: The hash of the message to sign.
+ * @param[in] hashLen: The hash length.
+ * @param[in] sig: The signature to verify.
+ * @param[in] sigLen: The signature length.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_verifySignature(palX509Handle_t x509, palMDType_t mdType, const unsigned char *hash, size_t hashLen, const unsigned char *sig, size_t sigLen ); 
+
+/*! Get the tag and its length, check for the requested tag.
+*   Updates the pointer to immediately after the tag and length. 
+ *
+ * @param[in,out] position: The position in the ASN.1 data.
+ * @param[in] end: The end of data.
+ * @param[out] len: The tag length.
+ * @param[in] tag: The expected tag.
+ *
+ \return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_ASN1GetTag(unsigned char **position, const unsigned char *end, size_t *len, uint8_t tag );
+
+/*!	CCM initialization.
+*
+* @param[in] ctx: The CCM context to be initialized.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CCMInit(palCCMHandle_t* ctx);
+
+/*!	CCM destruction.
+*
+* @param[in] ctx: The CCM context to destroy.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CCMFree(palCCMHandle_t* ctx);
+
+/*!	CCM set key.
+*
+* @param[in] ctx:       The CCM context.
+* @param[in] id:        The cipher to use (a 128-bit block cipher).
+* @param[in] key:       The encryption key.
+* @param[in] keybits:   The key size in bits (must be acceptable by the cipher).
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CCMSetKey(palCCMHandle_t ctx, palCipherID_t id, const unsigned char *key, unsigned int keybits);
+
+/*!	CCM buffer authenticated decryption.
+*
+* @param[in] ctx:       The CCM context.
+* @param[in] input      A buffer holding the input data.
+* @param[in] inLen:    	The length of the input data.
+* @param[in] iv:        The initialization vector.
+* @param[in] ivLen:    	The length of the IV.
+* @param[in] add:       Additional data.
+* @param[in] addLen:   	The length of additional data.
+* @param[in] tag:      	A buffer holding the tag.
+* @param[in] tag_len:  	The length of the tag.
+* @param[out] output:   A buffer for holding the output data.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CCMDecrypt(palCCMHandle_t ctx, unsigned char* input, size_t inLen, unsigned char* iv, size_t ivLen, unsigned char* add, size_t addLen, unsigned char* tag, size_t tagLen, unsigned char* output);
+
+/*!	CCM buffer encryption.
+*
+* @param[in] ctx:       The CCM context.
+* @param[in] input      A buffer holding the input data.
+* @param[in] inLen:    	The length of the input data.
+* @param[in] iv:        The initialization vector.
+* @param[in] ivLen:    	The length of the IV.
+* @param[in] add:       Additional data.
+* @param[in] addLen:   	The length of additional data.
+* @param[out] output:   A buffer for holding the output data, must be at least 'inLen' bytes wide.
+* @param[out] tag:      A buffer for holding the tag.
+* @param[out] tag_len:  The length of the tag to generate in bytes.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CCMEncrypt(palCCMHandle_t ctx, unsigned char* input, size_t inLen, unsigned char* iv, size_t ivLen, unsigned char* add, size_t addLen, unsigned char* output, unsigned char* tag, size_t tagLen);
+
+/*!	CTR_DRBG initialization.
+*
+* @param[in] ctx:   The CTR_DRBG context to be initialized.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CtrDRBGInit(palCtrDrbgCtxHandle_t* ctx);
+
+/*!	CTR_DRBG destroy.
+*
+* @param[in] ctx:   The CTR_DRBG context to destroy.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CtrDRBGFree(palCtrDrbgCtxHandle_t* ctx);
+
+/*!	CTR_DRBG initial seeding.
+*
+* @param[in] ctx:	The CTR_DRBG context to be seeded.
+* @param[in] seed:	The seed data.
+* @param[in] len:	The seed data length.
+*
+\return PAL_SUCCESS on success, negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CtrDRBGSeed(palCtrDrbgCtxHandle_t ctx, const void* seed, size_t len);
+
+/*!	CTR_DRBG generate random.
+*
+* @param[in] ctx:	The CTR_DRBG context.
+* @param[in] out:	The buffer to fill.
+* @param[in] len:	The length of the buffer.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CtrDRBGGenerate(palCtrDrbgCtxHandle_t ctx, unsigned char* out, size_t len);
+
+/*!	CTR_DRBG generate random with additional update input.
+*
+* @param[in] ctx:	The CTR_DRBG context.
+* @param[in] out:	The buffer to fill.
+* @param[in] len:	The length of the buffer.
+* @param[in] additional:	Additional data to update with.
+* @param[in] additionalLen:	Length of additional data.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CtrDRBGGenerateWithAdditional(palCtrDrbgCtxHandle_t ctx, unsigned char* out, size_t len, unsigned char* additional, size_t additionalLen);
+
+#if PAL_CMAC_SUPPORT
+
+/*!	AES cipher CMAC.
+*
+* @param[in] ctx:               The CMAC context to initialize.
+* @param[in] key:               The encryption key.
+* @param[in] keyLenInBits:      The key size in bits.
+* @param[in] input:             A buffer for the input data.
+* @param[in] inputLenInBytes:   The input data length in bytes.
+* @param[out] output:           Generic CMAC result.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_cipherCMAC(const unsigned char *key, size_t keyLenInBits, const unsigned char *input, size_t inputLenInBytes, unsigned char *output);
+
+/*!	Iterative cipher CMAC start.
+*
+* @param[in] ctx:   	 The CMAC context to initialize.
+* @param[in] key:  		 The CMAC key.
+* @param[in] keyLenBits: The key size in bits.
+* @param[in] cipherID:   A buffer for the input data.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CMACStart(palCMACHandle_t *ctx, const unsigned char *key, size_t keyLenBits, palCipherID_t cipherID);
+
+/*!	Iterative cipher CMAC update.
+*
+* @param[in] ctx:   	The CMAC context to initialize.
+* @param[in] input:  	A buffer for the input data.
+* @param[in] inputLen:  The input data length.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CMACUpdate(palCMACHandle_t ctx, const unsigned char *input, size_t inLen);
+
+/*!	Iterative cipher CMAC finish.
+*
+* @param[in] ctx:   	The CMAC context to initialize.
+* @param[out] output:  	A buffer for the output data.
+* @param[out] outLen:   The output data length.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_CMACFinish(palCMACHandle_t *ctx, unsigned char *output, size_t* outLen);
+
+#endif //PAL_CMAC_SUPPORT
+
+/*! One shot md HMAC.
+*
+* @param[in] key:  				The encryption key.
+* @param[in] keyLenInBytes:   	The key size in bytes.
+* @param[in] input:  	        A buffer for the input data.
+* @param[in] inputLenInBytes:   The input data length in bytes.
+* @param[out] output:           The generic HMAC result.
+* @param[out] outputLenInBytes: Size of the HMAC result (optional).
+*
+\note Expects output to be 32 bytes long
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_mdHmacSha256(const unsigned char *key, size_t keyLenInBytes, const unsigned char *input, size_t inputLenInBytes, unsigned char *output, size_t* outputLenInBytes);
+
+
+/*!	Check that the private and/or public key is a valid key and the public key is on this curve.
+*
+* @param[in] grp:		The curve/group the point should belong to.
+* @param[in] key:		A pointer to the struct that holds the keys to check.
+* @param[in] type:      PAL_CHECK_PRIVATE_KEY/PAL_CHECK_PUBLIC_KEY/PAL_CHECK_BOTH_KEYS
+* @param[out] verified:	The result of the verification.
+*
+\note	The key can contain only private or public key or both.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_ECCheckKey(palCurveHandle_t grp, palECKeyHandle_t key, uint32_t type, bool *verified);
+
+/*!	Allocate key context and initialize a key pair (as an invalid one).
+*
+* @Param[in] key:	The key pair context to initialize
+*
+\return PAL_SUCCESS on success, negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_ECKeyNew(palECKeyHandle_t* key);
+
+/*!	Free the components of a key pair.
+*
+* @param[in] key:	The key to free.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_ECKeyFree(palECKeyHandle_t* key);
+
+/*!	Parse a DER encoded private key.
+*
+* @param[in] prvDERKey:	A buffer that holds the DER encoded private key.
+* @param[in] keyLen:   The key length.
+* @param[out] key:		A handle for the context that holds the parsed key.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_parseECPrivateKeyFromDER(const unsigned char* prvDERKey, size_t keyLen, palECKeyHandle_t key);
+
+/*!	Parse a DER encoded public key.
+*
+* @param[in] pubDERKey:	A buffer that holds the DER encoded public key.
+* @param[in] keyLen:    The key length.
+* @param[out] key:		A handle for the context that holds the parsed key.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_parseECPublicKeyFromDER(const unsigned char* pubDERKey, size_t keyLen, palECKeyHandle_t key);
+
+/*! Encode the given private key from the key handle to the DER buffer.
+*
+* @param[in] key: 		 A handle to the private key.
+* @param[out] derBuffer: A buffer to hold the result of the DER encoding.
+* @param[in] bufferSize: The size of the allocated buffer.
+* @param[out] actualSize: The actual size of the written data.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_writePrivateKeyToDer(palECKeyHandle_t key, unsigned char* derBuffer, size_t bufferSize, size_t* actualSize);
+
+/*! Encode the given public key from the key handle to the DER buffer.
+*
+* @param[in] key: 		 A handle to the public key.
+* @param[out] derBuffer: A buffer to hold the result of the DER encoding.
+* @param[in] bufferSize: The size of the allocated buffer.
+* @param[out] actualSize: The actual size of the written data.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_writePublicKeyToDer(palECKeyHandle_t key, unsigned char* derBuffer, size_t bufferSize, size_t* actualSize);
+
+/*!	 Generate a keypair.
+*
+* @param[in] grpID:	The ECP group identifier.
+* @param[in] key:	A handle to the destination keypair.
+*
+\note The `key` parameter must be first allocated by `pal_ECKeyNew()`.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_ECKeyGenerateKey(palGroupIndex_t grpID, palECKeyHandle_t key);
+
+/*! Retrieve the curve ID if it exists in the given key. 
+*
+* @param[in] key: The key to retrieve its curve. 
+* @param[out] grpID: The curve/group ID for the given key. In case of error, this pointer contains "PAL_ECP_DP_NONE".
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_ECKeyGetCurve(palECKeyHandle_t key, palGroupIndex_t* grpID);
+
+/*! Allocate and initialize the x509 CSR context.
+*
+* @param[in] x509CSR:	The CSR context to allocate and initialize. 
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_x509CSRInit(palx509CSRHandle_t *x509CSR);
+
+/*! Set the subject name for a CSR. The subject names should contain a comma-separated list of OIDs and values.
+*
+* @param[in] x509CSR: 	  The CSR context to use.
+* @param[in] subjectName: The subject name to set.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_x509CSRSetSubject(palx509CSRHandle_t x509CSR, const char* subjectName);
+
+/*! Set the MD algorithm to use for the signature.
+*
+* @param[in] x509CSR:   The CSR context to use.
+* @param[in] mdType:    The MD algorithm to use.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_x509CSRSetMD(palx509CSRHandle_t x509CSR, palMDType_t mdType);
+
+/*! Set the key for a CSR.
+*
+* @param[in] x509CSR:   The CSR context to use.
+* @param[in] pubKey:    The public key to include. To use the keypair handle, see the note.
+* @param[in] prvKey:    The public key to sign with.
+*
+\note To use the keypair, please send it as `pubKey` and NULL as `prvKey`.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_x509CSRSetKey(palx509CSRHandle_t x509CSR, palECKeyHandle_t pubKey, palECKeyHandle_t prvKey);
+
+/*! Set the key usage extension flags.
+*
+* @param[in] x509CSR:   The CSR context to use.
+* @param[in] keyUsage:  The key usage flags that should be taken from `palKeyUsage_t`.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_x509CSRSetKeyUsage(palx509CSRHandle_t x509CSR, uint32_t keyUsage);
+
+/*! Set the extended key usage extension.
+*
+* @param[in] x509CSR:   The CSR context to use.
+* @param[in] extKeyUsage:  The extended key usage flags, should be taken from `palExtKeyUsage_t`.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_x509CSRSetExtendedKeyUsage(palx509CSRHandle_t x509CSR, uint32_t extKeyUsage);
+
+/*! Generic function to add to the CSR.
+*
+* @param[in] x509CSR:  The CSR context to use.
+* @param[in] oid:  	   The OID of the extension.
+* @param[in] oidLen: 	The OID length.
+* @param[in] value: 	The value of the extension OCTET STRING.
+* @param[in] valueLen:  The value length.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_x509CSRSetExtension(palx509CSRHandle_t x509CSR,const char* oid, size_t oidLen, const unsigned char* value, size_t valueLen);
+
+/*! Write a CSR to a DER structure.
+*
+* @param[in] x509CSR:      The CSR context to use.
+* @param[in] derBuf:  		A buffer to write to.
+* @param[in] derBufLen: 	The buffer length.
+* @param[in] actualDerLen: 	The actual length of the written data.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_x509CSRWriteDER(palx509CSRHandle_t x509CSR, unsigned char* derBuf, size_t derBufLen, size_t* actualDerLen);
+
+/*! Calculate the hash of the To Be Signed part of an X509 certificate.
+* This function may be used to validate a certificate signature: Simply retrieve this hash, verify the signature using this hash, the public key and the signature of the X509
+*
+* @param[in] x509Cert:	        Handle to the certificate to hash the TBS (to be signed part). 
+* @param[in] hash_type:	        The hash type. Currently only PAL_SHA256 supported
+* @param[out] output:	        Pointer to a buffer that will contain the hash digest. This buffer must be at least the size of the digest. If hash_type is PAL_SHA256, then buffer pointed to by output must be at least 32 bytes. 
+* @param[in] outLenBytes:       The size of the buffer pointed to by output. Must be at least the size of the digest
+* @param[out] actualOutLenBytes:    Size of the digest copied to output. In case of success, will always be the length of the hash digest
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_x509CertGetHTBS(palX509Handle_t x509Cert, palMDType_t hash_type, unsigned char* output, size_t outLenBytes, size_t* actualOutLenBytes);
+
+/*! Free the x509 CSR context.
+*
+* @param[in] x509CSR:	The CSR context to free.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_x509CSRFree(palx509CSRHandle_t *x509CSR);
+
+/*!	Compute a shared secret.
+*
+* @param[in] grp:			The ECP group.
+* @param[in] peerPublicKey:	The public key from a peer.
+* @param[in] privateKey:	The private key.
+* @param[out] outKey:		The shared secret.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_ECDHComputeKey(const palCurveHandle_t grp, const palECKeyHandle_t peerPublicKey, const palECKeyHandle_t privateKey, palECKeyHandle_t outKey);
+
+/*!	Compute the ECDSA signature of a previously hashed message.
+*
+* @param[in] grp:		The ECP group.
+* @param[in] prvKey:	The private signing key-
+* @param[in] dgst:		The message hash.
+* @param[in] dgstLen:	The length of the message buffer.
+* @param[out] sig:		A buffer to hold the computed signature.
+* @param[out] sigLen:  The length of the computed signature.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_ECDSASign(palCurveHandle_t grp, palMDType_t mdType, palECKeyHandle_t prvKey, unsigned char* dgst, uint32_t dgstLen, unsigned char *sig, size_t *sigLen);
+
+/*!	Verify the ECDSA signature of a previously hashed message.
+*
+* @param[in] pubKey:	The public key for verification.
+* @param[in] dgst:		The message hash.
+* @param[in] dgstLen:	The length of the message buffer.
+* @param[in] sign:		The signature.
+* @param[in] sig:		A buffer to hold the computed signature.
+* @param[in] sigLen:    The length of the computed signature.
+* @param[out] verified: The boolean to hold the verification result.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_ECDSAVerify(palECKeyHandle_t pubKey, unsigned char* dgst, uint32_t dgstLen, unsigned char* sig, size_t sigLen, bool* verified);
+
+/*!	Free the components of an ECP group.
+*
+* @param[in] grp:	The curve/group to free.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_ECGroupFree(palCurveHandle_t* grp);
+
+/*!	ECP group initialize and set a group using well-known domain parameters.
+*
+* @param[in] grp:	The destination group.
+* @param[in] index:	The index in the list of well-known domain parameters.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_ECGroupInitAndLoad(palCurveHandle_t* grp, palGroupIndex_t index);
+
+
+#endif //_PAL_PLAT_CRYPTO_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_TLS.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,322 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef _PAL_PLAT_TLS_H_
+#define _PAL_PLAT_TLS_H_
+#include "pal_TLS.h"
+
+/*! \file pal_plat_TLS.h
+*  \brief PAL TLS/DTLS - platform.
+*   This file contains TLS/DTLS APIs that need to be implemented in the platform layer. 
+*/
+
+/***************************************************/
+/**** PAL DTLS internal data structures ************/
+/***************************************************/
+typedef enum palDTLSSide{
+#ifdef PAL_TLS_SUPPORT_SERVER_MODE
+	PAL_TLS_IS_SERVER,
+#endif // PAL_TLS_SUPPORT_SERVER_MODE
+	PAL_TLS_IS_CLIENT
+} palDTLSSide_t;
+
+typedef enum palTLSAuthMode{
+	PAL_TLS_VERIFY_NONE,		//! Server mode: The peer certificate is not verified. For client mode, this is insecure!
+	PAL_TLS_VERIFY_OPTIONAL,	//! The peer certificate verification can be failed and handshake continues.
+	PAL_TLS_VERIFY_REQUIRED		//! The peer certificate verification MUST pass.
+}palTLSAuthMode_t;
+
+//! This is the list of the available cipher suites, this code MUST be 
+//! defined in the `pal_plat_TLS.c` with the proper values for the SSL platform:
+typedef enum palTLSSuites{
+	PAL_TLS_PSK_WITH_AES_128_CBC_SHA256,
+	PAL_TLS_PSK_WITH_AES_128_CCM_8,
+	PAL_TLS_PSK_WITH_AES_256_CCM_8,
+	PAL_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
+	PAL_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+    PAL_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+    PAL_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
+    PAL_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256
+}palTLSSuites_t;
+
+typedef void* palTLSSocketHandle_t;
+typedef void* palTimerCtx_t;
+
+//! This prototype can be re-defined by the platform side.
+//! Consider moving them to separate header.
+typedef int (*palBIOSend_f)(palTLSSocketHandle_t socket, const unsigned char *buf, size_t len);
+typedef int (*palBIORecv_f)(palTLSSocketHandle_t socket, unsigned char *buf, size_t len);
+typedef int (*palVerifyCallback_f)(void *, void *, int, uint32_t *);
+typedef void (*palSetTimer_f)( void *data, uint32_t intMs, uint32_t finMs ); 
+typedef int (*palGetTimer_f)(void* data);
+typedef void (*palLogFunc_f)(void *context, int debugLevel, const char *fileName, int line, const char *message);
+
+
+/*!	Initiate the TLS library. This API is not required for each TLS library.
+* 	For example for mbed TLS, it will be an empty function.
+*
+\note You must call this function in the general PAL initializtion function.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_initTLSLibrary(void);
+
+/*!	Free resources for the TLS library.
+*
+\note You must call this function in the general PAL cleanup function.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_cleanupTLS(void);
+
+/*! Initiate new configuration context.
+*
+* @param[out] palTLSConf: The TLS configuration context.
+* @param[in] tranportVersion: The `palTLSTransportMode_t` type deciding the transportation version (for example tlsv1.2).
+* @param[in] methodType: The `palDTLSSide_t` type deciding the endpoint type (server or client).
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_initTLSConf(palTLSConfHandle_t* confCtx, palTLSTransportMode_t transportVersion, palDTLSSide_t methodType);
+
+/*! Destroy and release resources for the TLS configuration context.
+*
+* @param[inout] palTLSConf: The TLS configuration context to free.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_tlsConfigurationFree(palTLSConfHandle_t* palTLSConf);
+
+/*!	Initiate a new TLS context.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[out] palTLSHandle: The index to the TLS context.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_initTLS(palTLSConfHandle_t palTLSConf, palTLSHandle_t* palTLSHandle);
+
+/*! Destroy and release resources for the TLS context.
+*
+* @param[inout] ssl: The TLS context to free.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_freeTLS(palTLSHandle_t* palTLSHandle);
+
+/*! Add an entropy source to the TLS/DTLS library (this API may NOT be available in all TLS/DTLS platforms, see the note).
+*
+* @param[in] entropyCallback: The entropy callback to be used in the TLS/DTLS handshake.
+*
+\note This function is available ONLY when the TLS/DTLS platform supports this functionality. In other platforms,
+      PAL_ERR_NOT_SUPPORTED should be returned.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code or PAL_ERR_NOT_SUPPORTED in case of failure.
+*/
+palStatus_t pal_plat_addEntropySource(palEntropySource_f entropyCallback);
+
+/*!	Set the supported cipher suites to the configuration context.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] palSuites: The supported cipher suites to be added.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_setCipherSuites(palTLSConfHandle_t sslConf, palTLSSuites_t palSuite);
+
+/*!	 Return the result of the certificate verification. The handshake API calls this.
+*
+* @param[in] ssl: The TLS context.
+* @param[out] verifyResult: bitmask of errors that cause the failure, this value is 
+*							relevant ONLY in case that the return value of the function is `PAL_ERR_X509_CERT_VERIFY_FAILED`.
+*
+\note In case platform doesn't support multipule errors for certificate verification, please return `PAL_ERR_X509_CERT_VERIFY_FAILED` and the reason should be specified in the `verifyResult`
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_sslGetVerifyResultExtended(palTLSHandle_t palTLSHandle, int32_t* verifyResult);
+
+/*!  Read at most 'len' application data bytes.
+*
+* @param[in] ssl: The TLS context.
+* @param[out] buffer: A buffer holding the data.
+* @param[in] len: The maximum number of bytes to read.
+* @param[out] actualLen: The actual number of bytes read.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_sslRead(palTLSHandle_t palTLSHandle, void *buffer, uint32_t len, uint32_t* actualLen);
+
+/*! Try to write exactly 'len' application data bytes.
+*
+* @param[in] ssl: The TLS context.
+* @param[in] buffer: A buffer holding the data.
+* @param[in] len: The number of bytes to be written.
+* @param[out] bytesWritten: The number of bytes actually written.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_sslWrite(palTLSHandle_t palTLSHandle, const void *buffer, uint32_t len, uint32_t *bytesWritten);
+
+/*! Set the retransmit timeout values for the DTLS handshake.
+*	(DTLS only, no effect on TLS.)
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] timeoutInMilliSec: The maximum timeout value in milliseconds.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_setHandShakeTimeOut(palTLSConfHandle_t palTLSConf, uint32_t timeoutInMilliSec);
+
+/*!	Set up a TLS context for use.
+*
+* @param[in/out] ssl: The TLS context.
+* @param[in] palTLSConf: The TLS configuration context.
+*
+\return The function returns `palTLSHandle_t`, the index to the TLS context.
+*/
+palStatus_t pal_plat_sslSetup(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSConf);
+
+/*! Perform the TLS handshake.
+*
+* @param[in] ssl: The TLS context.
+* @param[out] serverTime: The server time recieved in the server hello message during handshake.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_handShake(palTLSHandle_t palTLSHandle, uint64_t* serverTime);
+
+#if PAL_USE_SECURE_TIME
+/*! Perform the TLS handshake renegotiation.
+*
+* @param[in] ssl: The TLS context.
+* @param[in] serverTime: The server time used to update the TLS time during handshake renegotiate.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_renegotiate(palTLSHandle_t palTLSHandle, uint64_t sreverTime);
+#endif //PAL_USE_SECURE_TIME
+
+/*! Set the socket for the TLS configuration context.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] socket: The socket for the TLS context.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_tlsSetSocket(palTLSConfHandle_t palTLSConf, palTLSSocket_t* socket);
+
+/*! Set your own certificate chain and private key.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] ownCert: Your own public certificate chain.
+* @param[in] privateKey: Your own private key.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_setOwnCertAndPrivateKey(palTLSConfHandle_t palTLSConf, palX509_t* ownCert, palPrivateKey_t* privateKey);
+
+/*! Set your own certificate chain.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] ownCert: Your own public certificate chain.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_setOwnCertChain(palTLSConfHandle_t palTLSConf, palX509_t* ownCert);
+
+/*! Set your own private key.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] privateKey: Your own private key.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_setOwnPrivateKey(palTLSConfHandle_t palTLSConf, palPrivateKey_t* privateKey);
+
+/*! Set the data required to verify a peer certificate.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] caChain: The trusted CA chain.
+* @param[in] caCRL: The trusted CA CRLs.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_setCAChain(palTLSConfHandle_t palTLSConf, palX509_t* caChain, palX509CRL_t* caCRL);
+
+/*! Set the Pre-Shared Key (PSK) and the expected identity name.
+*
+* @param[in] sslConf: The TLS configuration context.
+* @param[in] identity: A pointer to the pre-shared key identity.
+* @param[in] maxIdentityLenInBytes: The maximum length of the identity key.
+* @param[in] psk: A pointer to the pre-shared key.
+* @param[in] maxPskLenInBytes: The maximum length of the pre-shared key.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_setPSK(palTLSConfHandle_t sslConf, const unsigned char *identity, uint32_t maxIdentityLenInBytes, const unsigned char *psk, uint32_t maxPskLenInBytes);
+
+
+/*!	Set the certificate verification mode.
+*
+* @param[in] sslConf: The TLS configuration context.
+* @param[in] authMode: The authentication mode.
+*
+\note In some platforms, a verification callback MAY be needed. In this case, it must be provided by the porting side.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_setAuthenticationMode(palTLSConfHandle_t sslConf, palTLSAuthMode_t authMode);
+
+
+/*! Turn on/off the TLS library debugging for the given configuration handle. The logs are sent via the mbedTrace.
+*   In case of release mode, an error will be returned.
+*
+* @param[in] palTLSConf : the TLS confuguraiton to modify
+* @param[in] turnOn: if greater than 0 turn on debugging, otherwise turn it off
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_sslSetDebugging(palTLSConfHandle_t palTLSConf, uint8_t turnOn);
+
+/*! Set the IO callbacks for the TLS context. 
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] palIOCtx: The shared context by BIO callbacks.
+* @param[in] palBIOSend: A pointer to send BIO function.
+* @param[in] palBIORecv: A pointer to receive BIO function.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_sslSetIOCallBacks(palTLSConfHandle_t palTLSConf, palTLSSocket_t* palIOCtx, palBIOSend_f palBIOSend, palBIORecv_f palBIORecv);
+
+/*!	Set the timer callbacks.
+*
+* @param[in] palTLSHandle: The TLS context.
+* @param[in] timerCtx: The shared context by BIO callbacks.
+* @param[in] setTimer: The set timer callback.
+* @param[in] getTimer: The get timer callback.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_setTimeCB(palTLSHandle_t* palTLSHandle, palTimerCtx_t timerCtx, palSetTimer_f setTimer, palGetTimer_f getTimer);
+
+/*! Set the logging function.
+*
+* @param[in] palTLSConf: The TLS configuration context.
+* @param[in] palLogFunction: A pointer to the logging function.
+* @param[in] logContext: The context for the logging function.
+*
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_SetLoggingCb(palTLSConfHandle_t palTLSConf, palLogFunc_f palLogFunction, void *logContext);
+
+#endif //_PAL_PLAT_TLS_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_fileSystem.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,292 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#ifndef PAL_PALT_FILE_SYSTEM_H
+#define PAL_PALT_FILE_SYSTEM_H
+
+#include "pal_fileSystem.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! \file pal_plat_fileSystem.h
+*  \brief PAL file system - platform.
+*	This file contains the file system APIs that need to be implemented in the platform layer.
+*/
+
+/*!  @defgroup PAL_PLAT_GROUP_FS
+*	\note You need to add the prefix of the ESFS folder root stored in \c g_esfsRootFolder to all files and folders.
+*	To change this, call \c pal_plat_fsSetEsfsRootFolder().
+*
+*/
+
+/**
+@defgroup PAL_PLAT_PUBLIC_FUNCTION  PAL Platform Public Functions
+@ingroup PAL_PLAT_GROUP_FS
+*/
+
+/**
+@addtogroup PAL_PLAT_PUBLIC_FUNCTION
+@{*/
+
+/*! \brief 	This function attempts to create a directory named \c pathName.
+*
+* @param[in]	*pathName A pointer to the null-terminated string that specifies the directory name to create.
+*
+* \return PAL_SUCCESS upon a successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see the error code description \c palError_t.
+*
+* \note To remove a directory use \c PAL_ERR_FS_rmdir.
+*
+*\b Example
+\code{.cpp}
+	palStatus_t ret;
+	ret = PAL_ERR_FS_mkdir("Dir1");
+	if(!ret)
+	{
+		//Error
+	}
+\endcode
+*/
+palStatus_t pal_plat_fsMkdir(const char *pathName);
+
+
+
+/*! \brief This function deletes a directory.
+*
+* @param[in]	*pathName A pointer to the null-terminated string that specifies the name of the directory to be deleted.
+*
+* \return PAL_SUCCESS upon a successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see the error code description \c palError_t.
+*
+* \note The directory to be deleted \b must \b be \b Empty and \b closed.
+*		The folder path must end with "/".
+*		If given "..", the function changes the root directory to one directory down and deletes the working directory.
+*/
+palStatus_t pal_plat_fsRmdir(const char *pathName);
+
+
+
+/*!\brief This function opens the file whose name is specified in the parameter `pathName` and associates it with a stream
+*		   that can be identified in future operations by the `fd` pointer returned.
+*
+* @param[out]	fd A file descriptor for the file entered in the `pathName`.
+* @param[in]	*pathName A pointer to the null-terminated string that specifies the file name to open or create.
+* @param[in]	mode A mode flag that specifies the type of access and open method for the file.
+*
+*
+* \return PAL_SUCCESS upon a successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see the error code description \c palError_t.
+*
+* \note	  The folder path must end with "/".
+* \note	  If necessary, the platform layer \b allocates \b memory for the file descriptor. The structure
+* 		  \c pal_plat_fclose() shall free that buffer.
+* \note   The mode flags sent to this function are normalized to the \c pal_fsFileMode_t and each platform needs to replace them with the proper values.
+*
+*/
+palStatus_t pal_plat_fsFopen(const char *pathName, pal_fsFileMode_t mode, palFileDescriptor_t *fd);
+
+
+
+/*! \brief This function closes an open file object.
+*
+* @param[in] fd A pointer to the open file object structure to be closed.
+*
+* \return PAL_SUCCESS upon a successful operation. \n
+*         PAL_FILE_SYSTEM_ERROR - see the error code \c palError_t.a 
+*
+* \note After successful execution of the function, the file object is no longer valid and it can be discarded.
+* \note In some platforms, this function needs to \b free the file descriptor memory.
+*/
+palStatus_t pal_plat_fsFclose(palFileDescriptor_t *fd);
+
+
+
+/*! \brief	This function reads an array of bytes from the stream and stores them in the block of memory
+*			specified by the buffer. The position indicator of the stream is advanced by the total amount of bytes read.
+*
+* @param[in]	fd A pointer to the open file object structure.
+* @param[in]	buffer A buffer for storing the read data.
+* @param[in]	numOfBytes The number of bytes to read.
+* @param[out]	numberOfBytesRead The number of bytes read.
+*
+* \return PAL_SUCCESS upon a successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see the error code description \c palError_t.
+*
+* \note	After successful execution of the function,
+*		`numberOfBytesRead` should be checked to detect end of the file.
+*		If `numberOfBytesRead` is less than `numOfBytes`,
+*		the read/write pointer has reached the end of the file during the read operation or an error has occurred.
+*
+*/
+palStatus_t pal_plat_fsFread(palFileDescriptor_t *fd, void * buffer, size_t numOfBytes, size_t *numberOfBytesRead);
+
+
+
+/*! \brief This function starts to write data from the \c buffer to the file at the position pointed by the read/write pointer.
+*
+* @param[in]	fd A pointer to the open file object structure.
+* @param[in]	buffer A pointer to the data to be written.
+* @param[in]	numOfBytes The number of bytes to write.
+* @param[out]	numberOfBytesWritten The number of bytes written.
+*
+* \return PAL_SUCCESS upon a successful operation. \n
+*           PAL_FILE_SYSTEM_ERROR - see the error code \c palError_t.
+*
+* \note The read/write pointer advances as number of bytes written. After successful execution of the function,
+* \note `numberOfBytesWritten` should be checked to detect if the disk is full.
+*		If `numberOfBytesWritten` is less than `numOfBytes`, the volume got full during the write operation.
+*
+*/
+palStatus_t pal_plat_fsFwrite(palFileDescriptor_t *fd, const void *buffer, size_t numOfBytes, size_t *numberOfBytesWritten);
+
+
+/*! \brief	This function moves the file read/write pointer without any read/write operation to the file.
+*
+* @param[in]	fd A pointer to the open file object structure.
+* @param[in]	offset The byte offset from top of the file to set the read/write pointer.
+* @param[out]   whence The offset is relative to this.
+*
+* \return PAL_SUCCESS upon a successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see the error code description \c palError_t.
+*
+* \note - The `whence` options are:
+* 		 -# \c PAL_ERR_FS_SEEKSET - relative to the start of the file.
+*  		 -# \c PAL_ERR_FS_SEEKCUR - relative to the current position indicator.
+* 		 -# \c PAL_ERR_FS_SEEKEND - relative to the end-of-file.
+*
+* \note In some systems, there is no \c whence argument.
+* 	If you need to implement the `whence` argument:\n
+* 	\b PAL_ERR_FS_SEEKEND - The function first finds the length of the file, then subtracts the file length from the position to find the relative path from the beginning.\n
+*       \b PAL_ERR_FS_SEEKCUR - The function finds the current stream position and calculates the relative path from the file start.\n
+*   
+* In both options, \c fseek() needs to verify that the offset is smaller than the file end or start. 
+*
+*/
+palStatus_t pal_plat_fsFseek(palFileDescriptor_t *fd, int32_t offset, pal_fsOffset_t whence);
+
+
+
+/*! \brief This function gets the current read/write pointer of a file.
+*
+* @param[in]	fd A pointer to the open file object structure.
+*
+* \return PAL_SUCCESS upon a successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see the error code description \c palError_t.
+*
+*/
+palStatus_t pal_plat_fsFtell(palFileDescriptor_t *fd, int32_t * pos);
+
+
+
+/*! \brief This function deletes a \b single file from the file system.
+*
+* @param[in]  pathName A pointer to a null-terminated string that specifies the \b file to be removed.
+* @param[in]  buildRelativeDirectory Needed to add a working directory to give \c pathName.
+*
+* \return PAL_SUCCESS upon a successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see the error code description \c palError_t.
+*
+* \note The file \b must \b not \b be \b opened
+*
+*/
+palStatus_t pal_plat_fsUnlink(const char *pathName);
+
+
+
+/*! \brief This function deletes \b all files in a folder from the file system (FLAT remove only).
+*
+* @param[in]  pathName A pointer to a null-terminated string that specifies the \b folder.
+*
+* \return PAL_SUCCESS upon a successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see the error code description \c palError_t.
+*
+* \note The folder \b must \b not \b be \b open and the folder path must end with "/".
+* \note The process deletes one file at a time by calling \c pal_plat_fsUnlink until all files are removed.
+* \note The function does not remove the directory found in the path.
+*/
+palStatus_t pal_plat_fsRmFiles(const char *pathName);
+
+
+
+/*! \brief This function copies \b all files from a source folder to a destination folder (FLAT copy only).
+*
+* @param[in]  pathNameSrc A pointer to a null-terminated string that specifies the source folder.
+* @param[in]  pathNameDest A pointer to a null-terminated string that specifies the destination folder (MUST exist).
+*
+* \return PAL_SUCCESS upon a successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see the error code description \c palError_t.
+*
+* \note Both folders \b must \b not \b be \b open. If a folder does not exist the function fails.
+* \note The process copies one file at a time until all files are copied.
+* \note The function does not copy a directory found in the path.
+*/
+palStatus_t pal_plat_fsCpFolder(const char *pathNameSrc,  char *pathNameDest);
+
+
+/*! \brief This function gets the default value for  root directory (primary)
+*
+* @param[in]  dataID - id of the data to ge the root folder for.
+*
+* \return pointer to the default path.
+*
+*/
+const char* pal_plat_fsGetDefaultRootFolder(pal_fsStorageID_t dataID);
+
+
+
+/*! \brief This function finds the length of the string received.
+*
+*
+* @param[in]  stringToChk A pointer to the string received with a null terminator.
+*
+* \return The size of the string.
+*
+*/
+size_t pal_plat_fsSizeCheck(const char *stringToChk);
+
+
+
+/*! \brief This function sets up the mount point.
+*
+*
+* @param void
+*
+* \return PAL_SUCCESS upon a successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see the error code description \c palError_t.
+*
+*/
+palStatus_t pal_plat_fsMountSystem(void);
+/**
+@} */
+
+
+/*! \brief This function formats the SD partition indicated by `partitionID` (mapping the ID to an actual partition is done in the porting layer).
+*
+*
+* @param[in] partitionID The ID of the partition to be formatted.
+*
+* \return PAL_SUCCESS upon a successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see the error code description \c palError_t.
+*
+*/
+palStatus_t pal_plat_fsFormat(pal_fsStorageID_t dataID);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_internalFlash.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#ifndef PAL_PLAT_FLASH_H_
+#define PAL_PLAT_FLASH_H_
+
+#include "pal_internalFlash.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! \brief This function initialized the flash API module,
+ * 			And should be called prior flash APIs calls
+ *
+ * \return   PAL_SUCCESS upon successful operation. \n
+ *           PAL_ERR_INTERNAL_FLASH_ERROR - see error code \c palError_t.
+ *
+ * \note should be called only once unless \c pal_InternalFlashDeinit function is called
+ * \note This function is Blocking till completion!!
+ *
+ */
+palStatus_t pal_plat_internalFlashInit(void);
+
+/*! \brief This function destroy the flash module
+ *
+ * \return PAL_SUCCESS upon successful operation. \n
+ *         PAL_ERR_INTERNAL_FLASH_ERROR - see error code \c palError_t.
+ *
+ * \note Should be called only after \c pal_InternalFlashinit() is called.
+ * \note Flash APIs will not work after calling this function
+ * \note This function is Blocking till completion!!
+ *
+ */
+palStatus_t pal_plat_internalFlashDeInit(void);
+
+/*! \brief This function writes to the internal flash
+*
+* @param[in]	buffer - pointer to the buffer to be written
+* @param[in]	size - the size of the buffer in bytes, must be aligned to minimum writing unit (page size).
+* @param[in]	address - the address of the internal flash.
+*
+* \return PAL_SUCCESS upon successful operation. \n
+*         PAL_ERR_INTERNAL_FLASH_ERROR - see error code \c palError_t.
+*
+* \note This function is Blocking till completion!!
+* \note This function is Thread Safe!!
+*/
+palStatus_t pal_plat_internalFlashWrite(const size_t size, const uint32_t address, const uint32_t * buffer);
+
+/*! \brief This function copies the memory data into the user given buffer
+*
+* @param[in]	size - the size of the buffer in bytes.
+* @param[in]	address - the address of the internal flash.
+* @param[out]	buffer - pointer to the buffer to write to
+*
+* \return PAL_SUCCESS upon successful operation. \n
+*         PAL_ERR_INTERNAL_FLASH_ERROR - see error code \c palError_t.
+* \note This function is Blocking till completion!!
+* \note This function is Thread Safe!!
+*
+*/
+palStatus_t pal_plat_internalFlashRead(const size_t size, const uint32_t address, uint32_t * buffer);
+
+/*! \brief This function Erase the sector
+*
+* @param[in]	size - the size to be erased, must be align to sector.
+* @param[in]	address - sector start address to be erased, must be align to sector.
+*
+* \return PAL_SUCCESS upon successful operation. \n
+*         PAL_ERR_INTERNAL_FLASH_ERROR - see error code \c palError_t.
+*
+* \note ALL sectors can be erased!! No protection to bootloader, program or other...
+* \note This function is Blocking till completion!!
+* \note Only one sector can be erased in each function call
+* \note This function is Thread Safe!!
+*/
+palStatus_t pal_plat_internalFlashErase(uint32_t address, size_t size);
+
+/*! \brief This function returns the minimum writing unit to the flash
+*
+* \return size_t the 2, 4, 8....
+*/
+size_t pal_plat_internalFlashGetPageSize(void);
+
+
+/*! \brief This function returns the sector size
+ *
+* @param[in]	address - the starting address of the sector is question
+*
+* \return size of sector, 0 if error
+*/
+size_t pal_plat_internalFlashGetSectorSize(uint32_t address);
+
+
+
+///////////////////////////////////////////////////////////////
+////-------------------SOTP functions------------------------//
+///////////////////////////////////////////////////////////////
+/*! \brief This function return the SOTP section data
+*
+* @param[in]	section - the section number (0 or 1)
+* @param[out]	data - the information about the section
+*
+* \return PAL_SUCCESS upon successful operation. \n
+*         PAL_ERR_INTERNAL_FLASH_ERROR - see error code \c palError_t.
+*
+*/
+palStatus_t pal_plat_internalFlashGetAreaInfo(uint8_t section, palSotpAreaData_t *data);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PAL_PLAT_FLASH_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_network.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef _PAL_PLAT_SOCKET_H
+#define _PAL_PLAT_SOCKET_H
+
+#include "pal.h"
+#include "pal_network.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! \file pal_plat_network.h
+*  \brief PAL network - platform.
+*   This file contains the network APIs that need to be implemented in the platform layer.
+*/
+
+//! PAL network socket API /n
+//! PAL network socket configuration options:
+//! - define PAL_NET_TCP_AND_TLS_SUPPORT if TCP is supported by the platform and is required.
+//! - define PAL_NET_ASYNCHRONOUS_SOCKET_API if asynchronous socket API is supported by the platform. Currently MANDATORY.
+//! - define PAL_NET_DNS_SUPPORT if DNS name resolution is supported.
+
+/*! Initialize sockets - must be called before other socket functions (is called from PAL init).
+* @param[in] context Optional context - if not available/applicable use NULL.
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_socketsInit(void* context);
+
+/*! Register a network interface for use with PAL sockets - must be called before other socket functions - most APIs will not work before a single interface is added.
+* @param[in] networkInterfaceContext The context of the network interface to be added (OS specific. In mbed OS, this is the NetworkInterface object pointer for the network adapter [**note:** We assume connect has already been called on this]). - if not available use NULL (may not be required on some OSs).
+* @param[out] interfaceIndex Contains the index assigned to the interface if it has been assigned successfully. This index can be used when creating a socket to bind the socket to the interface.
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_registerNetworkInterface(void* networkInterfaceContext, uint32_t* interfaceIndex);
+
+/*! Initialize terminate - can be called when sockets are no longer needed to free socket resources allocated by init.
+* @param[in] context Optional context - if not available use NULL.
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_socketsTerminate(void* context);
+
+/*! Get a network socket.
+* @param[in] domain The domain of the created socket (see `palSocketDomain_t` for supported types).
+* @param[in] type The type of the created socket (see `palSocketType_t` for supported types).
+* @param[in] nonBlockingSocket If true, the socket is non-blocking (with O_NONBLOCK set).
+* @param[in] interfaceNum The number of the network interface used for this socket (info in interfaces supported via `pal_getNumberOfNetInterfaces` and `pal_getNetInterfaceInfo`), select PAL_NET_DEFAULT_INTERFACE as the default interface.
+* @param[out] socket The socket is returned through this output parameter.
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_socket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palSocket_t* socket);
+
+/*! Set options for a given network socket. Only a few options are supported (see `palSocketOptionName_t`).
+* @param[in] socket The socket to get options for.
+* @param[in] optionName The name to set the option for (see enum palSocketOptionName_t for supported types).
+* @param[in] optionValue The buffer holding the value to set for the given option.
+* @param[in] optionLength The size of the buffer provided for `optionValue`.
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_setSocketOptions(palSocket_t socket, int optionName, const void* optionValue, palSocketLength_t optionLength);
+
+/*! Check if the given socket is non-blocking.
+* @param[in] socket The socket for which to check non-blocking status.
+* @param[out] isNonBlocking The non-blocking status for the socket (true if non-blocking, otherwise false).
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_isNonBlocking(palSocket_t socket, bool* isNonBlocking);
+
+/*! Bind a given socket to a local address.
+* @param[in] socket The socket to bind.
+* @param[in] myAddress The address to bind to.
+* @param[in] addressLength The length of the address passed in `myAddress`.
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_bind(palSocket_t socket, palSocketAddress_t* myAddress, palSocketLength_t addressLength);
+
+/*! Receive a payload from the given socket.
+* @param[in] socket The socket to receive from [sockets passed to this function should be of type PAL_SOCK_DGRAM (the implementation may support other types as well)].
+* @param[out] buffer The buffer for the payload data.
+* @param[in] length The length of the buffer for the payload data.
+* @param[out] from The address that sent the payload [optional - if not required pass NULL].
+* @param[in, out] fromLength The length of the `from` address. When completed, this contains the amount of data actually written to the `from` address [optional - if not required pass NULL].
+* @param[out] bytesReceived The actual amount of payload data received in the buffer.
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_receiveFrom(palSocket_t socket, void* buffer, size_t length, palSocketAddress_t* from, palSocketLength_t* fromLength, size_t* bytesReceived);
+
+/*! Send a payload to the given address using the given socket.
+* @param[in] socket The socket to use for sending the payload [sockets passed to this function should be of type PAL_SOCK_DGRAM (the implementation may support other types as well)].
+* @param[in] buffer The buffer for the payload data.
+* @param[in] length The length of the buffer for the payload data.
+* @param[in] to The address to which the payload should be sent.
+* @param[in] toLength The length of the `to` address.
+* @param[out] bytesSent The actual amount of payload data sent.
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_sendTo(palSocket_t socket, const void* buffer, size_t length, const palSocketAddress_t* to, palSocketLength_t toLength, size_t* bytesSent);
+
+/*! Close a network socket. \n
+* \note The function recieves `palSocket_t*` and not `palSocket_t` so that it can zero the socket to avoid re-use.
+* @param[in,out] socket Release and zero socket pointed to by given pointer.
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_close(palSocket_t* socket);
+
+/*! Get the number of current network interfaces (interfaces that have been registered through).
+* @param[out] numInterfaces The number of interfaces after a successful call.
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_getNumberOfNetInterfaces(uint32_t* numInterfaces);
+
+/*! Get information regarding the socket at the index/interface number given (this number is returned when registering the socket).
+* @param[in] interfaceNum The number of the interface to get information for.
+* @param[out] interfaceInfo The information for the given interface number.
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t* interfaceInfo);
+
+
+#if PAL_NET_TCP_AND_TLS_SUPPORT // The functionality below is supported only if TCP is supported. 
+
+
+/*! Use a socket to listen to incoming connections. You may also limit the queue of incoming connections.
+* @param[in] socket The socket to listen to [sockets passed to this function should be of type PAL_SOCK_STREAM_SERVER (the implementation may support other types as well)].
+* @param[in] backlog The number of pending connections that can be saved for the socket.
+\return PAL_SUCCESS (0) in case of success. A specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_listen(palSocket_t socket, int backlog);
+
+/*! Accept a connection on the given socket.
+* @param[in] socket The socket on which to accept the connection. The socket needs to be created and bound and listen must have been called on it. [sockets passed to this function should be of type PAL_SOCK_STREAM_SERVER (the implementation may support other types as well)].
+* @param[out] address The source address of the incoming connection.
+* @param[in, out] addressLen The length of the address field on input, the length of the data returned on output.
+* @param[out] acceptedSocket The socket of the accepted connection is returned if the connection is accepted successfully.
+\return PAL_SUCCESS (0) in case of success, a specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_accept(palSocket_t socket, palSocketAddress_t* address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket);
+
+/*! Open a connection from the given socket to the given address.
+* @param[in] socket The socket to use for the connection to the given address [sockets passed to this function should be of type PAL_SOCK_STREAM (the implementation may support other types as well)].
+* @param[in] address The destination address of the connection.
+* @param[in] addressLen The length of the address field.
+\return PAL_SUCCESS (0) in case of success, a specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_connect(palSocket_t socket, const palSocketAddress_t* address, palSocketLength_t addressLen);
+
+/*! Receive data from the given connected socket.
+* @param[in] socket The connected socket on which to receive data [sockets passed to this function should be of type PAL_SOCK_STREAM (the implementation may support other types as well)].
+* @param[out] buf The output buffer for the message data.
+* @param[in] len The length of the input data buffer.
+* @param[out] recievedDataSize The length of the data actually received.
+\return PAL_SUCCESS (0) in case of success, a specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_recv(palSocket_t socket, void* buf, size_t len, size_t* recievedDataSize);
+
+/*! Send a given buffer via the given connected socket.
+* @param[in] socket The connected socket on which to send data [sockets passed to this function should be of type PAL_SOCK_STREAM (the implementation may support other types as well)].
+* @param[in] buf The output buffer for the message data.
+* @param[in] len The length of the input data buffer.
+* @param[out] sentDataSize The length of the data sent.
+\return PAL_SUCCESS (0) in case of success, a specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_send(palSocket_t socket, const void* buf, size_t len, size_t* sentDataSize);
+
+
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+
+/*! Get an asynchronous network socket.
+* @param[in] domain The domain of the created socket (see enum `palSocketDomain_t` for supported types).
+* @param[in] type The type of the created socket (see enum `palSocketType_t` for supported types).
+* @param[in] callback A callback function that is called when any supported event takes place in the given asynchronous socket.
+* @param[in] callbackArgument the argument with which the callback will be called when any supported event takes place in the given asynchronous socket.
+* @param[out] socket This output parameter returns the socket.
+\return PAL_SUCCESS (0) in case of success, a specific negative error code in case of failure.
+*/
+palStatus_t pal_plat_asynchronousSocket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void* callbackArgument , palSocket_t* socket);
+
+#endif
+
+#if PAL_NET_DNS_SUPPORT
+
+/*! This function translates the URL to a `palSocketAddress_t` that can be used with PAL sockets.
+* @param[in] url The URL to be translated to a `palSocketAddress_t`.
+* @param[out] address The address for the output of the translation.
+*/
+palStatus_t pal_plat_getAddressInfo(const char* url, palSocketAddress_t* address, palSocketLength_t* addressLength);
+
+#ifdef PAL_DNS_API_V2
+/*! This function translates the URL to a `palSocketAddress_t` that can be used with PAL sockets.
+* @param[in] info address of `pal_asyncAddressInfo_t`.
+*/
+palStatus_t pal_plat_getAddressInfoAsync(pal_asyncAddressInfo_t* info);
+
+/*! This function is cancelation for pal_plat_getAddressInfoAsync. 
+* @param[in] queryHandle Id of ongoing DNS query.
+*/
+palStatus_t pal_plat_cancelAddressInfoAsync(palDNSQuery_t queryHandle);
+#endif // PAL_DNS_API_V2
+
+#endif // PAL_NET_DNS_SUPPORT
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif //_PAL_PLAT_SOCKET_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_rtos.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,326 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef _PAL_PLAT_RTOS_H
+#define _PAL_PLAT_RTOS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pal.h"
+    
+
+/*! \file pal_plat_rtos.h
+*  \brief PAL RTOS - platform.
+*   This file contains the real-time OS APIs that need to be implemented in the platform layer.
+*/
+
+#define PAL_SHA256_DEVICE_KEY_SIZE_IN_BYTES 32
+#define PAL_DEVICE_KEY_SIZE_IN_BITS (128)
+#define PAL_DEVICE_KEY_SIZE_IN_BYTES (PAL_DEVICE_KEY_SIZE_IN_BITS / 8)
+
+
+/*! Initiate a system reboot.
+*/
+void pal_plat_osReboot(void);
+
+/*! Application provided implementation to replace default pal_osReboot() functionality.
+*/
+void pal_plat_osApplicationReboot(void);
+
+/*! Initialize all data structures (semaphores, mutexes, memory pools, message queues) at system initialization.
+*   In case of a failure in any of the initializations, the function returns an error and stops the rest of the initializations.
+* @param[in] opaqueContext The context passed to the initialization (not required for generic CMSIS, pass NULL in this case).
+* \return PAL_SUCCESS(0) in case of success, PAL_ERR_CREATION_FAILED in case of failure.
+*/
+palStatus_t pal_plat_RTOSInitialize(void* opaqueContext);
+
+/*! De-initialize thread objects.
+*/
+palStatus_t pal_plat_RTOSDestroy(void);
+
+/*! Get the RTOS kernel system timer counter.
+*
+* \return The RTOS kernel system timer counter.
+*
+* \note The required tick counter is the OS (platform) kernel system tick counter.
+* \note If the platform supports 64-bit tick counter, please implement it. If the platform supports only 32 bit, note
+*       that this counter wraps around very often (for example, once every 42 sec for 100Mhz).
+*/
+uint64_t pal_plat_osKernelSysTick(void);
+
+/*! Convert the value from microseconds to kernel sys ticks.
+* This is the same as CMSIS macro `osKernelSysTickMicroSec`.
+*/
+uint64_t pal_plat_osKernelSysTickMicroSec(uint64_t microseconds);
+
+/*! Get the system tick frequency.
+* \return The system tick frequency.
+*
+* \note The system tick frequency MUST be more than 1KHz (at least one tick per millisecond).
+*/
+uint64_t pal_plat_osKernelSysTickFrequency(void);
+
+/*! Create and run the thread.
+*
+* @param[in] function A function pointer to the thread callback function.
+* @param[in] funcArgument An argument for the thread function.
+* @param[in] priority The priority of the thread.
+* @param[in] stackSize The stack size of the thread, can NOT be 0.
+* @param[out] threadID: The created thread ID handle. In case of error, this value is NULL.
+*
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*
+*/
+palStatus_t pal_plat_osThreadCreate(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, palThreadID_t* threadID);
+
+/*! Terminate and free allocated data for the thread.
+*
+* @param[in] threadData A pointer to a palThreadData_t structure containing information about the thread.
+*
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*
+*/
+palStatus_t pal_plat_osThreadTerminate(palThreadID_t* threadID);
+
+/*! Get the ID of the current thread.
+* \return The ID of the current thread. In case of error, returns PAL_MAX_UINT32.
+*/
+palThreadID_t pal_plat_osThreadGetId(void);
+
+/*! Wait for a specified period of time in milliseconds.
+*
+* @param[in] milliseconds The number of milliseconds to wait before proceeding.
+*
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_osDelay(uint32_t milliseconds);
+
+/*! Create a timer.
+*
+* @param[in] function A function pointer to the timer callback function.
+* @param[in] funcArgument An argument for the timer callback function.
+* @param[in] timerType The timer type to be created, periodic or `oneShot`.
+* @param[out] timerID The ID of the created timer. Zero value indicates an error.
+*
+* \return PAL_SUCCESS when the timer was created successfully. A specific error in case of failure. \n
+*         PAL_ERR_NO_MEMORY: No memory resource available to create a timer object.
+*
+* \note The timer callback function runs according to the platform resources of stack size and priority.
+* \note The create function MUST not wait for platform resources and it should return PAL_ERR_RTOS_RESOURCE, unless the platform API is blocking.
+*/
+palStatus_t pal_plat_osTimerCreate(palTimerFuncPtr function, void* funcArgument, palTimerType_t timerType, palTimerID_t* timerID);
+
+/*! Start or restart a timer.
+*
+* @param[in] timerID The handle for the timer to start.
+* @param[in] millisec: The time in milliseconds to set the timer to, MUST be larger than 0.
+*                      In case the value is 0, the error PAL_ERR_RTOS_VALUE will be returned.
+*
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_osTimerStart(palTimerID_t timerID, uint32_t millisec);
+
+/*! Stop a timer.
+*
+* @param[in] timerID The handle for the timer to stop.
+*
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_osTimerStop(palTimerID_t timerID);
+
+/*! Delete the timer object.
+*
+* @param[inout] timerID The handle for the timer to delete. In success, `*timerID` = NULL.
+*
+* \return PAL_SUCCESS when the timer was deleted successfully. PAL_ERR_RTOS_PARAMETER when the `timerID` is incorrect.
+* \note In case of a running timer, `pal_platosTimerDelete()` MUST stop the timer before deletion.
+*/
+palStatus_t pal_plat_osTimerDelete(palTimerID_t* timerID);
+
+/*! Create and initialize a mutex object.
+*
+* @param[out] mutexID The created mutex ID handle, zero value indicates an error.
+*
+* \return PAL_SUCCESS when the mutex was created successfully, a specific error in case of failure. \n
+*         PAL_ERR_NO_MEMORY when there is no memory resource available to create a mutex object.
+* \note The create function MUST NOT wait for the platform resources and it should return PAL_ERR_RTOS_RESOURCE, unless the platform API is blocking.
+*		 By default, the mutex is created with a recursive flag set.
+*/
+palStatus_t pal_plat_osMutexCreate(palMutexID_t* mutexID);
+
+/*! Wait until a mutex becomes available.
+*
+* @param[in] mutexID The handle for the mutex.
+* @param[in] millisec The timeout for the waiting operation if the timeout expires before the semaphore is released and an error is returned from the function.
+*
+* \return PAL_SUCCESS(0) in case of success. One of the following error codes in case of failure: \n
+*         - PAL_ERR_RTOS_RESOURCE - Mutex not available but no timeout set. \n
+*         - PAL_ERR_RTOS_TIMEOUT - Mutex was not available until timeout expired. \n
+*         - PAL_ERR_RTOS_PARAMETER - The mutex ID is invalid. \n
+*         - PAL_ERR_RTOS_ISR - Cannot be called from interrupt service routines.
+*/
+palStatus_t pal_plat_osMutexWait(palMutexID_t mutexID, uint32_t millisec);
+
+/*! Release a mutex that was obtained by `osMutexWait`.
+*
+* @param[in] mutexID The handle for the mutex.
+*
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_osMutexRelease(palMutexID_t mutexID);
+
+/*! Delete a mutex object.
+*
+* @param[inout] mutexID The ID of the mutex to delete. In success, `*mutexID` = NULL.
+*
+* \return PAL_SUCCESS when the mutex was deleted successfully, one of the following error codes in case of failure: \n
+*         - PAL_ERR_RTOS_RESOURCE - Mutex already released. \n
+*         - PAL_ERR_RTOS_PARAMETER - Mutex ID is invalid. \n
+*         - PAL_ERR_RTOS_ISR - Cannot be called from interrupt service routines.
+* \note After this call, `mutex_id` is no longer valid and cannot be used.
+*/
+palStatus_t pal_plat_osMutexDelete(palMutexID_t* mutexID);
+
+/*! Create and initialize a semaphore object.
+*
+* @param[in] count The number of available resources.
+* @param[out] semaphoreID The ID of the created semaphore, zero value indicates an error.
+*
+* \return PAL_SUCCESS when the semaphore was created successfully, a specific error in case of failure. \n
+*         PAL_ERR_NO_MEMORY: No memory resource available to create a semaphore object.
+* \note The create function MUST not wait for the platform resources and it should return PAL_ERR_RTOS_RESOURCE, unless the platform API is blocking.
+*/
+palStatus_t pal_plat_osSemaphoreCreate(uint32_t count, palSemaphoreID_t* semaphoreID);
+
+/*! Wait until a semaphore token becomes available.
+*
+* @param[in] semaphoreID The handle for the semaphore.
+* @param[in] millisec The timeout for the waiting operation if the timeout expires before the semaphore is released and an error is returned from the function.
+* @param[out] countersAvailable The number of semaphores available. If semaphores are not available (timeout/error) zero is returned. 
+* \return PAL_SUCCESS(0) in case of success. One of the following error codes in case of failure: \n
+*       - PAL_ERR_RTOS_TIMEOUT - Semaphore was not available until timeout expired. \n
+*       - PAL_ERR_RTOS_PARAMETER - Semaphore ID is invalid.
+*/
+palStatus_t pal_plat_osSemaphoreWait(palSemaphoreID_t semaphoreID, uint32_t millisec, int32_t* countersAvailable);
+
+/*! Release a semaphore token.
+*
+* @param[in] semaphoreID The handle for the semaphore.
+*
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_osSemaphoreRelease(palSemaphoreID_t semaphoreID);
+
+/*! Delete a semaphore object.
+*
+* @param[inout] semaphoreID: The ID of the semaphore to delete. In success, `*semaphoreID` = NULL.
+*
+* \return PAL_SUCCESS when the semaphore was deleted successfully. One of the following error codes in case of failure: \n
+*         PAL_ERR_RTOS_RESOURCE - Semaphore already released. \n
+*         PAL_ERR_RTOS_PARAMETER - Semaphore ID is invalid.
+* \note After this call, the `semaphore_id` is no longer valid and cannot be used.
+*/
+palStatus_t pal_plat_osSemaphoreDelete(palSemaphoreID_t* semaphoreID);
+
+
+/*! Perform an atomic increment for a signed32 bit value.
+*
+* @param[in,out] valuePtr The address of the value to increment.
+* @param[in] increment The number by which to increment.
+*
+* \returns The value of the `valuePtr` after the increment operation.
+*/
+int32_t pal_plat_osAtomicIncrement(int32_t* valuePtr, int32_t increment);
+
+/*! Perform allocation from the heap according to the OS specification.
+*
+* @param[in] len The length of the buffer to be allocated.
+*
+* \returns `void *`. The pointer of the malloc received from the OS if NULL error occurred
+*/
+void *pal_plat_malloc(size_t len);
+
+/*! Free memory back to the OS heap.
+*
+* @param[in] *buffer A pointer to the buffer that should be free.
+*
+* \returns `void`
+*/
+ void pal_plat_free(void * buffer);
+
+/*! Generate a random number into the given buffer with the given size in bytes.
+*
+* @param[out] randomBuf A buffer to hold the generated number.
+* @param[in] bufSizeBytes The size of the buffer and the size of the required random number to generate.
+* @param[out] actualRandomSizeBytes The actual size of the written random data to the output buffer.
+\return PAL_SUCCESS on success. A negative value indicating a specific error code in case of failure.
+\note In case the platform was able to provide random data with non-zero size and less than `bufSizeBytes`the function must return `PAL_ERR_RTOS_TRNG_PARTIAL_DATA`
+*/
+palStatus_t pal_plat_osRandomBuffer(uint8_t *randomBuf, size_t bufSizeBytes, size_t* actualRandomSizeBytes);
+
+
+/*! Retrieve platform Root of Trust certificate
+*
+* @param[in,out] *keyBuf A pointer to the buffer that holds the RoT.
+* @param[in] keyLenBytes The size of the buffer to hold the 128 bit key, must be at least 16 bytes.
+* The buffer needs to be able to hold 16 bytes of data.
+*
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*/
+
+palStatus_t pal_plat_osGetRoTFromHW(uint8_t *keyBuf, size_t keyLenBytes);
+
+/*! \brief  This function calls the platform layer and sets the new RTC to the H/W
+*
+* @param[in] uint64_t rtcSetTime the new RTC time
+*
+* \return PAL_SUCCESS when the RTC return correctly
+*
+*/
+palStatus_t pal_plat_osSetRtcTime(uint64_t rtcSetTime);
+
+/*! \brief This function gets the RTC from the platform
+*
+* @param[out] uint64_t * rtcGetTime - Holds the RTC value
+*
+* \return PAL_SUCCESS when the RTC return correctly
+*
+*/
+palStatus_t pal_plat_osGetRtcTime(uint64_t *rtcGetTime);
+
+
+/*! \brief This function DeInitialize the RTC module
+*
+* \return PAL_SUCCESS when the success or error upon failing
+*
+*/
+palStatus_t pal_plat_rtcDeInit(void);
+
+
+/*! \brief This function initialize the RTC module
+*
+* \return PAL_SUCCESS when the success or error upon failing
+*
+*/
+palStatus_t pal_plat_rtcInit(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //_PAL_COMMON_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Platform-API/pal_plat_update.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef PAL_PLAT_UPDATE_HEADER
+#define PAL_PLAT_UPDATE_HEADER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "pal.h"
+
+
+/*! \file pal_plat_update.h
+*  \brief PAL update - platform.
+*   This file contains the firmware update APIs that need to be implemented in the platform layer.
+*/
+
+
+/*! Set the callback function that is called before the end of each API (except `imageGetDirectMemAccess`).
+* @param[in] CBfunction A pointer to the callback function.
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_imageInitAPI(palImageSignalEvent_t CBfunction);
+
+
+/*! Clear all the resources used by the `pal_update` APIs.
+ * \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_imageDeInit(void);
+
+/*! Set the `imageNumber` to the number of available images. You can do this through the hard coded define inside the linker script.  
+* @param[out] imageNumber The total number of images the system supports.
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_imageGetMaxNumberOfImages(uint8_t* imageNumber);
+
+/*! Claim space in the relevant storage region for `imageId` with the size of the image.
+* @param[in] imageId The image ID.
+* @param[in] imageSize The size of the images.
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_imageReserveSpace(palImageId_t imageId, size_t imageSize);
+
+
+/*! Set up the details for the image header. The data is written when the image write is called for the first time.
+* @param[in] imageId The image ID.
+* @param[in] details The data needed to build the image header.
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_imageSetHeader(palImageId_t imageId,palImageHeaderDeails_t* details);
+
+/*! Write the data in the chunk buffer with the size written in chunk `bufferLength` in the location of `imageId` adding the relative offset.
+ * @param[in] imageId The image ID.
+ * @param[in] offset The relative offset to write the data into.
+ * @param[in] chunk A pointer to the struct containing the data and the data length to write.
+ * \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_imageWrite(palImageId_t imageId, size_t offset, palConstBuffer_t*  chunk);
+
+/*! Update the image version of `imageId` to the version written in version buffer with version `bufferLength`.
+* @param[in] imageId The image ID.
+* @param[in] version The image version and its length.
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+*/
+palStatus_t pal_plat_imageSetVersion(palImageId_t imageId, const palConstBuffer_t* version);
+
+/*! Flush the entire image data after writing ends for `imageId`.
+* @param[in] imageId The image ID.
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_imageFlush(palImageId_t imageId);
+
+/*! Verify whether the `imageId` is readable and set `imagePtr` to point to the beginning of the image in the memory and `imageSizeInBytes` to the image size. \n
+* @param[in] imageId The image ID.
+* @param[out] imagePtr A pointer to the start of the image.
+* @param[out] imageSizeInBytes The size of the image.
+* \return PAL_SUCCESS(0) in case of success. A negative value indicating a specific error code in case of failure and sets `imagePtr` to NULL. 
+*/
+palStatus_t pal_plat_imageGetDirectMemAccess(palImageId_t imageId, void** imagePtr, size_t* imageSizeInBytes);
+
+
+/*! Read the max of chunk `maxBufferLength` bytes from the `imageId` with relative offset and store it in chunk buffer. \n
+* Set the chunk `bufferLength` value to the actual number of bytes read.
+* \note Please use this API in case the image is not directly accessible via the `imageGetDirectMemAccess` function.
+* @param[in] imageId The image ID.
+* @param[in] offset The offset to start reading from.
+* @param[out] chunk The data and actual bytes read.
+*/
+palStatus_t pal_plat_imageReadToBuffer(palImageId_t imageId, size_t offset, palBuffer_t* chunk);
+
+/*! Set the `imageId` to be the active image (after device reset).
+ * @param[in] imageId The image ID.
+ */
+palStatus_t pal_plat_imageActivate(palImageId_t imageId);
+
+/*! Retrieve the hash value of the active image to the hash buffer with the max size hash `maxBufferLength` and set the hash `bufferLength` to the hash size.
+ * @param[out] hash The hash and actual size of hash read.
+ */
+palStatus_t pal_plat_imageGetActiveHash(palBuffer_t* hash);
+
+/*! Retrieve the version of the active image to the version buffer with the size set to version `bufferLength`.
+ * @param[out] version The version and actual size of version read.
+ */
+palStatus_t pal_plat_imageGetActiveVersion (palBuffer_t* version);
+
+/*! Write the `dataId` stored in `dataBuffer` to the memory accessible to the bootloader. Currently, only HASH is available.
+* @param[in] hashValue The data and size of the HASH.
+ */
+palStatus_t pal_plat_imageWriteHashToMemory(const palConstBuffer_t* const hashValue);
+
+
+
+
+#endif /* SOURCE_PAL_IMPL_MODULES_UPDATE_PAL_PALT_UPDATE_H_ */
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/mbedTLS/Crypto/pal_plat_Crypto.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2028 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "stdlib.h"
+#include "string.h"
+#include "time.h"
+#include "pal.h"
+#include "pal_plat_Crypto.h"
+#include "pal_plat_rtos.h"
+#include "mbedtls/aes.h"
+#if (PAL_ENABLE_X509 == 1)
+#include "mbedtls/asn1write.h"
+#include "mbedtls/x509_crt.h"
+#include "mbedtls/x509_csr.h"
+#endif 
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/sha256.h"
+#include "mbedtls/md.h"
+#include "mbedtls/ccm.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/cmac.h"
+#include "mbedtls/asn1.h"
+#include "mbedtls/ecp.h"
+
+#include "mbedtls/ecdh.h"
+#include "mbedtls/oid.h"
+#include "mbedtls/platform_time.h"
+
+
+typedef mbedtls_ccm_context palCCM_t;
+typedef mbedtls_ecp_group palECGroup_t;
+typedef mbedtls_ecp_point palECPoint_t;
+typedef mbedtls_mpi palMP_t;
+typedef mbedtls_pk_context palECKey_t;
+
+#if (PAL_ENABLE_X509 == 1)
+typedef mbedtls_x509write_csr palx509CSR_t; 
+#endif
+
+typedef mbedtls_cipher_context_t palCipherCtx_t;
+
+
+//! forward declaration
+//! This function is based on PAL random algorithm which uses CTR-DRBG algorithm
+PAL_PRIVATE int pal_plat_entropySource( void *data, unsigned char *output, size_t len);
+
+//! forward declarations
+//! This function access directly to the plarform entropy source
+//! it was added specialy for DRBG reseeding process
+PAL_PRIVATE int pal_plat_entropySourceDRBG( void *data, unsigned char *output, size_t len);
+
+
+typedef struct palSign{
+    mbedtls_mpi r;
+    mbedtls_mpi s;
+}palSignature_t;
+
+typedef struct palCtrDrbgCtx{
+    mbedtls_entropy_context entropy;
+    mbedtls_ctr_drbg_context ctrDrbgCtx;
+}palCtrDrbgCtx_t;
+
+typedef struct palAes{
+    mbedtls_aes_context platCtx;
+    unsigned char stream_block[PAL_CRYPT_BLOCK_SIZE];  //The saved stream-block for resuming. Is overwritten by the function.
+    size_t nc_off;   //The offset in the current stream_block
+}palAes_t;
+
+#if (PAL_ENABLE_X509 == 1)
+typedef struct palX509Ctx{
+    mbedtls_x509_crt crt;
+}palX509Ctx_t;
+#endif
+
+typedef struct palMD{
+     mbedtls_md_context_t md;
+}palMD_t;
+
+#define CRYPTO_PLAT_SUCCESS 0
+#define CRYPTO_PLAT_GENERIC_ERROR (-1)
+
+palStatus_t pal_plat_initCrypto()
+{
+    return PAL_SUCCESS;
+}
+
+palStatus_t pal_plat_cleanupCrypto()
+{
+    return PAL_SUCCESS;
+}
+
+palStatus_t pal_plat_initAes(palAesHandle_t *aes)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palAes_t* localCtx = NULL;
+
+    localCtx = (palAes_t*)malloc(sizeof(palAes_t));
+    if (NULL == localCtx)
+    {
+        status = PAL_ERR_CREATION_FAILED;
+    }
+    else
+    {
+        mbedtls_aes_init(&localCtx->platCtx);
+        localCtx->nc_off = 0;
+        memset(localCtx->stream_block, 0, 16);
+
+        *aes = (palAesHandle_t)localCtx;
+    }
+    return status;
+}
+
+palStatus_t pal_plat_freeAes(palAesHandle_t *aes)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palAes_t* localCtx = NULL;
+    
+    localCtx = (palAes_t*)*aes;
+    
+    mbedtls_aes_free(&localCtx->platCtx);
+    free(localCtx);
+    *aes = NULLPTR;
+    return status;
+}
+
+palStatus_t pal_plat_setAesKey(palAesHandle_t aes, const unsigned char* key, uint32_t keybits, palAesKeyType_t keyTarget)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palAes_t* localCtx = (palAes_t*)aes;
+
+    if (PAL_KEY_TARGET_ENCRYPTION == keyTarget)
+    {
+        platStatus = mbedtls_aes_setkey_enc(&localCtx->platCtx, key, keybits);
+    }
+    else
+    {
+        platStatus = mbedtls_aes_setkey_dec(&localCtx->platCtx, key, keybits);
+    }
+
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_AES_INVALID_KEY_LENGTH;
+    }
+
+    return status;    
+}
+
+palStatus_t pal_plat_aesCTR(palAesHandle_t aes, const unsigned char* input, unsigned char* output, size_t inLen, unsigned char iv[16], bool zeroOffset)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palAes_t* localCtx = (palAes_t*)aes;
+
+    if (true == zeroOffset)
+    {
+        localCtx->nc_off = 0;
+        memset(localCtx->stream_block, 0, 16);
+    }
+
+    platStatus = mbedtls_aes_crypt_ctr(&localCtx->platCtx, inLen, &localCtx->nc_off, iv, localCtx->stream_block, input, output);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        PAL_LOG(ERR, "Crypto aes ctr status %" PRId32 "", platStatus);
+        status = PAL_ERR_GENERIC_FAILURE;
+    }
+    return status;
+}
+
+palStatus_t pal_plat_aesECB(palAesHandle_t aes, const unsigned char input[PAL_CRYPT_BLOCK_SIZE], unsigned char output[PAL_CRYPT_BLOCK_SIZE], palAesMode_t mode)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palAes_t* localCtx = (palAes_t*)aes;
+
+    platStatus = mbedtls_aes_crypt_ecb(&localCtx->platCtx, (PAL_AES_ENCRYPT == mode ? MBEDTLS_AES_ENCRYPT : MBEDTLS_AES_DECRYPT), input, output);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        PAL_LOG(ERR, "Crypto aes ecb status  %" PRId32 "", platStatus);
+        status = PAL_ERR_GENERIC_FAILURE;
+    }
+    return status;
+}
+
+palStatus_t pal_plat_sha256(const unsigned char* input, size_t inLen, unsigned char* output)
+{    
+    mbedtls_sha256(input, inLen, output, 0);
+     
+    return PAL_SUCCESS;
+}
+#if (PAL_ENABLE_X509 == 1)
+palStatus_t pal_plat_x509Initiate(palX509Handle_t* x509)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palX509Ctx_t* localCtx = NULL;
+
+    localCtx = (palX509Ctx_t*)malloc(sizeof(palX509Ctx_t));
+    if (NULL == localCtx)
+    {
+        status = PAL_ERR_CREATION_FAILED;
+    }
+    else
+    {
+        mbedtls_x509_crt_init(&localCtx->crt);
+        *x509 = (uintptr_t)localCtx;
+    }
+
+    return status;
+}
+
+
+palStatus_t pal_plat_x509CertParse(palX509Handle_t x509, const unsigned char* input, size_t inLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palX509Ctx_t* localCtx = (palX509Ctx_t*)x509;
+
+     platStatus = mbedtls_x509_crt_parse_der(&localCtx->crt, input, inLen);
+    if (platStatus < CRYPTO_PLAT_SUCCESS)
+    {
+		if (MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE == platStatus)
+		{
+			status = PAL_ERR_NOT_SUPPORTED_CURVE;
+		}
+		
+        else if (-(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG) == ((-platStatus) & 0xFF80))
+        {
+            status = PAL_ERR_INVALID_MD_TYPE;
+        }
+        
+        else
+        {
+            status = PAL_ERR_CERT_PARSING_FAILED;
+        }
+    }
+
+    return status;
+}
+
+PAL_PRIVATE palStatus_t pal_plat_x509CertGetID(palX509Ctx_t* x509Cert, uint8_t *id, size_t outLenBytes, size_t* actualOutLenBytes)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+
+    platStatus = mbedtls_ecp_point_write_binary( &((mbedtls_ecp_keypair *)((x509Cert->crt).pk).pk_ctx)->grp, &((mbedtls_ecp_keypair *)((x509Cert->crt).pk).pk_ctx)->Q,
+         MBEDTLS_ECP_PF_COMPRESSED, actualOutLenBytes, id, outLenBytes);
+    if (platStatus != CRYPTO_PLAT_SUCCESS)
+    {
+        status = PAL_ERR_FAILED_TO_WRITE_PUBLIC_KEY;
+    }
+    return status;
+}
+
+PAL_PRIVATE palStatus_t pal_plat_X509GetField(palX509Ctx_t* x509Ctx, const char* fieldName, void* output, size_t outLenBytes, size_t* actualOutLenBytes)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    const char *shortName = NULL;
+    size_t fieldNameLength = 0;
+    mbedtls_x509_name *x509Name = &x509Ctx->crt.subject;
+
+    fieldNameLength = strlen(fieldName);
+    while( x509Name ) 
+    {
+        platStatus = mbedtls_oid_get_attr_short_name(&x509Name->oid, &shortName);
+        if (CRYPTO_PLAT_SUCCESS != platStatus)
+        {
+            status = PAL_ERR_INVALID_IOD; 
+            break;  
+        }
+        if (strncmp(shortName, fieldName, fieldNameLength) == 0)
+        {
+            if (outLenBytes < (x509Name->val.len + 1))
+            {
+                status = PAL_ERR_BUFFER_TOO_SMALL;
+                *actualOutLenBytes = x509Name->val.len + 1;
+                break;
+            }
+            memcpy(output, x509Name->val.p, x509Name->val.len);
+            ((char*)output)[x509Name->val.len] = '\0';
+            *actualOutLenBytes = x509Name->val.len + 1;
+            break;
+        }
+        x509Name = x509Name->next;
+    }
+    return status;
+}
+
+PAL_PRIVATE bool pal_isLeapYear(uint8_t year)
+{
+    bool result = false;
+    if (year % 4 != 0)
+    {
+        result = false;
+    }
+    else if ((year % 100) != 0)
+    {
+        result = true;
+    } 
+    else
+    {
+        result = ((year % 400) == 0);
+    }
+    return result;
+}
+
+PAL_PRIVATE palStatus_t pal_timegm( struct tm *tm, uint64_t* outTime) 
+{
+    uint64_t epoc = 0;
+    uint8_t palMonthDays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+    if (NULL == outTime || NULL == tm || tm->tm_year < 1970 || tm->tm_mon > 12)
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    for (uint16_t y = 1970; y < tm->tm_year; ++y)
+    {
+        if (pal_isLeapYear(y))
+        {
+            epoc += 366 * PAL_SECONDS_PER_DAY;
+        }
+        else
+        {
+            epoc += 365 * PAL_SECONDS_PER_DAY;
+        }      
+    }
+    
+    for (uint8_t m = 1; m < tm->tm_mon; ++m) 
+    {
+        epoc += palMonthDays[m - 1] * PAL_SECONDS_PER_DAY;
+        if (m == PAL_FEB_MONTH && pal_isLeapYear(tm->tm_year))
+        {
+            epoc += PAL_SECONDS_PER_DAY;
+        }
+    }
+
+    epoc += (tm->tm_mday - 1) * PAL_SECONDS_PER_DAY;
+    epoc += tm->tm_hour * PAL_SECONDS_PER_HOUR;
+    epoc += tm->tm_min * PAL_SECONDS_PER_MIN;
+    epoc += tm->tm_sec;
+    *outTime = epoc;
+    return PAL_SUCCESS;
+}
+
+
+palStatus_t pal_plat_x509CertGetAttribute(palX509Handle_t x509Cert, palX509Attr_t attr, void* output, size_t outLenBytes, size_t* actualOutLenBytes)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palX509Ctx_t* localCtx = (palX509Ctx_t*)x509Cert;
+    *actualOutLenBytes = 0;
+
+    switch(attr)
+    {
+        case PAL_X509_ISSUER_ATTR:
+            if (localCtx->crt.issuer_raw.len <= outLenBytes)
+            {
+                memcpy(output, localCtx->crt.issuer_raw.p, localCtx->crt.issuer_raw.len);
+            }
+            else
+            {
+                status = PAL_ERR_BUFFER_TOO_SMALL;
+            }
+            *actualOutLenBytes = localCtx->crt.issuer_raw.len;
+            break;
+
+        case PAL_X509_SUBJECT_ATTR:
+            if (localCtx->crt.subject_raw.len <= outLenBytes)
+            {
+                memcpy(output, localCtx->crt.subject_raw.p, localCtx->crt.subject_raw.len);
+            }
+            else
+            {
+                status = PAL_ERR_BUFFER_TOO_SMALL;
+            }
+            *actualOutLenBytes = localCtx->crt.subject_raw.len;
+            break;
+
+        case PAL_X509_VALID_FROM:
+            if ( PAL_CRYPTO_CERT_DATE_LENGTH > outLenBytes)
+            {
+                status = PAL_ERR_BUFFER_TOO_SMALL;
+            }
+            else
+            {
+                struct tm time;
+                uint64_t timeOfDay;
+                time.tm_year = localCtx->crt.valid_from.year;
+                time.tm_mon = localCtx->crt.valid_from.mon;
+                time.tm_mday = localCtx->crt.valid_from.day;
+                time.tm_hour = localCtx->crt.valid_from.hour;
+                time.tm_min = localCtx->crt.valid_from.min;
+                time.tm_sec = localCtx->crt.valid_from.sec;
+                time.tm_isdst = -1;                                   //unknown DST 
+                status = pal_timegm(&time, &timeOfDay);
+                if (PAL_SUCCESS != status)
+                {
+                    status = PAL_ERR_TIME_TRANSLATE;
+                }
+                else
+                {
+                    memcpy(output, &timeOfDay, PAL_CRYPTO_CERT_DATE_LENGTH);
+                }
+            }
+            *actualOutLenBytes = PAL_CRYPTO_CERT_DATE_LENGTH;
+            break;
+	    
+        case PAL_X509_VALID_TO:
+            if ( PAL_CRYPTO_CERT_DATE_LENGTH > outLenBytes)
+            {
+                status = PAL_ERR_BUFFER_TOO_SMALL;
+            }
+            else
+            {
+                struct tm time;
+                uint64_t timeOfDay;
+                time.tm_year = localCtx->crt.valid_to.year;
+                time.tm_mon = localCtx->crt.valid_to.mon;
+                time.tm_mday = localCtx->crt.valid_to.day;
+                time.tm_hour = localCtx->crt.valid_to.hour;
+                time.tm_min = localCtx->crt.valid_to.min;
+                time.tm_sec = localCtx->crt.valid_to.sec;
+                time.tm_isdst = -1;                                 //unknown DST
+                status = pal_timegm(&time, &timeOfDay);
+                if (PAL_SUCCESS != status)
+                {
+                    status = PAL_ERR_TIME_TRANSLATE;
+                }
+                else
+                {
+                    memcpy(output, &timeOfDay, PAL_CRYPTO_CERT_DATE_LENGTH);
+                }
+            }
+            *actualOutLenBytes = PAL_CRYPTO_CERT_DATE_LENGTH;
+            break;
+        
+        case PAL_X509_CN_ATTR:
+            status = pal_plat_X509GetField(localCtx, "CN", output, outLenBytes, actualOutLenBytes);
+            break; 
+
+        case PAL_X509_L_ATTR:
+            status = pal_plat_X509GetField(localCtx, "L", output, outLenBytes, actualOutLenBytes);
+            break;
+
+        case PAL_X509_OU_ATTR:
+            status = pal_plat_X509GetField(localCtx, "OU", output, outLenBytes, actualOutLenBytes);
+            break;
+        
+        case PAL_X509_CERT_ID_ATTR:
+            if (PAL_CERT_ID_SIZE > outLenBytes)
+            {
+                status = PAL_ERR_BUFFER_TOO_SMALL;
+                *actualOutLenBytes = PAL_CERT_ID_SIZE;
+            }
+            else
+            {
+                status = pal_plat_x509CertGetID(localCtx, output, outLenBytes, actualOutLenBytes);
+            }
+            break;
+
+        case PAL_X509_SIGNATUR_ATTR:
+            if (localCtx->crt.sig.len > outLenBytes) {
+                status = PAL_ERR_BUFFER_TOO_SMALL;
+                break;
+            }
+
+            memcpy(output, localCtx->crt.sig.p, localCtx->crt.sig.len);
+            *actualOutLenBytes = localCtx->crt.sig.len;
+            break;
+
+        default:
+           status = PAL_ERR_INVALID_X509_ATTR;
+    }
+    return status;
+}
+
+PAL_PRIVATE const mbedtls_x509_crt_profile s_PALProfile =
+{
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ),
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ) | MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ),
+    MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ),
+    0x7FFFFFFF // RSA not allowed
+};
+
+palStatus_t pal_plat_x509CertVerifyExtended(palX509Handle_t x509Cert, palX509Handle_t x509CertChain, int32_t* verifyResult)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palX509Ctx_t* localCert = (palX509Ctx_t*)x509Cert;
+    palX509Ctx_t* localCAChain = (palX509Ctx_t*)x509CertChain;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    uint32_t flags = 0;
+    *verifyResult = 0;
+
+    if (NULL == localCAChain)
+    {
+        platStatus = mbedtls_x509_crt_verify_with_profile(&localCert->crt, NULL, NULL, &s_PALProfile, NULL, &flags, NULL, NULL);
+    }
+    else
+    {
+        platStatus = mbedtls_x509_crt_verify_with_profile(&localCert->crt, &localCAChain->crt, NULL, &s_PALProfile, NULL, &flags, NULL, NULL);
+    }
+
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_X509_CERT_VERIFY_FAILED;
+        //! please DO NOT change errors order
+        if (MBEDTLS_X509_BADCERT_NOT_TRUSTED & flags)
+        {
+            *verifyResult |= PAL_ERR_X509_BADCERT_NOT_TRUSTED;
+            status = PAL_ERR_X509_BADCERT_NOT_TRUSTED;
+        }
+        if (MBEDTLS_X509_BADCERT_BAD_KEY & flags)
+        {
+            *verifyResult |= PAL_ERR_X509_BADCERT_BAD_KEY;
+            status = PAL_ERR_X509_BADCERT_BAD_KEY;
+        }
+        if (MBEDTLS_X509_BADCERT_BAD_PK & flags)
+        {
+            *verifyResult |= PAL_ERR_X509_BADCERT_BAD_PK;
+            status = PAL_ERR_X509_BADCERT_BAD_PK;
+        }
+        if (MBEDTLS_X509_BADCERT_BAD_MD & flags)
+        {
+            *verifyResult |= PAL_ERR_X509_BADCERT_BAD_MD;
+            status = PAL_ERR_X509_BADCERT_BAD_MD;
+        }
+        if (MBEDTLS_X509_BADCERT_FUTURE & flags)
+        {
+            *verifyResult |= PAL_ERR_X509_BADCERT_FUTURE;
+            status = PAL_ERR_X509_BADCERT_FUTURE;
+        }
+        if (MBEDTLS_X509_BADCERT_EXPIRED & flags)
+        {
+            *verifyResult |= PAL_ERR_X509_BADCERT_EXPIRED;
+            status = PAL_ERR_X509_BADCERT_EXPIRED;
+        }
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_x509Free(palX509Handle_t* x509)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palX509Ctx_t* localCtx = NULL;
+
+    localCtx = (palX509Ctx_t*)*x509;
+    mbedtls_x509_crt_free(&localCtx->crt);
+    free(localCtx);
+    *x509 = NULLPTR;
+    return status;
+}
+
+#endif
+
+palStatus_t pal_plat_mdInit(palMDHandle_t* md, palMDType_t mdType)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palMD_t* localCtx = NULL;
+    const mbedtls_md_info_t* mdInfo = NULL;
+    mbedtls_md_type_t mdAlg = MBEDTLS_MD_NONE;
+
+    localCtx = (palMD_t*)malloc(sizeof(palMD_t));
+    if (NULL == localCtx)
+    {
+        status = PAL_ERR_CREATION_FAILED;
+        goto finish;
+    }
+
+    
+    mbedtls_md_init(&localCtx->md);
+    
+    switch (mdType)
+    {
+        case PAL_SHA256:
+            mdAlg = MBEDTLS_MD_SHA256;
+            break;
+        default:
+            status = PAL_ERR_INVALID_MD_TYPE;
+            goto finish;
+    }
+
+    mdInfo = mbedtls_md_info_from_type(mdAlg);
+    if (NULL == mdInfo)
+    {
+        status = PAL_ERR_INVALID_MD_TYPE;
+        goto finish;
+    }
+
+    platStatus = mbedtls_md_setup(&localCtx->md, mdInfo, 0); // 0 because we don't want to use HMAC in mbedTLS to save memory
+    switch(platStatus)
+    {
+        case CRYPTO_PLAT_SUCCESS:
+            break;
+        case MBEDTLS_ERR_MD_BAD_INPUT_DATA:
+            {
+                status = PAL_ERR_MD_BAD_INPUT_DATA;
+                goto finish;
+            }
+        case MBEDTLS_ERR_MD_ALLOC_FAILED:
+            {
+                status = PAL_ERR_CREATION_FAILED;
+                goto finish;
+            }
+        default: 
+            {
+                PAL_LOG(ERR, "Crypto md start setup  %" PRId32 "", platStatus);
+                status = PAL_ERR_GENERIC_FAILURE;
+                goto finish;
+            }
+    }
+    
+    platStatus = mbedtls_md_starts(&localCtx->md);
+    switch(platStatus)
+    {
+        case CRYPTO_PLAT_SUCCESS:
+            break;
+        case MBEDTLS_ERR_MD_BAD_INPUT_DATA:
+            {
+                status = PAL_ERR_MD_BAD_INPUT_DATA;
+                goto finish;
+            }
+        default: 
+            {
+                PAL_LOG(ERR, "Crypto md start status  %" PRId32 "", platStatus);
+                status = PAL_ERR_GENERIC_FAILURE;
+                goto finish;
+            }
+    }
+
+    *md = (uintptr_t)localCtx;
+finish:
+    if (PAL_SUCCESS != status && NULL != localCtx)
+    {
+        free(localCtx);
+    }
+    return status;
+}
+
+palStatus_t pal_plat_mdUpdate(palMDHandle_t md, const unsigned char* input, size_t inLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palMD_t* localCtx = (palMD_t*)md;
+
+    platStatus =  mbedtls_md_update(&localCtx->md, input, inLen);
+    switch(platStatus)
+    {
+        case CRYPTO_PLAT_SUCCESS:
+            break;
+        case MBEDTLS_ERR_MD_BAD_INPUT_DATA:
+            status = PAL_ERR_MD_BAD_INPUT_DATA;
+            break;
+        default: 
+            {
+                PAL_LOG(ERR, "Crypto md update status %" PRId32 "", platStatus);
+                status = PAL_ERR_GENERIC_FAILURE;
+            }
+    }
+    return status;
+}
+
+palStatus_t pal_plat_mdGetOutputSize(palMDHandle_t md, size_t* bufferSize)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palMD_t* localCtx = (palMD_t*)md;
+
+    if (NULL != localCtx->md.md_info)
+    {
+        *bufferSize = (size_t)mbedtls_md_get_size(localCtx->md.md_info);
+    }
+    else
+    {
+        PAL_LOG(ERR, "Crypto md get size error");
+        status = PAL_ERR_GENERIC_FAILURE;
+    }
+    
+    return status;
+}
+
+palStatus_t pal_plat_mdFinal(palMDHandle_t md, unsigned char* output)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palMD_t* localCtx = (palMD_t*)md;
+
+    platStatus =  mbedtls_md_finish(&localCtx->md, output);
+    switch(platStatus)
+    {
+        case CRYPTO_PLAT_SUCCESS:
+            break;
+        case MBEDTLS_ERR_MD_BAD_INPUT_DATA:
+            status = PAL_ERR_MD_BAD_INPUT_DATA;
+            break;
+        default: 
+            {
+                PAL_LOG(ERR, "Crypto md finish status %" PRId32 "", platStatus);
+                status = PAL_ERR_GENERIC_FAILURE;
+            }
+    } 
+    return status;
+}
+
+palStatus_t pal_plat_mdFree(palMDHandle_t* md)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palMD_t* localCtx = NULL;
+
+    localCtx = (palMD_t*)*md;
+    mbedtls_md_free(&localCtx->md);
+    free(localCtx);
+    *md = NULLPTR;
+    return status;
+}
+#if (PAL_ENABLE_X509 == 1)
+palStatus_t pal_plat_verifySignature(palX509Handle_t x509, palMDType_t mdType, const unsigned char *hash, size_t hashLen, const unsigned char *sig, size_t sigLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    mbedtls_md_type_t mdAlg = MBEDTLS_MD_NONE;
+    palX509Ctx_t* localCtx = (palX509Ctx_t*)x509;
+
+    switch (mdType)
+    {
+        case PAL_SHA256:
+            mdAlg = MBEDTLS_MD_SHA256;
+            break;
+        default:
+            status = PAL_ERR_INVALID_MD_TYPE;
+            goto finish;
+    }
+
+    platStatus = mbedtls_pk_verify(&localCtx->crt.pk, mdAlg, hash, hashLen, sig, sigLen);
+    if (platStatus < CRYPTO_PLAT_SUCCESS)
+    {
+        status = PAL_ERR_PK_SIG_VERIFY_FAILED;
+    }
+finish:
+    return status;
+}
+#endif 
+
+palStatus_t pal_plat_ASN1GetTag(unsigned char **position, const unsigned char *end, size_t *len, uint8_t tag )
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    int platTag = 0;
+
+    switch (tag & PAL_ASN1_CLASS_BITS) 
+    {
+        case 0x00:
+            //MBEDTLS_ASN1_PRIMITIVE
+            break;
+        case PAL_ASN1_CONTEXT_SPECIFIC:
+            platTag |= MBEDTLS_ASN1_CONTEXT_SPECIFIC;
+            break;
+        default:
+            status = PAL_ERR_NOT_SUPPORTED_ASN_TAG;
+            goto finish;
+    }
+
+    if (tag & PAL_ASN1_CONSTRUCTED)
+    {
+        platTag |= MBEDTLS_ASN1_CONSTRUCTED;
+    }
+
+
+    switch(tag & PAL_ASN1_TAG_BITS)
+    {
+    case PAL_ASN1_BOOLEAN:
+        platTag |= MBEDTLS_ASN1_BOOLEAN;
+        break;
+    case PAL_ASN1_INTEGER:
+        platTag |= MBEDTLS_ASN1_INTEGER;
+            break;
+    case PAL_ASN1_BIT_STRING:
+        platTag |= MBEDTLS_ASN1_BIT_STRING;
+            break;
+    case PAL_ASN1_OCTET_STRING:
+        platTag |= MBEDTLS_ASN1_OCTET_STRING;
+                break;
+    case PAL_ASN1_NULL:
+        platTag |= MBEDTLS_ASN1_NULL;
+                break;
+    case PAL_ASN1_OID:
+        platTag |= MBEDTLS_ASN1_OID;
+                break;
+    case PAL_ASN1_UTF8_STRING:
+        platTag |= MBEDTLS_ASN1_UTF8_STRING;
+                break;
+    case PAL_ASN1_SEQUENCE:
+        platTag |= MBEDTLS_ASN1_SEQUENCE;
+                break;
+    case PAL_ASN1_SET:
+        platTag |= MBEDTLS_ASN1_SET;
+                break;
+    case PAL_ASN1_PRINTABLE_STRING:
+        platTag |= MBEDTLS_ASN1_PRINTABLE_STRING;
+                break;
+    case PAL_ASN1_T61_STRING:
+        platTag |= MBEDTLS_ASN1_T61_STRING;
+                break;
+    case PAL_ASN1_IA5_STRING:
+        platTag |= MBEDTLS_ASN1_IA5_STRING;
+                break;
+    case PAL_ASN1_UTC_TIME:
+        platTag |= MBEDTLS_ASN1_UTC_TIME;
+                break;
+    case PAL_ASN1_GENERALIZED_TIME:
+        platTag |= MBEDTLS_ASN1_GENERALIZED_TIME;
+                break;
+    case PAL_ASN1_UNIVERSAL_STRING:
+        platTag |= MBEDTLS_ASN1_UNIVERSAL_STRING;
+                break;
+    case PAL_ASN1_BMP_STRING:
+        platTag |= MBEDTLS_ASN1_BMP_STRING;
+                break;
+    default:
+        status = PAL_ERR_NOT_SUPPORTED_ASN_TAG;
+        goto finish;
+    }
+
+    platStatus =  mbedtls_asn1_get_tag(position, end, len, platTag);
+    if (platStatus < CRYPTO_PLAT_SUCCESS)
+    {
+        status = PAL_ERR_ASN1_UNEXPECTED_TAG;
+    }
+finish:
+    return status;
+}
+
+palStatus_t pal_plat_CCMInit(palCCMHandle_t* ctx)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palCCM_t* ccmCtx = NULL;
+
+    ccmCtx = (palCCM_t*)malloc(sizeof(palCCM_t));
+    if (NULL == ccmCtx)
+    {
+        status = PAL_ERR_NO_MEMORY;
+    }
+    else
+    {
+        mbedtls_ccm_init(ccmCtx);
+        *ctx = (palCCMHandle_t)ccmCtx;
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_CCMFree(palCCMHandle_t* ctx)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palCCM_t* ccmCtx = (palCCM_t*)*ctx;
+
+    mbedtls_ccm_free(ccmCtx);
+    free(ccmCtx);
+    *ctx = NULLPTR;
+    return status;
+}
+
+palStatus_t pal_plat_CCMSetKey(palCCMHandle_t ctx, palCipherID_t id, const unsigned char *key, unsigned int keybits)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palCCM_t* ccmCtx = (palCCM_t*)ctx;
+    mbedtls_cipher_id_t mbedtls_cipher_id;
+
+    switch (id) 
+    {
+        case PAL_CIPHER_ID_AES:
+            mbedtls_cipher_id = MBEDTLS_CIPHER_ID_AES;
+            break;
+        default:
+            return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    platStatus = mbedtls_ccm_setkey(ccmCtx, mbedtls_cipher_id, key, keybits);
+
+    switch(platStatus)
+    {
+    case CRYPTO_PLAT_SUCCESS:
+        status = PAL_SUCCESS;
+        break;
+    default:
+        {
+            PAL_LOG(ERR, "Crypto ccm setkey status %" PRId32 "", platStatus);
+            status = PAL_ERR_GENERIC_FAILURE;
+        }
+    }
+    return status;
+}
+
+palStatus_t pal_plat_CCMDecrypt(palCCMHandle_t ctx, unsigned char* input, size_t inLen, unsigned char* iv, size_t ivLen, unsigned char* add, size_t addLen, unsigned char* tag, size_t tagLen, unsigned char* output)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palCCM_t* ccmCtx = (palCCM_t*)ctx;
+
+    platStatus = mbedtls_ccm_auth_decrypt(ccmCtx, inLen, iv, ivLen, add, addLen, input, output, tag, tagLen);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        switch(platStatus)
+        {
+        default:
+            {
+                PAL_LOG(ERR, "Crypto ccm decrypt status %" PRId32 "", platStatus);
+                status = PAL_ERR_GENERIC_FAILURE;
+            }
+        }
+    }
+    return status;
+}
+
+palStatus_t pal_plat_CCMEncrypt(palCCMHandle_t ctx, unsigned char* input, size_t inLen, unsigned char* iv, size_t ivLen, unsigned char* add, size_t addLen, unsigned char* output, unsigned char* tag, size_t tagLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palCCM_t* ccmCtx = (palCCM_t*)ctx;
+
+    platStatus = mbedtls_ccm_encrypt_and_tag(ccmCtx, inLen, iv, ivLen, add, addLen, input, output, tag, tagLen);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        switch(platStatus)
+        {
+        default:
+            {
+                PAL_LOG(ERR, "Crypto ccm encrypt status %" PRId32 "", platStatus);
+                status = PAL_ERR_GENERIC_FAILURE;
+            }
+        }
+    }
+    return status;
+}
+
+palStatus_t pal_plat_CtrDRBGInit(palCtrDrbgCtxHandle_t* ctx)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palCtrDrbgCtx_t* palCtrDrbgCtx = NULL;
+
+    palCtrDrbgCtx = (palCtrDrbgCtx_t*)malloc(sizeof(palCtrDrbgCtx_t));
+    if (NULL == palCtrDrbgCtx)
+    {
+        status = PAL_ERR_NO_MEMORY;
+    }
+    else
+    {
+        mbedtls_ctr_drbg_init(&palCtrDrbgCtx->ctrDrbgCtx);
+        mbedtls_entropy_init(&palCtrDrbgCtx->entropy);
+        *ctx = (palCtrDrbgCtxHandle_t)palCtrDrbgCtx;
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_CtrDRBGFree(palCtrDrbgCtxHandle_t* ctx)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palCtrDrbgCtx_t* palCtrDrbgCtx = (palCtrDrbgCtx_t*)*ctx;
+
+    mbedtls_ctr_drbg_free(&palCtrDrbgCtx->ctrDrbgCtx);
+    mbedtls_entropy_free(&palCtrDrbgCtx->entropy);
+    free(palCtrDrbgCtx);
+    *ctx = NULLPTR;
+
+    return status;
+}
+
+palStatus_t pal_plat_CtrDRBGSeed(palCtrDrbgCtxHandle_t ctx, const void* seed, size_t len)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palCtrDrbgCtx_t* palCtrDrbgCtx = (palCtrDrbgCtx_t*)ctx;
+
+    platStatus = mbedtls_ctr_drbg_seed_entropy_len(&palCtrDrbgCtx->ctrDrbgCtx, pal_plat_entropySourceDRBG, &palCtrDrbgCtx->entropy, seed, len, 0);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        switch(platStatus)
+        {
+            case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED:
+                status = PAL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
+                break;
+            default:
+                {
+                    PAL_LOG(ERR, "Crypto ctrdrbg seed status %" PRId32 "", platStatus);
+                    status = PAL_ERR_GENERIC_FAILURE;
+                }
+        }
+    }
+    return status;
+}
+
+palStatus_t pal_plat_CtrDRBGGenerate(palCtrDrbgCtxHandle_t ctx, unsigned char* out, size_t len)
+{
+    palStatus_t status = pal_plat_CtrDRBGGenerateWithAdditional(ctx, out, len, NULL, 0);
+    return status;
+}
+
+palStatus_t pal_plat_CtrDRBGGenerateWithAdditional(palCtrDrbgCtxHandle_t ctx, unsigned char* out, size_t len, unsigned char* additional, size_t additionalLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palCtrDrbgCtx_t* palCtrDrbgCtx = (palCtrDrbgCtx_t*)ctx;
+    
+    platStatus = mbedtls_ctr_drbg_random_with_add(&palCtrDrbgCtx->ctrDrbgCtx, out, len, additional, additionalLen);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        switch (platStatus)
+        {
+            case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED:
+                status = PAL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
+                break;
+            case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG:
+                status = PAL_ERR_CTR_DRBG_REQUEST_TOO_BIG;
+                break;
+            default:
+            {
+                PAL_LOG(ERR, "Crypto ctrdrbg generate status %" PRId32 "", platStatus);
+                status = PAL_ERR_GENERIC_FAILURE;
+            }
+        }
+    }
+    return status;
+}
+
+#if PAL_CMAC_SUPPORT
+palStatus_t pal_plat_cipherCMAC(const unsigned char *key, size_t keyLenInBits, const unsigned char *input, size_t inputLenInBytes, unsigned char *output)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    const mbedtls_cipher_info_t *cipherInfo;
+
+    cipherInfo = mbedtls_cipher_info_from_values(MBEDTLS_CIPHER_ID_AES, keyLenInBits, MBEDTLS_MODE_ECB);
+    if (NULL == cipherInfo)
+    {
+        PAL_LOG(ERR, "Crypto cipher cmac error");
+        status = PAL_ERR_CMAC_GENERIC_FAILURE;
+        goto finish;
+    }
+
+    platStatus = mbedtls_cipher_cmac( cipherInfo, key, keyLenInBits, input, inputLenInBytes, output);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        PAL_LOG(ERR, "Crypto cipher cmac status %" PRId32 "", platStatus);
+        status = PAL_ERR_CMAC_GENERIC_FAILURE;
+    }
+finish:
+    return status;
+}
+
+palStatus_t pal_plat_CMACStart(palCMACHandle_t *ctx, const unsigned char *key, size_t keyLenBits, palCipherID_t cipherID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palCipherCtx_t* localCipher = NULL;
+    const mbedtls_cipher_info_t* cipherInfo = NULL;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    mbedtls_cipher_type_t platType = MBEDTLS_CIPHER_NONE;
+
+    switch(cipherID)
+    {
+        case PAL_CIPHER_ID_AES:
+            platType = MBEDTLS_CIPHER_AES_128_ECB;
+            break;
+        default:
+            status = PAL_ERR_INVALID_CIPHER_ID;
+            goto finish;
+    }
+
+    cipherInfo = mbedtls_cipher_info_from_type(platType);
+    if (NULL == cipherInfo)
+    {
+        PAL_LOG(ERR, "Crypto cmac cipher info error");
+        status = PAL_ERR_CMAC_GENERIC_FAILURE;
+        goto finish;
+    }
+
+    localCipher = (palCipherCtx_t*)malloc(sizeof(palCipherCtx_t));
+    if (NULL == localCipher)
+    {
+        status = PAL_ERR_NO_MEMORY;
+        goto finish;
+    }
+
+    mbedtls_cipher_init(localCipher);
+    platStatus = mbedtls_cipher_setup(localCipher, cipherInfo);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        PAL_LOG(ERR, "Crypto cmac cipher setup status %" PRId32 ".", platStatus);
+        status = PAL_ERR_CMAC_GENERIC_FAILURE;
+        goto finish;
+    }
+
+    platStatus = mbedtls_cipher_cmac_starts(localCipher, key, keyLenBits);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_CMAC_START_FAILED;
+        goto finish;
+    }
+
+    *ctx = (palCMACHandle_t)localCipher;
+finish:
+    if (PAL_SUCCESS != status && NULL != localCipher)
+    {
+        free(localCipher);
+    }
+    return status;
+}
+
+palStatus_t pal_plat_CMACUpdate(palCMACHandle_t ctx, const unsigned char *input, size_t inLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palCipherCtx_t* localCipher = (palCipherCtx_t*)ctx;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+
+    platStatus = mbedtls_cipher_cmac_update(localCipher, input, inLen);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_CMAC_UPDATE_FAILED;
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_CMACFinish(palCMACHandle_t *ctx, unsigned char *output, size_t* outLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palCipherCtx_t* localCipher = (palCipherCtx_t*)*ctx;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+
+    platStatus = mbedtls_cipher_cmac_finish(localCipher, output);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_CMAC_FINISH_FAILED;
+    }
+    else
+    {
+        *outLen = localCipher->cipher_info->block_size;
+    }
+
+    
+
+    mbedtls_cipher_free(localCipher);
+    free(localCipher);
+    *ctx = NULLPTR;
+    return status;
+}
+#endif //PAL_CMAC_SUPPORT
+palStatus_t pal_plat_mdHmacSha256(const unsigned char *key, size_t keyLenInBytes, const unsigned char *input, size_t inputLenInBytes, unsigned char *output, size_t* outputLenInBytes)
+{
+    const mbedtls_md_info_t *md_info = NULL;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palStatus_t status = PAL_SUCCESS;
+
+    md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+    if (NULL == md_info)
+    {
+        PAL_LOG(ERR, "Crypto hmac sha256 md info error");
+        status = PAL_ERR_HMAC_GENERIC_FAILURE;
+    }
+
+    if (PAL_SUCCESS == status)
+    {
+        platStatus = mbedtls_md_hmac(md_info, key, keyLenInBytes, input, inputLenInBytes, output);
+        if (platStatus != CRYPTO_PLAT_SUCCESS)
+        {
+            if (platStatus == MBEDTLS_ERR_MD_BAD_INPUT_DATA)
+            {
+                status = PAL_ERR_MD_BAD_INPUT_DATA;
+            }
+            else
+            {
+                PAL_LOG(ERR, "Crypto hmac status %" PRId32 "", platStatus);
+                status = PAL_ERR_HMAC_GENERIC_FAILURE;
+            }
+        }
+    }
+
+    if ((NULL != outputLenInBytes) && (PAL_SUCCESS == status))
+    {
+        *outputLenInBytes = (size_t)mbedtls_md_get_size(md_info);
+    }
+
+    return status;
+}
+
+//! Check EC private key function. 
+PAL_PRIVATE palStatus_t pal_plat_ECCheckPrivateKey(palECGroup_t* ecpGroup, palECKeyHandle_t key, bool *verified)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palECKey_t* privateKey = (palECKey_t*)key;
+    mbedtls_mpi* prvMP = NULL;
+    if(NULL == (mbedtls_ecp_keypair*)privateKey->pk_ctx)
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    prvMP = &((mbedtls_ecp_keypair*)privateKey->pk_ctx)->d;
+
+    platStatus =  mbedtls_ecp_check_privkey(ecpGroup, prvMP);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_PRIVATE_KEY_VARIFICATION_FAILED;
+    }
+    else
+    {
+        *verified = true;
+    }
+    
+    return status;
+}
+
+//! Check EC public key function.
+PAL_PRIVATE palStatus_t pal_plat_ECCheckPublicKey(palECGroup_t* ecpGroup, palECKeyHandle_t key, bool *verified)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palECKey_t* publicKey = (palECKey_t*)key;
+    mbedtls_ecp_point* pubPoint = NULL;
+    if(NULL == (mbedtls_ecp_keypair*)publicKey->pk_ctx)
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+	pubPoint = &((mbedtls_ecp_keypair*)publicKey->pk_ctx)->Q;
+
+    platStatus =  mbedtls_ecp_check_pubkey(ecpGroup, pubPoint);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_PUBLIC_KEY_VARIFICATION_FAILED;
+    }
+    else
+    {
+        *verified = true;
+    }
+    
+    return status;
+}
+
+palStatus_t pal_plat_ECCheckKey(palCurveHandle_t grp, palECKeyHandle_t key, uint32_t type, bool *verified)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palECGroup_t* ecpGroup = (palECGroup_t*)grp;
+
+    *verified = false;
+
+    if ((PAL_CHECK_PRIVATE_KEY & type) != 0)
+    {
+        status = pal_plat_ECCheckPrivateKey(ecpGroup, key, verified);
+    }
+
+    if ((PAL_SUCCESS == status) && ((PAL_CHECK_PUBLIC_KEY & type) != 0))
+    {
+        status = pal_plat_ECCheckPublicKey(ecpGroup, key, verified);
+    }
+
+    return status;
+}
+
+
+palStatus_t pal_plat_ECKeyNew(palECKeyHandle_t* key)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palECKey_t* localECKey = NULL;
+
+    localECKey = (palECKey_t*)malloc(sizeof(palECKey_t));
+    if (NULL == localECKey)
+    {
+        status = PAL_ERR_NO_MEMORY;
+    }
+    else
+    {
+        mbedtls_pk_init(localECKey);
+        *key = (palECKeyHandle_t)localECKey;
+    }
+    
+    return status;
+}
+
+palStatus_t pal_plat_ECKeyFree(palECKeyHandle_t* key)
+{
+    palECKey_t* localECKey = NULL;
+
+    localECKey = (palECKey_t*)*key;
+    mbedtls_pk_free(localECKey);
+    free(localECKey);
+    *key = NULLPTR;
+    return PAL_SUCCESS;
+}
+
+//! Check if the given data is a valid PEM format or not by checking the
+//! the header and the footer of the data.
+PAL_PRIVATE bool pal_plat_isPEM(const unsigned char* key, size_t keyLen)
+{
+    bool result = false;
+    const unsigned char *s1 = NULL;
+    const unsigned char *s2 = NULL;
+
+    s1 = (unsigned char *) strstr( (const char *) key, "-----BEGIN ");
+    if (NULL != s1)
+    {
+        result = true;
+    }
+    else
+    {
+        s2 = (unsigned char *) strstr( (const char *) key, "-----END " );
+        if (NULL != s2)
+        {
+            result = true;
+        }
+    }
+
+    return result;
+}
+
+palStatus_t pal_plat_parseECPrivateKeyFromDER(const unsigned char* prvDERKey, size_t keyLen, palECKeyHandle_t key)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palECKey_t* localECKey = (palECKey_t*)key;
+
+    if(pal_plat_isPEM(prvDERKey, keyLen))
+    {
+    	return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    platStatus = mbedtls_pk_parse_key(localECKey, prvDERKey, keyLen, NULL, 0);
+    switch(platStatus)
+    {
+        case CRYPTO_PLAT_SUCCESS:
+            break;
+        case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG:
+            status = PAL_ERR_PK_UNKNOWN_PK_ALG;
+            break;
+        case MBEDTLS_ERR_PK_KEY_INVALID_VERSION:
+            status = PAL_ERR_PK_KEY_INVALID_VERSION;
+            break;
+        case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT:
+            status = PAL_ERR_PK_KEY_INVALID_FORMAT;
+            break;
+        case MBEDTLS_ERR_PK_PASSWORD_REQUIRED:
+            status = PAL_ERR_PK_PASSWORD_REQUIRED;
+            break;
+        default:
+            status = PAL_ERR_PARSING_PRIVATE_KEY;
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_parseECPublicKeyFromDER(const unsigned char* pubDERKey, size_t keyLen, palECKeyHandle_t key)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palECKey_t* localECKey = (palECKey_t*)key;
+
+    if (pal_plat_isPEM(pubDERKey, keyLen))
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    platStatus = mbedtls_pk_parse_public_key(localECKey, pubDERKey, keyLen);
+    switch(platStatus)
+    {
+        case CRYPTO_PLAT_SUCCESS:
+            break;
+        case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG:
+            status = PAL_ERR_PK_UNKNOWN_PK_ALG;
+            break;
+        case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE:
+            status = PAL_ERR_NOT_SUPPORTED_CURVE;
+            break;
+        case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT:
+            status = PAL_ERR_PK_KEY_INVALID_FORMAT;
+            break;
+        case MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH: //This is how mbedTLS returns erros for this function
+            status = PAL_ERR_PK_INVALID_PUBKEY_AND_ASN1_LEN_MISMATCH;
+            break;
+        case MBEDTLS_ERR_ECP_INVALID_KEY:
+            status = PAL_ERR_ECP_INVALID_KEY;
+            break;
+        default:
+            status = PAL_ERR_PARSING_PUBLIC_KEY;
+    }
+
+    return status;
+}
+
+//! Move data from the end of the buffer to the begining, this function is needed since mbedTLS
+//! write functions write the data at the end of the buffers.
+PAL_PRIVATE void moveDataToBufferStart(unsigned char* buffer, size_t bufferSize, size_t actualSize)
+{
+    size_t j = 0;
+    size_t i = bufferSize - actualSize;
+    if (bufferSize == actualSize)
+    {
+        return;
+    }
+
+    for( ; j < actualSize ; ++i , ++j)
+    {
+        buffer[j] = buffer[i];
+        buffer[i] = (unsigned char)0;
+    }
+}
+
+palStatus_t pal_plat_writePrivateKeyToDer(palECKeyHandle_t key, unsigned char* derBuffer, size_t bufferSize, size_t* actualSize)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palECKey_t* localECKey = (palECKey_t*)key;
+
+    platStatus = mbedtls_pk_write_key_der(localECKey, derBuffer, bufferSize);
+    if (CRYPTO_PLAT_SUCCESS < platStatus)
+    {
+        *actualSize = platStatus;
+        moveDataToBufferStart(derBuffer, bufferSize, *actualSize);
+    }
+    else
+    {
+        switch (platStatus) {
+            case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL:
+                status = PAL_ERR_BUFFER_TOO_SMALL;
+                break;
+            default:
+                status = PAL_ERR_FAILED_TO_WRITE_PRIVATE_KEY;
+        }
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_writePublicKeyToDer(palECKeyHandle_t key, unsigned char* derBuffer, size_t bufferSize, size_t* actualSize)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palECKey_t* localECKey = (palECKey_t*)key;
+
+    platStatus = mbedtls_pk_write_pubkey_der(localECKey, derBuffer, bufferSize);
+    if (CRYPTO_PLAT_SUCCESS < platStatus)
+    {
+        *actualSize = platStatus;
+        moveDataToBufferStart(derBuffer, bufferSize, *actualSize);
+    }
+    else
+    {
+        switch (platStatus) {
+            case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL:
+                status = PAL_ERR_BUFFER_TOO_SMALL;
+                break;
+            default:
+                status = PAL_ERR_FAILED_TO_WRITE_PUBLIC_KEY;
+        }
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_ECKeyGenerateKey(palGroupIndex_t grpID, palECKeyHandle_t key)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    mbedtls_ecp_group_id platCurve = MBEDTLS_ECP_DP_NONE;
+    palECKey_t* localECKey = (palECKey_t*)key;
+    mbedtls_ecp_keypair* keyPair = NULL;
+
+    switch(grpID)
+    {
+        case PAL_ECP_DP_SECP256R1:
+            platCurve = MBEDTLS_ECP_DP_SECP256R1;
+            break;
+        default: 
+            status = PAL_ERR_NOT_SUPPORTED_CURVE;
+            goto finish;
+    }
+
+    platStatus = mbedtls_pk_setup(localECKey, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
+    if (CRYPTO_PLAT_SUCCESS != platStatus) {
+        status = PAL_ERR_KEYPAIR_GEN_FAIL;
+        goto finish;
+    }
+
+    keyPair = (mbedtls_ecp_keypair*)localECKey->pk_ctx;
+
+    platStatus = mbedtls_ecp_gen_key(platCurve, keyPair, pal_plat_entropySource, NULL);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_KEYPAIR_GEN_FAIL;
+        mbedtls_pk_free(localECKey);
+    }
+
+finish:
+    return status;
+}
+
+palStatus_t pal_plat_ECKeyGetCurve(palECKeyHandle_t key, palGroupIndex_t* grpID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palECKey_t* localECKey = (palECKey_t*)key;
+    mbedtls_ecp_keypair* keyPair = NULL;
+
+    if (NULL == (mbedtls_ecp_keypair*)localECKey->pk_ctx)
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    keyPair = (mbedtls_ecp_keypair*)localECKey->pk_ctx;
+
+    switch(keyPair->grp.id)
+    {
+        case MBEDTLS_ECP_DP_SECP256R1:
+            *grpID = PAL_ECP_DP_SECP256R1;
+            break;
+        default:
+            *grpID = PAL_ECP_DP_NONE;
+            status = PAL_ERR_NOT_SUPPORTED_CURVE;
+    }
+    return status;
+}
+
+palStatus_t pal_plat_ECGroupFree(palCurveHandle_t* grp)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palECGroup_t* localGroup = NULL;
+
+    localGroup = (palECGroup_t*)*grp;
+    mbedtls_ecp_group_free(localGroup);
+    free(localGroup);
+    *grp = NULLPTR;
+    return status;
+}
+
+palStatus_t pal_plat_ECGroupInitAndLoad(palCurveHandle_t* grp, palGroupIndex_t index)
+{
+    palStatus_t status = PAL_SUCCESS;
+    mbedtls_ecp_group_id platCurve = MBEDTLS_ECP_DP_NONE;
+    palECGroup_t* localGroup = NULL;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+
+    localGroup = (palECGroup_t*)malloc(sizeof(palECGroup_t));
+    if (NULL == localGroup)
+    {
+        status = PAL_ERR_NO_MEMORY;
+        goto finish;
+    }
+
+    mbedtls_ecp_group_init(localGroup);
+    switch(index)
+    {
+        case PAL_ECP_DP_SECP256R1:
+            platCurve = MBEDTLS_ECP_DP_SECP256R1;
+            break;
+        default: 
+            status = PAL_ERR_NOT_SUPPORTED_CURVE;
+            goto finish;
+    }
+
+    platStatus = mbedtls_ecp_group_load(localGroup ,platCurve);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_GROUP_LOAD_FAILED;
+    }
+    else
+    {
+        *grp = (palCurveHandle_t)localGroup;
+    }
+    
+finish:
+    if (PAL_SUCCESS != status && localGroup != NULL)
+    {
+        free(localGroup);
+    }
+
+    return status;
+}
+
+
+palStatus_t pal_plat_ECDHComputeKey(const palCurveHandle_t grp, const palECKeyHandle_t peerPublicKey, const palECKeyHandle_t privateKey, palECKeyHandle_t outKey)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palECGroup_t* ecpGroup = (palECGroup_t*)grp;
+    mbedtls_ecp_keypair* pubKeyPair = NULL;
+    mbedtls_ecp_keypair* prvKeyPair = NULL;
+    mbedtls_ecp_keypair* outKeyPair = NULL;
+    mbedtls_ctr_drbg_context ctrDrbgCtx;
+
+    mbedtls_ctr_drbg_init(&ctrDrbgCtx);
+
+    pubKeyPair = (mbedtls_ecp_keypair*)((palECKey_t*)peerPublicKey)->pk_ctx;
+    prvKeyPair = (mbedtls_ecp_keypair*)((palECKey_t*)privateKey)->pk_ctx;
+    outKeyPair = (mbedtls_ecp_keypair*)((palECKey_t*)outKey)->pk_ctx;
+
+    if (NULL != pubKeyPair && NULL != prvKeyPair && NULL != outKeyPair)
+    {
+        platStatus = mbedtls_ecdh_compute_shared(ecpGroup, &outKeyPair->d, &pubKeyPair->Q, &prvKeyPair->d, mbedtls_ctr_drbg_random, (void*)&ctrDrbgCtx);
+        if (CRYPTO_PLAT_SUCCESS != platStatus)
+        {
+            status = PAL_ERR_FAILED_TO_COMPUTE_SHRED_KEY;
+        }
+    }
+    else 
+    {
+        status = PAL_ERR_INVALID_ARGUMENT;
+    }
+
+
+    mbedtls_ctr_drbg_free(&ctrDrbgCtx);
+
+    return status;
+}
+
+
+palStatus_t pal_plat_ECDSASign(palCurveHandle_t grp, palMDType_t mdType, palECKeyHandle_t prvKey, unsigned char* dgst, uint32_t dgstLen, unsigned char* sig, size_t* sigLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palECKey_t* localECKey = (palECKey_t*)prvKey;
+    mbedtls_ecp_keypair* keyPair = NULL;
+    mbedtls_ecdsa_context localECDSA;
+    palECGroup_t* localGroup = (palECGroup_t*)grp;
+    mbedtls_md_type_t mdAlg = MBEDTLS_MD_NONE;
+
+    keyPair = (mbedtls_ecp_keypair*)localECKey->pk_ctx;
+
+    mbedtls_ecdsa_init(&localECDSA);
+    platStatus = mbedtls_ecdsa_from_keypair(&localECDSA, keyPair);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_FAILED_TO_COPY_KEYPAIR;
+        goto finish;
+    }
+
+    platStatus = mbedtls_ecp_group_copy(&localECDSA.grp, localGroup);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_FAILED_TO_COPY_GROUP;
+        goto finish;
+    }
+
+    switch (mdType)
+    {
+        case PAL_SHA256:
+            mdAlg = MBEDTLS_MD_SHA256;
+            break;
+        default:
+            status = PAL_ERR_INVALID_MD_TYPE;
+            goto finish;
+    }
+
+    platStatus = mbedtls_ecdsa_write_signature(&localECDSA, mdAlg, dgst, dgstLen, sig, sigLen, NULL, NULL);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_FAILED_TO_WRITE_SIGNATURE;
+    }
+
+finish:
+    mbedtls_ecdsa_free(&localECDSA);
+    return status;
+}
+
+palStatus_t pal_plat_ECDSAVerify(palECKeyHandle_t pubKey, unsigned char* dgst, uint32_t dgstLen, unsigned char* sig, size_t sigLen, bool* verified)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palECKey_t* localECKey = (palECKey_t*)pubKey;
+    mbedtls_ecp_keypair* keyPair = NULL;
+    mbedtls_ecdsa_context localECDSA;
+
+    keyPair = (mbedtls_ecp_keypair*)localECKey->pk_ctx;
+
+    mbedtls_ecdsa_init(&localECDSA);
+    platStatus = mbedtls_ecdsa_from_keypair(&localECDSA, keyPair);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_FAILED_TO_COPY_KEYPAIR;
+        goto finish;
+    }
+
+    platStatus = mbedtls_ecdsa_read_signature(&localECDSA, dgst, dgstLen, sig, sigLen);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_FAILED_TO_VERIFY_SIGNATURE;
+        *verified = false;
+    }
+    else
+    {
+        *verified = true;
+    }
+finish:
+    mbedtls_ecdsa_free(&localECDSA);
+    return status;
+}
+#if (PAL_ENABLE_X509 == 1)
+palStatus_t pal_plat_x509CSRInit(palx509CSRHandle_t *x509CSR)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palx509CSR_t *localCSR = NULL;
+
+    localCSR = (palx509CSR_t*)malloc(sizeof(palx509CSR_t));
+    if (NULL == localCSR)
+    {
+        status = PAL_ERR_NO_MEMORY;
+    }
+    else
+    {
+        mbedtls_x509write_csr_init(localCSR);
+        *x509CSR = (palx509CSRHandle_t)localCSR;
+    }
+    return status;
+}
+
+palStatus_t pal_plat_x509CSRSetSubject(palx509CSRHandle_t x509CSR, const char* subjectName)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palx509CSR_t *localCSR = (palx509CSR_t*)x509CSR;
+
+    platStatus = mbedtls_x509write_csr_set_subject_name(localCSR, subjectName);
+    switch (platStatus)
+    {
+        case CRYPTO_PLAT_SUCCESS:
+            status = PAL_SUCCESS;
+            break;
+        case MBEDTLS_ERR_X509_UNKNOWN_OID:
+            status = PAL_ERR_X509_UNKNOWN_OID;
+            break;
+        case MBEDTLS_ERR_X509_INVALID_NAME:
+            status = PAL_ERR_X509_INVALID_NAME;
+            break;
+        default:
+            {
+                PAL_LOG(ERR, "Crypto x509 CSR set subject status %" PRId32 ".", platStatus);
+                status = PAL_ERR_GENERIC_FAILURE;
+            }
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_x509CSRSetKey(palx509CSRHandle_t x509CSR, palECKeyHandle_t pubKey, palECKeyHandle_t prvKey)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palx509CSR_t *localCSR = (palx509CSR_t*)x509CSR;
+    palECKey_t* localPubKey = (palECKey_t*)pubKey;
+    palECKey_t* localPrvKey = (palECKey_t*)prvKey;
+
+    if (NULL != localPrvKey)
+    {
+        int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+        mbedtls_ecp_keypair* pubKeyPair = NULL;
+        mbedtls_ecp_keypair* prvKeyPair = NULL;
+
+        pubKeyPair = (mbedtls_ecp_keypair*)localPubKey->pk_ctx;
+        prvKeyPair = (mbedtls_ecp_keypair*)localPrvKey->pk_ctx;
+
+        if (NULL != pubKeyPair && NULL != prvKeyPair)
+        {
+            platStatus = mbedtls_mpi_copy(&(pubKeyPair->d), &(prvKeyPair->d));
+            if (CRYPTO_PLAT_SUCCESS != platStatus)
+            {
+                status = PAL_ERR_FAILED_TO_COPY_KEYPAIR;
+            }
+        }
+        else
+        {
+            status = PAL_ERR_INVALID_ARGUMENT;
+        }
+    }
+    
+    if (PAL_SUCCESS == status)
+    {
+        mbedtls_x509write_csr_set_key(localCSR, localPubKey);
+    }
+    
+    return status;
+}
+    
+palStatus_t pal_plat_x509CSRSetMD(palx509CSRHandle_t x509CSR, palMDType_t mdType)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palx509CSR_t *localCSR = (palx509CSR_t*)x509CSR;
+    mbedtls_md_type_t mdAlg = MBEDTLS_MD_NONE;
+
+    switch (mdType)
+    {
+        case PAL_SHA256:
+            mdAlg = MBEDTLS_MD_SHA256;
+            break;
+        default:
+            status = PAL_ERR_INVALID_MD_TYPE;
+            goto finish;
+    }
+
+    mbedtls_x509write_csr_set_md_alg(localCSR, mdAlg);
+
+finish:
+    return status;
+}
+
+palStatus_t pal_plat_x509CSRSetKeyUsage(palx509CSRHandle_t x509CSR, uint32_t keyUsage)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palx509CSR_t *localCSR = (palx509CSR_t*)x509CSR;
+    uint8_t localKeyUsage = 0;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+
+    if (PAL_X509_KU_DIGITAL_SIGNATURE & keyUsage)
+    {
+        localKeyUsage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
+    }
+    if (PAL_X509_KU_KEY_CERT_SIGN & keyUsage)
+    {
+        localKeyUsage |= MBEDTLS_X509_KU_KEY_CERT_SIGN;
+    }
+    if (PAL_X509_KU_NON_REPUDIATION & keyUsage)
+    {
+        localKeyUsage |= MBEDTLS_X509_KU_NON_REPUDIATION;
+    }
+
+    if (0 == localKeyUsage)
+    {
+        status = PAL_ERR_INVALID_KEY_USAGE;
+    }
+    else
+    {
+        platStatus = mbedtls_x509write_csr_set_key_usage(localCSR, localKeyUsage);
+        if (CRYPTO_PLAT_SUCCESS != platStatus)
+        {
+            status = PAL_ERR_FAILED_TO_SET_KEY_USAGE;
+        }
+    }
+    return status;
+}
+
+palStatus_t pal_plat_x509CSRSetExtendedKeyUsage(palx509CSRHandle_t x509CSR, uint32_t extKeyUsage)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palx509CSR_t *localCSR = (palx509CSR_t*)x509CSR;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+
+    // Max needed buffer if all option turned on
+    // In details: sequence tag + sequence len + ((oid tag + oid len + oid) * (7 options))
+    uint8_t value_buf[2 + (2 + MBEDTLS_OID_SIZE(MBEDTLS_OID_OCSP_SIGNING)) * 7];
+
+    uint8_t *start = value_buf;
+    uint8_t *end = value_buf + sizeof(value_buf);
+    uint32_t all_bits = PAL_X509_EXT_KU_ANY | PAL_X509_EXT_KU_SERVER_AUTH | PAL_X509_EXT_KU_CLIENT_AUTH |
+        PAL_X509_EXT_KU_CODE_SIGNING | PAL_X509_EXT_KU_EMAIL_PROTECTION | PAL_X509_EXT_KU_TIME_STAMPING |
+        PAL_X509_EXT_KU_OCSP_SIGNING;
+
+    // Check if all options valid
+    if ((extKeyUsage == 0) || (extKeyUsage & (~all_bits))) {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    /* As mbedTLS, build the DER in value_buf from end to start */
+
+    if (platStatus >= CRYPTO_PLAT_SUCCESS && PAL_X509_EXT_KU_OCSP_SIGNING & extKeyUsage) {
+        platStatus = mbedtls_asn1_write_oid(&end, start, MBEDTLS_OID_OCSP_SIGNING, MBEDTLS_OID_SIZE(MBEDTLS_OID_OCSP_SIGNING));
+    }
+    if (platStatus >= CRYPTO_PLAT_SUCCESS && PAL_X509_EXT_KU_TIME_STAMPING & extKeyUsage) {
+        platStatus = mbedtls_asn1_write_oid(&end, start, MBEDTLS_OID_TIME_STAMPING, MBEDTLS_OID_SIZE(MBEDTLS_OID_TIME_STAMPING));
+    }
+    if (platStatus >= CRYPTO_PLAT_SUCCESS && PAL_X509_EXT_KU_EMAIL_PROTECTION & extKeyUsage) {
+        platStatus = mbedtls_asn1_write_oid(&end, start, MBEDTLS_OID_EMAIL_PROTECTION, MBEDTLS_OID_SIZE(MBEDTLS_OID_EMAIL_PROTECTION));
+    }
+    if (platStatus >= CRYPTO_PLAT_SUCCESS && PAL_X509_EXT_KU_CODE_SIGNING & extKeyUsage) {
+        platStatus = mbedtls_asn1_write_oid(&end, start, MBEDTLS_OID_CODE_SIGNING, MBEDTLS_OID_SIZE(MBEDTLS_OID_CODE_SIGNING));
+    }
+    if (platStatus >= CRYPTO_PLAT_SUCCESS && PAL_X509_EXT_KU_CLIENT_AUTH & extKeyUsage){
+        platStatus = mbedtls_asn1_write_oid(&end, start, MBEDTLS_OID_CLIENT_AUTH, MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH));
+    }
+    if (platStatus >= CRYPTO_PLAT_SUCCESS && PAL_X509_EXT_KU_SERVER_AUTH & extKeyUsage){
+        platStatus = mbedtls_asn1_write_oid(&end, start, MBEDTLS_OID_SERVER_AUTH, MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH));
+    }
+    if (platStatus >= CRYPTO_PLAT_SUCCESS && PAL_X509_EXT_KU_ANY & extKeyUsage){
+        platStatus = mbedtls_asn1_write_oid(&end, start, MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE));
+    }
+
+    if (platStatus < CRYPTO_PLAT_SUCCESS) {
+        goto finish;
+    }
+
+    // Calc written len (from end to the end of value_buf) and write it to value_buf
+    platStatus = mbedtls_asn1_write_len(&end, start, (value_buf + sizeof(value_buf)) - end);
+    if (platStatus < CRYPTO_PLAT_SUCCESS) {
+        goto finish;
+    }
+    // Write sequence tag
+    platStatus = mbedtls_asn1_write_tag(&end, start, (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
+    if (platStatus < CRYPTO_PLAT_SUCCESS) {
+        goto finish;
+    }
+
+    // Set start and end pointer to the used part in value_buf and add the extension to the CSR 
+    start = end;
+    end = value_buf + sizeof(value_buf);
+    platStatus = mbedtls_x509write_csr_set_extension(localCSR, MBEDTLS_OID_EXTENDED_KEY_USAGE, MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE),
+                                                     start, (end - start));
+    if (CRYPTO_PLAT_SUCCESS != platStatus) {
+        goto finish;
+    }
+
+finish:
+    if (CRYPTO_PLAT_SUCCESS != platStatus) {
+        status = PAL_ERR_FAILED_TO_SET_EXT_KEY_USAGE;
+    }
+    return status;
+}
+
+palStatus_t pal_plat_x509CSRSetExtension(palx509CSRHandle_t x509CSR,const char* oid, size_t oidLen, const unsigned char* value, size_t valueLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palx509CSR_t *localCSR = (palx509CSR_t*)x509CSR;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+
+    platStatus = mbedtls_x509write_csr_set_extension(localCSR, oid, oidLen, value, valueLen);
+    if (CRYPTO_PLAT_SUCCESS != platStatus)
+    {
+        status = PAL_ERR_SET_EXTENSION_FAILED;
+    }
+    return status;
+}
+
+palStatus_t pal_plat_x509CSRWriteDER(palx509CSRHandle_t x509CSR, unsigned char* derBuf, size_t derBufLen, size_t* actualDerLen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = CRYPTO_PLAT_SUCCESS;
+    palx509CSR_t *localCSR = (palx509CSR_t*)x509CSR;
+
+    platStatus = mbedtls_x509write_csr_der(localCSR, derBuf, derBufLen, pal_plat_entropySource, NULL);
+    if (CRYPTO_PLAT_SUCCESS < platStatus)
+    {
+        *actualDerLen = platStatus;
+        moveDataToBufferStart(derBuf, derBufLen, *actualDerLen);
+    } else {
+        switch (platStatus) {
+            case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL:
+                status = PAL_ERR_BUFFER_TOO_SMALL;
+                break;
+            default:
+                status = PAL_ERR_CSR_WRITE_DER_FAILED;
+        }
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_x509CSRFree(palx509CSRHandle_t *x509CSR)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palx509CSR_t* localCSR = (palx509CSR_t*)*x509CSR;
+
+    mbedtls_x509write_csr_free(localCSR);
+    free(localCSR);
+    *x509CSR = NULLPTR;
+    return status;
+}
+
+palStatus_t pal_plat_x509CertGetHTBS(palX509Handle_t x509Cert, palMDType_t hash_type, unsigned char* output, size_t outLenBytes, size_t* actualOutLenBytes)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palX509Ctx_t *crt_ctx = (palX509Ctx_t*)x509Cert;
+
+    switch (hash_type) {
+        case PAL_SHA256:
+            if (outLenBytes < PAL_SHA256_SIZE) {
+                status = PAL_ERR_BUFFER_TOO_SMALL;
+                break;
+            }
+            status = pal_plat_sha256(crt_ctx->crt.tbs.p, crt_ctx->crt.tbs.len, output);
+            *actualOutLenBytes = PAL_SHA256_SIZE;
+            break;
+        default:
+            status = PAL_ERR_INVALID_MD_TYPE;
+            break;
+    }
+    
+    return status;
+}
+
+#endif
+PAL_PRIVATE int pal_plat_entropySourceDRBG( void *data, unsigned char *output, size_t len)
+{
+    (void)data;
+    return CRYPTO_PLAT_SUCCESS;
+}
+
+PAL_PRIVATE int pal_plat_entropySource( void *data, unsigned char *output, size_t len)
+{
+	palStatus_t status = PAL_SUCCESS;
+    (void)data;
+    
+    status = pal_osRandomBuffer((uint8_t*) output, len);
+    if (PAL_SUCCESS == status)
+    {
+        return CRYPTO_PLAT_SUCCESS;
+    }
+    else
+    {
+        return CRYPTO_PLAT_GENERIC_ERROR;
+    }
+}
+
+#ifdef __arm__ // we are compiling using the ARM compiler
+/* This function is provided for ARM-CC compiler, since mbedTLS uses it and it returns NULL
+ * in ARM-CC, we need to provide replacement function to keep correct functionality
+ * mbedTLS will change the internal implementation which uses gmtime()
+ */ 
+struct tm *gmtime(const time_t *timep)
+{
+    return localtime(timep);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/Lib_Specific/mbedTLS/TLS/pal_plat_TLS.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1277 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "pal.h"
+#include "pal_plat_TLS.h"
+#include "mbedtls/ssl.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/ssl_internal.h"
+#include "stdlib.h"
+#include "string.h"
+#include "sotp.h"
+
+
+#define SSL_LIB_SUCCESS 0
+
+#if PAL_USE_SECURE_TIME
+#include "platform_time.h"
+PAL_PRIVATE mbedtls_time_t g_timeFromHS = 0;
+PAL_PRIVATE palMutexID_t g_palTLSTimeMutex = NULLPTR;
+#ifdef MBEDTLS_PLATFORM_TIME_ALT
+PAL_PRIVATE mbedtls_time_t pal_mbedtlsTimeCB(mbedtls_time_t* timer);
+#endif
+#endif //PAL_USE_SECURE_TIME
+
+#if defined(MBEDTLS_DEBUG_C)
+//! Add forward declaration for the function from mbedTLS
+void mbedtls_debug_set_threshold( int threshold );
+#endif
+
+
+typedef mbedtls_ssl_context platTlsContext;
+typedef mbedtls_ssl_config platTlsConfiguraionContext;
+
+PAL_PRIVATE mbedtls_entropy_context *g_entropy = NULL;
+PAL_PRIVATE bool g_entropyInitiated = false;
+
+typedef struct palTimingDelayContext
+{
+	uint64_t						start_ticks;
+	uint32_t						int_ms;
+	uint32_t						fin_ms;
+} palTimingDelayContext_t;
+
+
+//! the full structures will be defined later in the implemetation.
+typedef struct palTLS {
+    platTlsContext tlsCtx;
+    bool tlsInit;
+    char* psk; //NULL terminated
+    char* identity; //NULL terminated
+    bool wantReadOrWrite;
+}palTLS_t;
+
+
+//! the full structures will be defined later in the implemetation.
+typedef struct palTLSConf {
+    platTlsConfiguraionContext*  confCtx;
+    palTLSSocketHandle_t palIOCtx; // which will be used as bio context for mbedTLS
+    palTLS_t* tlsContext; // to help us to get the index of the containing palTLS_t in the array. will be updated in the init
+                          // maybe we need to make this an array, since index can be shared for more than one TLS context
+    mbedtls_ctr_drbg_context ctrDrbg;
+    palTimingDelayContext_t timerCtx;
+#if (PAL_ENABLE_X509 == 1)
+    mbedtls_x509_crt owncert;
+    mbedtls_x509_crt cacert; 
+#endif 
+	mbedtls_pk_context pkey;	
+    bool hasKeys;
+    bool hasChain;
+    int cipherSuites[PAL_MAX_ALLOWED_CIPHER_SUITES + 1];  // The +1 is for the Zero Termination required by mbedTLS
+}palTLSConf_t;
+
+
+
+
+
+
+PAL_PRIVATE palStatus_t translateTLSErrToPALError(int32_t error) 
+{
+	palStatus_t status;
+	switch(error) 
+	{
+		case SSL_LIB_SUCCESS: 
+			status = PAL_ERR_END_OF_FILE;
+			break;
+		case MBEDTLS_ERR_SSL_WANT_READ:
+			status = PAL_ERR_TLS_WANT_READ;
+			break;
+		case MBEDTLS_ERR_SSL_WANT_WRITE:
+			status = PAL_ERR_TLS_WANT_WRITE;
+			break;
+		case MBEDTLS_ERR_SSL_TIMEOUT:
+			status = PAL_ERR_TIMEOUT_EXPIRED;
+			break;
+		case MBEDTLS_ERR_SSL_BAD_INPUT_DATA:
+			status = PAL_ERR_TLS_BAD_INPUT_DATA;
+			break;
+		case MBEDTLS_ERR_SSL_CLIENT_RECONNECT:
+			status = PAL_ERR_TLS_CLIENT_RECONNECT;
+			break;
+		case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
+			status = PAL_ERR_TLS_PEER_CLOSE_NOTIFY;
+			break;
+#if (PAL_ENABLE_X509 == 1)
+		case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
+			status = PAL_ERR_X509_CERT_VERIFY_FAILED;
+			break;
+#endif
+		default:
+			{
+				status = PAL_ERR_GENERIC_FAILURE;
+			}
+	};
+	return status;
+
+}
+
+
+PAL_PRIVATE palStatus_t translateTLSHandShakeErrToPALError(palTLS_t* tlsCtx, int32_t error) 
+{
+	palStatus_t status;
+	switch(error)
+	{
+		case SSL_LIB_SUCCESS:
+			status = PAL_SUCCESS;
+			tlsCtx->wantReadOrWrite = false;
+			break;
+		case MBEDTLS_ERR_SSL_WANT_READ:
+			status = PAL_ERR_TLS_WANT_READ;
+			tlsCtx->wantReadOrWrite = true;
+			break;
+		case MBEDTLS_ERR_SSL_WANT_WRITE:
+			status = PAL_ERR_TLS_WANT_WRITE;
+			tlsCtx->wantReadOrWrite = true;
+			break;
+		case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
+			status = PAL_ERR_TLS_HELLO_VERIFY_REQUIRED;
+			break;
+		case MBEDTLS_ERR_SSL_TIMEOUT:
+			status = PAL_ERR_TIMEOUT_EXPIRED;
+			break;
+		case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
+			status = PAL_ERR_TLS_PEER_CLOSE_NOTIFY;
+			break;
+#if (PAL_ENABLE_X509 == 1)
+		case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
+			status = PAL_ERR_X509_CERT_VERIFY_FAILED;
+			break;
+#endif
+		default:
+			{
+				PAL_LOG(ERR, "SSL handshake return code 0x%" PRIx32 ".", -error);
+				status = PAL_ERR_GENERIC_FAILURE;
+			}
+	};
+	return status;
+}
+
+//! Forward declaration
+PAL_PRIVATE int palBIORecv_timeout(palTLSSocketHandle_t socket, unsigned char *buf, size_t len, uint32_t timeout);
+PAL_PRIVATE int palBIORecv(palTLSSocketHandle_t socket, unsigned char *buf, size_t len);
+PAL_PRIVATE int palBIOSend(palTLSSocketHandle_t socket, const unsigned char *buf, size_t len);
+PAL_PRIVATE void palDebug(void *ctx, int debugLevel, const char *fileName, int line, const char *message);
+int pal_plat_entropySourceTLS( void *data, unsigned char *output, size_t len, size_t *olen );
+PAL_PRIVATE int palTimingGetDelay( void *data );
+PAL_PRIVATE void palTimingSetDelay( void *data, uint32_t intMs, uint32_t finMs );
+
+palStatus_t pal_plat_initTLSLibrary(void)
+{
+	palStatus_t status = PAL_SUCCESS;
+
+	g_entropy = (mbedtls_entropy_context*)malloc(sizeof(mbedtls_entropy_context));
+	if (NULL == g_entropy)
+	{
+		status = PAL_ERR_NO_MEMORY;
+		goto finish;
+	}
+	else
+	{
+		mbedtls_entropy_init(g_entropy);
+		g_entropyInitiated = false;
+	}
+
+#if PAL_USE_SECURE_TIME
+	#ifdef MBEDTLS_PLATFORM_TIME_ALT
+		// this scope is here to keep warnings away from gotos which skip over variable initialization
+		{
+			int32_t platStatus = SSL_LIB_SUCCESS;
+			platStatus = mbedtls_platform_set_time(pal_mbedtlsTimeCB);
+			if (SSL_LIB_SUCCESS != platStatus)
+			{
+				status = PAL_ERR_FAILED_SET_TIME_CB;
+				goto finish;
+			}
+		}
+	#endif //MBEDTLS_PLATFORM_TIME_ALT
+		status = pal_osMutexCreate(&g_palTLSTimeMutex);
+		if(PAL_SUCCESS != status)
+		{
+			PAL_LOG(ERR, "Failed to Create TLS time Mutex error: %" PRId32 ".", status);
+		}
+#endif //PAL_USE_SECURE_TIME
+finish:
+	return status;
+}
+
+
+palStatus_t pal_plat_cleanupTLS(void)
+{
+	palStatus_t status = PAL_SUCCESS;
+	if(g_entropy != NULL)
+	{
+		mbedtls_entropy_free(g_entropy);
+	}
+	g_entropyInitiated = false;
+	free(g_entropy);
+	g_entropy = NULL;
+
+#if PAL_USE_SECURE_TIME
+	//! Try to catch the Mutex in order to prevent situation of deleteing under use mutex
+	status = pal_osMutexWait(g_palTLSTimeMutex, PAL_RTOS_WAIT_FOREVER);
+	if (PAL_SUCCESS != status)
+	{
+		PAL_LOG(ERR, "Failed to get TLS time Mutex error: %" PRId32 ".", status);
+	}
+
+	status = pal_osMutexRelease(g_palTLSTimeMutex);
+	if (PAL_SUCCESS != status)
+	{
+		PAL_LOG(ERR, "Failed to release TLS time Mutex error: %" PRId32 ".", status);
+	}
+
+	status = pal_osMutexDelete(&g_palTLSTimeMutex);
+	if(PAL_SUCCESS != status)
+	{
+		PAL_LOG(ERR, "Failed to Delete TLS time Mutex");
+	}
+#endif //PAL_USE_SECURE_TIME
+	return status;
+}
+
+
+palStatus_t pal_plat_addEntropySource(palEntropySource_f entropyCallback)
+{
+	palStatus_t status = PAL_SUCCESS;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+
+	if (NULL == entropyCallback)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	if (!g_entropyInitiated)
+	{
+		platStatus = mbedtls_entropy_add_source(g_entropy, entropyCallback, NULL, PAL_INITIAL_RANDOM_SIZE, MBEDTLS_ENTROPY_SOURCE_STRONG );
+		if (SSL_LIB_SUCCESS != platStatus)
+		{
+			status = PAL_ERR_TLS_CONFIG_INIT;
+		}
+		else
+		{
+			g_entropyInitiated = true;
+		}
+		
+	}
+
+	return status;
+}
+
+
+palStatus_t pal_plat_initTLSConf(palTLSConfHandle_t* palConfCtx, palTLSTransportMode_t transportVersion, palDTLSSide_t methodType)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConf_t* localConfigCtx = NULL;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+	int32_t endpoint = 0;
+	int32_t transport = 0;
+
+	if (NULLPTR == palConfCtx)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	localConfigCtx = (palTLSConf_t*)malloc(sizeof(palTLSConf_t));
+	if (NULL == localConfigCtx)
+	{
+		status = PAL_ERR_NO_MEMORY;
+		goto finish;
+	}
+
+	localConfigCtx->confCtx = (platTlsConfiguraionContext*)malloc(sizeof(platTlsConfiguraionContext));
+	if (NULL == localConfigCtx->confCtx)
+	{
+		status = PAL_ERR_NO_MEMORY;
+		goto finish;
+	}
+	localConfigCtx->tlsContext = NULL;
+	localConfigCtx->hasKeys = false;
+	localConfigCtx->hasChain = false;
+	memset(localConfigCtx->cipherSuites, 0,(sizeof(int)* (PAL_MAX_ALLOWED_CIPHER_SUITES+1)) );	
+	mbedtls_ssl_config_init(localConfigCtx->confCtx);
+
+#if (PAL_ENABLE_X509 == 1)
+	mbedtls_x509_crt_init(&localConfigCtx->owncert);
+	mbedtls_x509_crt_init(&localConfigCtx->cacert);
+#endif
+
+	if (PAL_TLS_IS_CLIENT == methodType)
+	{
+		endpoint = MBEDTLS_SSL_IS_CLIENT;
+	}
+	else
+	{
+		endpoint = MBEDTLS_SSL_IS_SERVER;
+	}
+
+	if (PAL_TLS_MODE == transportVersion)
+	{
+		transport = MBEDTLS_SSL_TRANSPORT_STREAM;
+	}
+	else
+	{
+		transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM;
+	}
+	platStatus = mbedtls_ssl_config_defaults(localConfigCtx->confCtx, endpoint, transport, MBEDTLS_SSL_PRESET_DEFAULT);
+	if (SSL_LIB_SUCCESS != platStatus)
+	{
+		PAL_LOG(ERR, "TLS Init conf status %" PRId32 ".", platStatus);
+		status = PAL_ERR_TLS_CONFIG_INIT;
+		goto finish;
+	}								
+
+	mbedtls_ctr_drbg_init(&localConfigCtx->ctrDrbg);
+	status = pal_plat_addEntropySource(pal_plat_entropySourceTLS);
+	if (PAL_SUCCESS != status)
+	{
+		goto finish;
+	}								
+
+	platStatus = mbedtls_ctr_drbg_seed(&localConfigCtx->ctrDrbg, mbedtls_entropy_func, g_entropy, NULL, 0); //Custom data can be defined in 
+																						  //pal_TLS.h header and to be defined by 
+																						  //Service code. But we need to check if other platform support this 
+																						  //input!
+	if (SSL_LIB_SUCCESS != platStatus)
+	{
+		status = PAL_ERR_TLS_CONFIG_INIT;
+		goto finish;
+	}
+	
+	mbedtls_ssl_conf_rng(localConfigCtx->confCtx, mbedtls_ctr_drbg_random, &localConfigCtx->ctrDrbg);
+	*palConfCtx = (uintptr_t)localConfigCtx;
+	
+finish:	
+	if (PAL_SUCCESS != status && NULL != localConfigCtx)
+	{
+		if (NULL != localConfigCtx->confCtx)
+		{
+			free(localConfigCtx->confCtx);			
+		}
+		free(localConfigCtx);
+		*palConfCtx = NULLPTR;
+	}
+	return status;
+}
+
+
+palStatus_t pal_plat_tlsConfigurationFree(palTLSConfHandle_t* palTLSConf)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConf_t* localConfigCtx = NULL;
+
+	if (NULLPTR == palTLSConf || NULLPTR == *palTLSConf)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	localConfigCtx = (palTLSConf_t*)*palTLSConf;
+
+	if (true == localConfigCtx->hasKeys)
+	{
+		mbedtls_pk_free(&localConfigCtx->pkey);
+#if (PAL_ENABLE_X509 == 1)
+		mbedtls_x509_crt_free(&localConfigCtx->owncert);
+	}
+
+	if (true == localConfigCtx->hasChain)
+	{
+		mbedtls_x509_crt_free(&localConfigCtx->cacert);
+#endif
+	}
+
+	mbedtls_ssl_config_free(localConfigCtx->confCtx);
+	mbedtls_ctr_drbg_free(&localConfigCtx->ctrDrbg);
+
+	free(localConfigCtx->confCtx);
+
+	memset(localConfigCtx, 0, sizeof(palTLSConf_t));
+	free(localConfigCtx);
+	*palTLSConf = NULLPTR;
+	return status;
+}
+
+
+palStatus_t pal_plat_initTLS(palTLSConfHandle_t palTLSConf, palTLSHandle_t* palTLSHandle)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
+    
+    palTLS_t* localTLSHandle = (palTLS_t*)malloc( sizeof(palTLS_t));
+    if (NULL == localTLSHandle)
+    {
+        status = PAL_ERR_TLS_RESOURCE;
+        goto finish;
+    }
+
+    memset(localTLSHandle, 0 , sizeof(palTLS_t));
+    mbedtls_ssl_init(&localTLSHandle->tlsCtx);
+    localConfigCtx->tlsContext = localTLSHandle;
+    localTLSHandle->tlsInit = true;
+    mbedtls_ssl_set_timer_cb(&localTLSHandle->tlsCtx, &localConfigCtx->timerCtx, palTimingSetDelay, palTimingGetDelay);
+    *palTLSHandle = (palTLSHandle_t)localTLSHandle;
+
+finish:
+    return status;
+}
+
+
+palStatus_t pal_plat_freeTLS(palTLSHandle_t* palTLSHandle)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLS_t* localTLSCtx = NULL;
+
+	localTLSCtx = (palTLS_t*)*palTLSHandle;
+	if (false == localTLSCtx->tlsInit)
+	{
+		status = PAL_ERR_TLS_CONTEXT_NOT_INITIALIZED;
+		goto finish;
+	}
+
+
+	mbedtls_ssl_free(&localTLSCtx->tlsCtx);
+    free(localTLSCtx);
+	*palTLSHandle = NULLPTR;
+
+finish:
+	return status;
+}
+
+
+palStatus_t pal_plat_setAuthenticationMode(palTLSConfHandle_t sslConf, palTLSAuthMode_t authMode)
+{
+	palStatus_t status = PAL_SUCCESS;
+	int32_t platAuthMode;
+	palTLSConf_t* localConfigCtx = (palTLSConf_t*)sslConf;
+
+	switch(authMode)
+	{
+		case PAL_TLS_VERIFY_NONE:
+			platAuthMode = MBEDTLS_SSL_VERIFY_NONE;
+			break;			
+		case PAL_TLS_VERIFY_OPTIONAL:
+			platAuthMode = MBEDTLS_SSL_VERIFY_OPTIONAL;
+			break;			
+		case PAL_TLS_VERIFY_REQUIRED:
+			platAuthMode = MBEDTLS_SSL_VERIFY_REQUIRED;
+			break;			
+		default:
+			status = PAL_ERR_INVALID_ARGUMENT;
+			goto finish;
+	};
+	mbedtls_ssl_conf_authmode(localConfigCtx->confCtx, platAuthMode );
+
+finish:
+	return status;	
+}
+
+palStatus_t pal_plat_setCipherSuites(palTLSConfHandle_t sslConf, palTLSSuites_t palSuite)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConf_t* localConfigCtx = (palTLSConf_t*)sslConf;
+
+	switch(palSuite)
+	{
+		case PAL_TLS_PSK_WITH_AES_128_CBC_SHA256:
+			localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256;
+			break;
+    	case PAL_TLS_PSK_WITH_AES_128_CCM_8:
+			localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8;
+			break;
+		case PAL_TLS_PSK_WITH_AES_256_CCM_8:
+			localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8;
+			break;
+		case PAL_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
+			localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
+			break;
+		case PAL_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+			localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
+			break;
+		case PAL_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+			localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
+			break;
+#ifdef MBEDTLS_ARIA_C
+        case PAL_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256:
+            localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256;
+            break;
+        case PAL_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256:
+            localConfigCtx->cipherSuites[0] = MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256;
+            break;
+#endif
+		default:
+			localConfigCtx->cipherSuites[0] = 0;
+			status = PAL_ERR_TLS_INVALID_CIPHER;
+			goto finish;
+	}
+
+	mbedtls_ssl_conf_ciphersuites(localConfigCtx->confCtx, localConfigCtx->cipherSuites);
+finish:
+	return status;
+}
+
+palStatus_t pal_plat_sslGetVerifyResultExtended(palTLSHandle_t palTLSHandle, int32_t* verifyResult)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+	*verifyResult = 0;
+	
+    platStatus = mbedtls_ssl_get_verify_result(&localTLSCtx->tlsCtx);
+	if (SSL_LIB_SUCCESS != platStatus)
+	{
+		status = PAL_ERR_X509_CERT_VERIFY_FAILED;
+#if (PAL_ENABLE_X509 == 1)
+        //! please DO NOT change errors order
+		if (MBEDTLS_X509_BADCERT_NOT_TRUSTED & platStatus)
+        {
+            *verifyResult |= PAL_ERR_X509_BADCERT_NOT_TRUSTED;
+			status = PAL_ERR_X509_BADCERT_NOT_TRUSTED;
+        }
+        if (MBEDTLS_X509_BADCERT_BAD_KEY & platStatus)
+        {
+            *verifyResult |= PAL_ERR_X509_BADCERT_BAD_KEY;
+			status = PAL_ERR_X509_BADCERT_BAD_KEY;
+        }
+		if (MBEDTLS_X509_BADCERT_BAD_PK & platStatus)
+        {
+            *verifyResult |= PAL_ERR_X509_BADCERT_BAD_PK;
+			status = PAL_ERR_X509_BADCERT_BAD_PK;
+        }
+		if (MBEDTLS_X509_BADCERT_BAD_MD & platStatus)
+        {
+            *verifyResult |= PAL_ERR_X509_BADCERT_BAD_MD;
+			status = PAL_ERR_X509_BADCERT_BAD_MD;
+        }
+        if (MBEDTLS_X509_BADCERT_FUTURE & platStatus)
+        {
+            *verifyResult |= PAL_ERR_X509_BADCERT_FUTURE;
+			status = PAL_ERR_X509_BADCERT_FUTURE;
+        }
+		if (MBEDTLS_X509_BADCERT_EXPIRED & platStatus)
+        {
+            *verifyResult |= PAL_ERR_X509_BADCERT_EXPIRED;
+			status = PAL_ERR_X509_BADCERT_EXPIRED;
+        }
+#endif
+	}
+	return status;
+}
+
+palStatus_t pal_plat_sslRead(palTLSHandle_t palTLSHandle, void *buffer, uint32_t len, uint32_t* actualLen)
+{
+	palStatus_t status = PAL_SUCCESS;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+	palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle;
+
+	platStatus = mbedtls_ssl_read(&localTLSCtx->tlsCtx, (unsigned char*)buffer, len);
+	if (platStatus > SSL_LIB_SUCCESS)
+	{
+		*actualLen = platStatus;
+	}
+	else
+	{
+		status = translateTLSErrToPALError(platStatus);
+		if (MBEDTLS_ERR_SSL_WANT_READ != platStatus)
+		{
+			PAL_LOG(ERR, "SSL Read return code %" PRId32 ".", platStatus);
+		}
+		else
+		{
+			PAL_LOG(DBG, "SSL Read return code %" PRId32 ".", platStatus);
+		}
+	}
+		
+	return status;
+}
+
+
+palStatus_t pal_plat_sslWrite(palTLSHandle_t palTLSHandle, const void *buffer, uint32_t len, uint32_t *bytesWritten)
+{
+	palStatus_t status = PAL_SUCCESS;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+	palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle;
+
+	platStatus = mbedtls_ssl_write(&localTLSCtx->tlsCtx, (unsigned char*)buffer, len);
+	if (platStatus > SSL_LIB_SUCCESS)
+	{
+		*bytesWritten = platStatus;
+	}
+	else
+	{
+		status = translateTLSErrToPALError(platStatus);
+		if (MBEDTLS_ERR_SSL_WANT_WRITE != platStatus)
+		{
+			PAL_LOG(ERR, "SSL Write platform return code %" PRId32 ".", platStatus);
+		}
+		else
+		{
+			PAL_LOG(DBG, "SSL Write platform return code %" PRId32 ".", platStatus);
+		}
+	}
+
+	return status;
+}
+
+
+palStatus_t pal_plat_setHandShakeTimeOut(palTLSConfHandle_t palTLSConf, uint32_t timeoutInMilliSec)
+{
+	palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
+	uint32_t minTimeout = PAL_DTLS_PEER_MIN_TIMEOUT;
+	uint32_t maxTimeout = timeoutInMilliSec >> 1; //! faster dividing by 2
+	//! Since mbedTLS algorithm for UDP handshake algorithm is as follow:
+	//! wait 'minTimeout' ..=> 'minTimeout = 2*minTimeout' while 'minTimeout < maxTimeout'
+	//! if 'minTimeout >= maxTimeout' them wait 'maxTimeout'.
+	//! The whole waiting time is the sum of the different intervals waited.
+	//! Therefore we need divide the 'timeoutInMilliSec' by 2 to give a close approximation of the desired 'timeoutInMilliSec'
+	//! 1 + 2 + ... + 'timeoutInMilliSec/2' ~= 'timeoutInMilliSec'
+
+	if (maxTimeout < PAL_DTLS_PEER_MIN_TIMEOUT)
+	{
+		minTimeout = (timeoutInMilliSec+1) >> 1; //to prevent 'minTimeout == 0'
+		maxTimeout = timeoutInMilliSec;
+	}
+
+	mbedtls_ssl_conf_handshake_timeout(localConfigCtx->confCtx, minTimeout, maxTimeout);
+
+	return PAL_SUCCESS;
+}
+
+
+palStatus_t pal_plat_sslSetup(palTLSHandle_t palTLSHandle, palTLSConfHandle_t palTLSConf)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle;
+	palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+
+	if (!localTLSCtx->wantReadOrWrite)
+	{
+        platStatus = mbedtls_ssl_setup(&localTLSCtx->tlsCtx, localConfigCtx->confCtx);
+		if (SSL_LIB_SUCCESS != platStatus)
+		{
+			if (MBEDTLS_ERR_SSL_ALLOC_FAILED == platStatus)
+			{
+				status = PAL_ERR_NO_MEMORY;
+				goto finish;
+			}
+			PAL_LOG(ERR, "SSL setup return code %" PRId32 ".", platStatus);
+			status = PAL_ERR_GENERIC_FAILURE;
+			goto finish;
+		}
+
+		localConfigCtx->tlsContext = localTLSCtx;
+	}
+finish:
+	return status;
+}
+
+palStatus_t pal_plat_handShake(palTLSHandle_t palTLSHandle, uint64_t* serverTime)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+	while( (MBEDTLS_SSL_HANDSHAKE_OVER != localTLSCtx->tlsCtx.state) && (PAL_SUCCESS == status) )
+    {
+        platStatus = mbedtls_ssl_handshake_step( &localTLSCtx->tlsCtx );
+
+		/* Extract the first 4 bytes of the ServerHello random */
+		if( MBEDTLS_SSL_SERVER_HELLO_DONE == localTLSCtx->tlsCtx.state )
+		{
+			*serverTime = (uint64_t)
+				( (uint32_t)localTLSCtx->tlsCtx.handshake->randbytes[32 + 0] << 24 ) |
+				( (uint32_t)localTLSCtx->tlsCtx.handshake->randbytes[32 + 1] << 16 ) |
+				( (uint32_t)localTLSCtx->tlsCtx.handshake->randbytes[32 + 2] << 8  ) |
+				( (uint32_t)localTLSCtx->tlsCtx.handshake->randbytes[32 + 3] << 0  );
+		}
+		if (SSL_LIB_SUCCESS != platStatus)
+		{
+			status = translateTLSHandShakeErrToPALError(localTLSCtx, platStatus);
+		}
+	}
+	return status;
+}
+
+#if PAL_USE_SECURE_TIME
+palStatus_t pal_plat_renegotiate(palTLSHandle_t palTLSHandle, uint64_t serverTime)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palStatus_t mutexStatus = PAL_SUCCESS;
+	palTLS_t* localTLSCtx = (palTLS_t*)palTLSHandle;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+
+	status = pal_osMutexWait(g_palTLSTimeMutex, PAL_RTOS_WAIT_FOREVER);
+	if (PAL_SUCCESS != status)
+	{
+		PAL_LOG(ERR, "Failed to get TLS time Mutex error: %" PRId32 ".", status);
+		goto finish;
+	}
+
+
+	if (0 == g_timeFromHS)
+	{
+		g_timeFromHS = (mbedtls_time_t)serverTime;
+	}
+	else
+	{ //! need to change the code for multi-threading mode (Erez)
+		status = PAL_ERR_TLS_MULTIPLE_HANDSHAKE;
+		goto finish;
+	}
+
+	platStatus = mbedtls_ssl_renegotiate(&localTLSCtx->tlsCtx);    
+	status = translateTLSHandShakeErrToPALError(localTLSCtx, platStatus);
+
+finish:
+	g_timeFromHS = 0;
+	
+	mutexStatus = pal_osMutexRelease(g_palTLSTimeMutex);
+	if (PAL_SUCCESS != mutexStatus)
+	{
+		PAL_LOG(ERR, "Failed to get TLS time Mutex error: %" PRId32 ".", mutexStatus);
+	}
+	if (PAL_SUCCESS == status)
+	{
+		status = mutexStatus;
+	}
+
+	return status;
+}
+#endif //PAL_USE_SECURE_TIME
+
+
+#if (PAL_ENABLE_X509 == 1)
+palStatus_t pal_plat_setOwnCertAndPrivateKey(palTLSConfHandle_t palTLSConf, palX509_t* ownCert, palPrivateKey_t* privateKey)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+
+	mbedtls_pk_init(&localConfigCtx->pkey);
+
+	
+    platStatus = mbedtls_x509_crt_parse_der(&localConfigCtx->owncert, (const unsigned char *)ownCert->buffer, ownCert->size);
+	if (SSL_LIB_SUCCESS != platStatus)
+	{
+		status = PAL_ERR_TLS_FAILED_TO_PARSE_CERT;
+		goto finish;
+	}
+
+	platStatus = mbedtls_pk_parse_key(&localConfigCtx->pkey, (const unsigned char *)privateKey->buffer, privateKey->size, NULL, 0 );
+	if (SSL_LIB_SUCCESS != platStatus)
+	{
+		status = PAL_ERR_TLS_FAILED_TO_PARSE_KEY;
+		goto finish;
+	}
+
+	platStatus = mbedtls_ssl_conf_own_cert(localConfigCtx->confCtx, &localConfigCtx->owncert, &localConfigCtx->pkey); 
+	if (SSL_LIB_SUCCESS != platStatus)
+	{
+		status = PAL_ERR_TLS_FAILED_TO_SET_CERT;
+	}
+
+	localConfigCtx->hasKeys = true;
+
+finish:
+	PAL_LOG(DBG, "TLS set and parse status %" PRIu32 ".", platStatus);
+	return status;
+}
+
+palStatus_t pal_plat_setOwnPrivateKey(palTLSConfHandle_t palTLSConf, palPrivateKey_t* privateKey)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+
+	mbedtls_pk_init(&localConfigCtx->pkey);
+
+	platStatus = mbedtls_pk_parse_key(&localConfigCtx->pkey, (const unsigned char *)privateKey->buffer, privateKey->size, NULL, 0 );
+	if (SSL_LIB_SUCCESS != platStatus)
+	{
+		status = PAL_ERR_TLS_FAILED_TO_PARSE_KEY;
+		goto finish;
+	}
+
+
+	localConfigCtx->hasKeys = true;
+
+finish:
+	PAL_LOG(DBG, "Privatekey set and parse status %" PRIu32 ".", platStatus);
+	return status;
+}
+
+palStatus_t pal_plat_setOwnCertChain(palTLSConfHandle_t palTLSConf, palX509_t* ownCert)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+
+	platStatus = mbedtls_x509_crt_parse_der(&localConfigCtx->owncert, (const unsigned char *)ownCert->buffer, ownCert->size);
+	if (SSL_LIB_SUCCESS != platStatus)
+	{
+		status = PAL_ERR_TLS_FAILED_TO_PARSE_CERT;
+		goto finish;
+	}
+
+	platStatus = mbedtls_ssl_conf_own_cert(localConfigCtx->confCtx, &localConfigCtx->owncert, &localConfigCtx->pkey); 
+	if (SSL_LIB_SUCCESS != platStatus)
+	{
+		status = PAL_ERR_TLS_FAILED_TO_SET_CERT;
+	}
+
+	localConfigCtx->hasKeys = true;
+
+finish:
+	PAL_LOG(DBG, "Own cert chain set and parse status %" PRIu32 ".", platStatus);
+	return status;
+}
+
+
+palStatus_t pal_plat_setCAChain(palTLSConfHandle_t palTLSConf, palX509_t* caChain, palX509CRL_t* caCRL)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+
+	platStatus = mbedtls_x509_crt_parse_der(&localConfigCtx->cacert, (const unsigned char *)caChain->buffer, caChain->size);
+	if (SSL_LIB_SUCCESS != platStatus)
+	{
+		PAL_LOG(ERR, "TLS CA chain status %" PRId32 ".", platStatus);
+		status = PAL_ERR_GENERIC_FAILURE;
+		goto finish;
+	}
+	mbedtls_ssl_conf_ca_chain(localConfigCtx->confCtx, &localConfigCtx->cacert, NULL );
+
+	localConfigCtx->hasChain = true;
+finish:
+	return status;
+}
+#endif
+
+#if (PAL_ENABLE_PSK == 1)
+palStatus_t pal_plat_setPSK(palTLSConfHandle_t palTLSConf, const unsigned char *identity, uint32_t maxIdentityLenInBytes, const unsigned char *psk, uint32_t maxPskLenInBytes)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
+	int32_t platStatus = SSL_LIB_SUCCESS;
+
+	platStatus = mbedtls_ssl_conf_psk(localConfigCtx->confCtx, psk, maxPskLenInBytes, identity, maxIdentityLenInBytes);
+	if (SSL_LIB_SUCCESS != platStatus)
+	{
+		if (MBEDTLS_ERR_SSL_ALLOC_FAILED == platStatus)
+		{
+			status = PAL_ERR_TLS_INIT;
+			goto finish;
+		}
+		PAL_LOG(ERR, "TLS set psk status %" PRId32 ".", platStatus);
+		status = PAL_ERR_GENERIC_FAILURE;
+	}
+finish:
+	return status;
+}
+
+#endif
+palStatus_t pal_plat_tlsSetSocket(palTLSConfHandle_t palTLSConf, palTLSSocket_t* socket)
+{
+	palStatus_t status = PAL_SUCCESS;
+
+	status = pal_plat_sslSetIOCallBacks(palTLSConf, socket, palBIOSend, palBIORecv);
+	return status;
+}
+
+palStatus_t pal_plat_sslSetIOCallBacks(palTLSConfHandle_t palTLSConf, palTLSSocket_t* palIOCtx, palBIOSend_f palBIOSend, palBIORecv_f palBIORecv)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
+	bool isNonBlocking = false;
+
+	localConfigCtx->palIOCtx = palIOCtx;
+
+	status = pal_isNonBlocking(palIOCtx->socket, &isNonBlocking);
+	if (PAL_SUCCESS != status)
+	{
+		return status;
+	}
+
+	if (isNonBlocking)
+	{
+		mbedtls_ssl_set_bio(&localConfigCtx->tlsContext->tlsCtx, palIOCtx, palBIOSend, palBIORecv, NULL);
+	}
+	else
+	{
+		mbedtls_ssl_set_bio(&localConfigCtx->tlsContext->tlsCtx, palIOCtx, palBIOSend, NULL, palBIORecv_timeout);
+	}
+
+	return PAL_SUCCESS;
+}
+
+
+
+palStatus_t pal_plat_sslSetDebugging(palTLSConfHandle_t palTLSConf, uint8_t turnOn)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palLogFunc_f func = NULL;
+#if defined(MBEDTLS_DEBUG_C)	
+    mbedtls_debug_set_threshold(PAL_TLS_DEBUG_THRESHOLD);
+#endif
+
+    if (turnOn)
+    {
+        func = palDebug;
+    }
+    status = pal_plat_SetLoggingCb(palTLSConf, func, NULL);
+    return  status;
+}
+
+palStatus_t pal_plat_SetLoggingCb(palTLSConfHandle_t palTLSConf, palLogFunc_f palLogFunction, void *logContext)
+{
+	palTLSConf_t* localConfigCtx = (palTLSConf_t*)palTLSConf;
+	
+	mbedtls_ssl_conf_dbg(localConfigCtx->confCtx, palLogFunction, logContext);
+	return PAL_SUCCESS;
+}
+
+PAL_PRIVATE uint64_t palTimingGetTimer(uint64_t *start_ticks, int reset)
+{
+	uint64_t delta_ms;
+	uint64_t ticks = pal_osKernelSysTick();
+
+	if (reset)
+	{
+		*start_ticks = ticks;
+		delta_ms = 0;
+	}
+	else
+	{
+		delta_ms = pal_osKernelSysMilliSecTick(ticks - *start_ticks);
+	}
+
+	return delta_ms;
+}
+
+
+/*
+ * Set delays to watch
+ */
+PAL_PRIVATE void palTimingSetDelay( void *data, uint32_t intMs, uint32_t finMs )
+{
+
+    palTimingDelayContext_t *ctx = data;
+
+    ctx->int_ms = intMs;
+    ctx->fin_ms = finMs;
+
+    if( finMs != 0 )
+	{
+		(void) palTimingGetTimer( &ctx->start_ticks, 1 );
+	}
+}
+
+/*
+ * Get number of delays expired
+ */
+PAL_PRIVATE int palTimingGetDelay( void *data )
+{
+	int result = 0;
+    palTimingDelayContext_t *ctx = data;
+    uint64_t elapsed_ms;
+
+    if( ctx->fin_ms == 0 )
+	{
+		result = -1;
+		goto finish;
+	}
+
+    elapsed_ms = palTimingGetTimer( &ctx->start_ticks, 0 );
+
+    if( elapsed_ms >= ctx->fin_ms )
+	{
+		result = 2;
+		goto finish;
+	}
+
+    if( elapsed_ms >= ctx->int_ms )
+	{
+		result = 1;
+		goto finish;
+	}
+
+finish:
+    return result;
+}
+
+
+int pal_plat_entropySourceTLS( void *data, unsigned char *output, size_t len, size_t *olen )
+{
+	palStatus_t status = PAL_SUCCESS;
+	(void)data;
+
+	status = pal_osRandomBuffer((uint8_t*) output, len);
+	if (PAL_SUCCESS == status)
+	{
+		if (NULL != olen)
+		{
+			*olen = len;
+		}
+		return 0;
+	}
+	else
+	{
+		return -1;
+	}
+}
+
+PAL_PRIVATE int palBIOSend(palTLSSocketHandle_t socket, const unsigned char *buf, size_t len)
+{
+	palStatus_t status = PAL_SUCCESS;
+	size_t sentDataSize = 0;
+	palTLSSocket_t* localSocket = (palTLSSocket_t*)socket;
+
+	if (NULLPTR == socket)
+	{
+		status = -1;
+		goto finish;
+	}
+
+	if (PAL_TLS_MODE == localSocket->transportationMode)
+	{
+		status = pal_send(localSocket->socket, buf, len, &sentDataSize);
+	}
+	else if (PAL_DTLS_MODE == localSocket->transportationMode)
+	{
+		status = pal_sendTo(localSocket->socket, buf, len, localSocket->socketAddress, localSocket->addressLength, &sentDataSize);
+	}
+	else
+	{
+		PAL_LOG(ERR, "TLS BIO send error");
+		status = PAL_ERR_GENERIC_FAILURE;
+	}
+	if (PAL_SUCCESS == status || PAL_ERR_NO_MEMORY == status || PAL_ERR_SOCKET_WOULD_BLOCK == status)
+	{
+        if (PAL_ERR_NO_MEMORY == status) 
+        { 
+            PAL_LOG(DBG, "Network module returned out of memory error, retrying..."); //Network module can return NO_MEMORY error since it was not able to allocate 
+																					  //memory at this point of time. In this case we translate the error to WANT_WRITE 
+																					  //in order to let the Network module retry to allocate the memory. 
+																					  //In case of real out of memory the handshake timeout will break the handshake process. 
+        }
+
+		if (0 != sentDataSize)
+		{
+            status = sentDataSize;
+		}
+		else
+		{
+			status = MBEDTLS_ERR_SSL_WANT_WRITE;
+		}
+	}
+finish:
+	return status;
+}
+
+PAL_PRIVATE int palBIORecv(palTLSSocketHandle_t socket, unsigned char *buf, size_t len)
+{
+	palStatus_t status = PAL_SUCCESS;
+	size_t recievedDataSize = 0;
+	palTLSSocket_t* localSocket = (palTLSSocket_t*)socket;
+
+	if (NULLPTR == socket)
+	{
+		status = -1;
+		goto finish;
+	}
+
+	if (PAL_TLS_MODE == localSocket->transportationMode)
+	{
+		status = pal_recv(localSocket->socket, buf, len, &recievedDataSize);
+		if (PAL_SUCCESS == status)
+		{
+			status = recievedDataSize;
+		}
+		else if (PAL_ERR_SOCKET_WOULD_BLOCK == status)
+		{
+			status = MBEDTLS_ERR_SSL_WANT_READ;
+		}
+	}
+	else if (PAL_DTLS_MODE == localSocket->transportationMode)
+	{
+		status = pal_receiveFrom(localSocket->socket, buf, len, localSocket->socketAddress, &localSocket->addressLength, &recievedDataSize);
+		if (PAL_SUCCESS == status)
+		{
+			if (0 != recievedDataSize)
+			{
+				status = recievedDataSize;
+			}
+			else
+			{
+				status = MBEDTLS_ERR_SSL_WANT_READ;
+			}
+		}
+		else if (PAL_ERR_SOCKET_WOULD_BLOCK == status)
+		{
+			status = MBEDTLS_ERR_SSL_WANT_READ;
+		}
+	}
+	else
+	{
+		PAL_LOG(ERR, "TLS BIO recv error");
+		status = PAL_ERR_GENERIC_FAILURE;
+	}
+
+finish:
+	return status;
+}
+
+PAL_PRIVATE int palBIORecv_timeout(palTLSSocketHandle_t socket, unsigned char *buf, size_t len, uint32_t timeout)
+{	
+	palStatus_t status = PAL_SUCCESS;
+	size_t recievedDataSize = 0;
+	uint32_t localTimeOut = timeout;
+	palTLSSocket_t* localSocket = (palTLSSocket_t*)socket;
+	bool isNonBlocking = false;
+
+	if (NULLPTR == socket)
+	{
+		status = -1;
+		goto finish;
+	}
+	
+	status = pal_isNonBlocking(localSocket->socket, &isNonBlocking);
+	if (PAL_SUCCESS != status)
+	{
+		goto finish;
+	}
+
+	if (PAL_TLS_MODE == localSocket->transportationMode)
+	{
+		status = pal_recv(localSocket->socket, buf, len, &recievedDataSize);
+		if (PAL_SUCCESS == status)
+		{
+			status = recievedDataSize;
+		}
+		else if (PAL_ERR_SOCKET_WOULD_BLOCK == status)
+		{
+			status = MBEDTLS_ERR_SSL_WANT_READ;
+		}
+	}
+	else if (PAL_DTLS_MODE == localSocket->transportationMode)
+	{
+		if (false == isNonBlocking) // timeout is relevant only if socket is blocking
+		{
+			status = pal_setSocketOptions(localSocket->socket, PAL_SO_RCVTIMEO, &localTimeOut, sizeof(localTimeOut));
+			if (PAL_SUCCESS != status)
+			{
+				goto finish;
+			}
+		}
+
+		status = pal_receiveFrom(localSocket->socket, buf, len, localSocket->socketAddress, &localSocket->addressLength, &recievedDataSize);
+		
+		if (PAL_SUCCESS == status)
+		{
+			if (0 != recievedDataSize)
+			{
+				status = recievedDataSize;
+			}
+			else
+			{
+				status = MBEDTLS_ERR_SSL_WANT_READ;
+			}
+		}
+		else if (PAL_ERR_SOCKET_WOULD_BLOCK == status)
+		{
+			status = MBEDTLS_ERR_SSL_TIMEOUT;
+		}
+	}
+	else
+	{
+		PAL_LOG(ERR, "TLS BIO recv timeout error");
+		status = PAL_ERR_GENERIC_FAILURE;
+	}
+
+finish:
+	return status;
+}
+
+#if PAL_USE_SECURE_TIME
+#ifdef MBEDTLS_PLATFORM_TIME_ALT
+PAL_PRIVATE mbedtls_time_t pal_mbedtlsTimeCB(mbedtls_time_t* timer)
+{
+	palStatus_t status = PAL_SUCCESS;
+	mbedtls_time_t mbedtlsTime = 0;
+
+	status = pal_osMutexWait(g_palTLSTimeMutex, PAL_RTOS_WAIT_FOREVER);
+	if (PAL_SUCCESS != status)
+	{
+		PAL_LOG(ERR, "Failed to get TLS time Mutex error: %" PRId32 ".", status);
+		goto finish;
+	}
+
+	if (0 != g_timeFromHS)
+	{
+		mbedtlsTime = g_timeFromHS;
+	}
+	else
+	{
+		uint64_t currentTime = pal_osGetTime();
+		//mbedtls_time_t is defined to time_t, so we can do a safe copy since till 2038 the value in currentTime is less than MAX_TIME_T_VALUE
+		mbedtlsTime = (mbedtls_time_t)currentTime; 	
+	}
+	status = pal_osMutexRelease(g_palTLSTimeMutex);
+	if (PAL_SUCCESS != status)
+	{
+		PAL_LOG(ERR, "Failed to release TLS time Mutex error: %" PRId32 ".", status);
+	}
+finish:
+	if (PAL_SUCCESS != status)
+	{
+		mbedtlsTime = 0;
+	}
+	return mbedtlsTime;
+}
+#endif
+#endif //PAL_USE_SECURE_TIME
+
+PAL_PRIVATE void palDebug(void *ctx, int debugLevel, const char *fileName, int line, const char *message)
+{
+	(void)ctx;
+	PAL_LOG(DBG, "%s: %d: %s", fileName, line, message);
+}
+
+#ifdef MBEDTLS_ENTROPY_NV_SEED
+int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len )
+{
+	palStatus_t status = PAL_SUCCESS;
+	status = pal_osRandomBuffer(buf, buf_len);
+	if (PAL_SUCCESS != status)
+	{
+	    return -1;
+	}
+	return 0;
+}
+
+int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len )
+{
+	return 0;
+}
+#endif //MBEDTLS_ENTROPY_NV_SEED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+Linux/*
+FreeRTOS/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/Board_Specific/TARGET_K64F/pal_plat_K64F.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+ 
+#include "pal_plat_rtos.h"
+#include "fsl_device_registers.h"
+#include "fsl_debug_console.h"
+#include "board.h"
+#include "fsl_rtc.h"
+#include "clock_config.h"
+
+
+/////////////////////////STATIC FUNCTION///////////////////////////
+/*! disable all interrupts in system
+*
+* @param[in] Void
+* \returns void
+*
+*/
+PAL_PRIVATE PAL_INLINE void pal_plat_DisableIrq(void);
+/*! Enable all interrupts in system
+*
+* @param[in] Void
+* \returns void
+*
+*/
+PAL_PRIVATE PAL_INLINE void pal_plat_EnableIrq(void);
+
+
+/*! get one random byte
+*
+* @param[out] byte: pointer to one byte to hold the random number
+*
+* \returns void
+*/
+PAL_PRIVATE void getTRNGByte(unsigned char *byte);
+
+/*! get random number in size of given bytes
+*
+* @param[out] output: pointer to buffer to hold the random number
+* @param[in] length: size of the output buffer
+* @param[out] output_length: actual size of the written data
+*
+* \returns void
+*/
+PAL_PRIVATE int getTRNGBytes(uint8_t *output, size_t length, size_t *output_length);
+
+PAL_PRIVATE PAL_INLINE void pal_plat_DisableIrq(void)
+{
+	__asm volatile 	( " cpsid i " );
+}
+
+PAL_PRIVATE PAL_INLINE void pal_plat_EnableIrq(void)
+{
+	__asm volatile 	( " cpsie i " );
+}
+/////////////////////////END STATIC FUNCTION///////////////////////////
+
+#if defined (__CC_ARM)          /* ARM Compiler */
+
+#pragma push
+#pragma O0
+
+#if ((defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M)) && !defined(NO_EXCLUSIVE_ACCESS))
+#define __USE_EXCLUSIVE_ACCESS
+#else
+#undef  __USE_EXCLUSIVE_ACCESS
+#endif // ARMCC end
+
+#elif defined (__GNUC__)        /* GNU Compiler */
+
+#undef  __USE_EXCLUSIVE_ACCESS
+#pragma GCC push_options
+#pragma GCC optimize ("O0")
+
+#if defined (__CORTEX_M0)
+#define __TARGET_ARCH_6S_M
+#endif
+
+#if defined (__VFP_FP__) && !defined(__SOFTFP__)
+#define __TARGET_FPU_VFP
+#endif
+#endif
+
+int32_t pal_plat_osAtomicIncrement(int32_t* valuePtr, int32_t increment)
+{
+#ifdef __USE_EXCLUSIVE_ACCESS
+        int32_t res;
+        res = __ldrex(valuePtr) + increment;
+        do {
+        } while (__strex(res, valuePtr));
+        return (res);
+#elif !defined (__CORTEX_M0)
+    if (valuePtr != NULL)
+    {
+        asm volatile(
+        "try:\n\t"
+            "LDREX   R0, [%[valuePtr]]\n\t"
+            "ADD     R0, %[increment]\n\t"
+            "CMP     R0, R0\n\t"
+            "ITT     EQ\n\t"
+            "STREXEQ R1, R0, [%[valuePtr]]\n\t"
+            "CMPEQ   R1, #0\n\t"
+            "BNE     try\n\t"
+            :[valuePtr]"+r"(valuePtr)
+            :[increment]"r"(increment)
+            );
+        return *valuePtr;
+    }
+    else
+    {
+        return 0;
+    }
+#else
+    int32_t res;
+    pal_plat_DisableIrq();
+     res = *valuePtr + increment;
+    *valuePtr = res;
+    pal_plat_EnableIrq();
+    return (res);
+#endif
+
+}
+#if defined (__CC_ARM)          /* ARM Compiler */
+
+#pragma pop
+
+#elif defined (__GNUC__)
+
+#pragma GCC pop_options
+
+#endif
+
+
+void pal_plat_osReboot()
+{
+#define RESET_MASK_FOR_CORTEX_M_SERIES	0x5fa0004
+
+    volatile unsigned int * AIRCR_REG = (volatile unsigned int *)(0xE000ED0C);  //This register address is true for the Cortex M family
+    *AIRCR_REG = RESET_MASK_FOR_CORTEX_M_SERIES;
+    while(1);                                                    /* wait until reset */
+}
+
+/*
+ * Get one byte of entropy from the RNG, assuming it is up and running.
+ * As recommended (34.1.1), get only one bit of each output.
+ */
+PAL_INLINE void getTRNGByte(unsigned char *byte)
+{
+    size_t bit;
+
+    /* 34.5 Steps 3-4-5: poll SR and read from OR when ready */
+    for( bit = 0; bit < 8; bit++ )
+    {
+        //! while random-data output is zero, wait in the while, else read the OR (Output Register)
+        while((RNG->SR & RNG_SR_OREG_LVL_MASK) == 0 );
+        *byte |= (RNG->OR & 1) << bit;
+    }
+}
+
+PAL_PRIVATE int getTRNGBytes(uint8_t *output, size_t length, size_t *output_length)
+{
+    size_t i;
+
+    /* Set "Interrupt Mask", "High Assurance" and "Go",
+     * unset "Clear interrupt" and "Sleep" */
+    RNG->CR = RNG_CR_INTM_MASK | RNG_CR_HA_MASK | RNG_CR_GO_MASK;
+
+    for (i = 0; i < length; i++) {
+        getTRNGByte(output + i);
+    }
+
+    /* Just be extra sure that we didn't do it wrong */
+    //! to make sure that no Security Violation has occured.
+    if ((RNG->SR & RNG_SR_SECV_MASK) != 0) {
+        return -1;
+    }
+
+    *output_length = length;
+
+    return 0;
+}
+
+palStatus_t pal_plat_getRandomBufferFromHW(uint8_t *randomBuf, size_t bufSizeBytes, size_t* actualRandomSizeBytes)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = 0;
+    size_t actualOutputLen = 0;
+        
+    platStatus = getTRNGBytes(randomBuf, bufSizeBytes, &actualOutputLen);
+    if ((0 != platStatus) || (0 == actualOutputLen))
+    {
+        status = PAL_ERR_RTOS_TRNG_FAILED;
+    }
+    if (actualOutputLen != bufSizeBytes)
+    {
+        status = PAL_ERR_RTOS_TRNG_PARTIAL_DATA;
+    }
+
+    if (NULL != actualRandomSizeBytes)
+    {
+        *actualRandomSizeBytes = actualOutputLen;
+    }
+    return status;
+}
+
+#if (PAL_USE_HW_RTC)
+palMutexID_t rtcMutex = NULLPTR;
+palStatus_t pal_plat_osGetRtcTime(uint64_t *rtcGetTime)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if(rtcGetTime != NULL)
+    {
+        *rtcGetTime = RTC->TSR;
+    }
+    else
+    {
+        ret = PAL_ERR_NULL_POINTER;
+    }
+    return ret;
+}
+
+palStatus_t pal_plat_osSetRtcTime(uint64_t rtcSetTime)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if (rtcSetTime < (uint64_t)PAL_MIN_RTC_SET_TIME)
+    {
+        ret = PAL_ERR_INVALID_TIME;
+    }
+    else
+    {
+        ret = pal_osMutexWait(rtcMutex, 5 * PAL_MILLI_PER_SECOND * PAL_ONE_SEC);
+        if(ret == PAL_SUCCESS)
+        {
+            RTC_StopTimer(RTC);
+            RTC->TSR = rtcSetTime;
+            RTC_StartTimer(RTC);
+            ret = pal_osMutexRelease(rtcMutex);
+        }
+    }
+    return ret;
+}
+
+palStatus_t pal_plat_rtcInit(void)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if(NULLPTR == rtcMutex)
+    {
+        ret = pal_osMutexCreate(&rtcMutex);
+    }
+    return ret;
+}
+
+palStatus_t pal_plat_rtcDeInit(void)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if(NULL != rtcMutex)
+    {
+        ret = pal_osMutexDelete(&rtcMutex);
+        rtcMutex = NULLPTR;
+    }
+    return ret;
+}
+#endif //#if (PAL_USE_HW_RTC)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/Networking/LWIP/pal_plat_network.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1039 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal.h"
+#include "pal_plat_network.h"
+
+#include "api.h" // include LWIP sockets header
+#include "netdb.h"
+#include "netif.h"
+#include "ip.h"
+#include "tcp.h"
+
+
+/* Static arena of sockets */
+//TODO: do we need to protect this agains multitheaded aceess? 
+ typedef struct palLwipSocketNetConnInfo {
+    bool inUse;
+
+    struct netconn *connection;
+    struct netbuf *buffer;
+    uint32_t offset;
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+    palAsyncSocketCallback_t callback;
+    void *callbackArgument;
+#endif
+ } palLwipNetConnInfo_t;
+
+ PAL_PRIVATE palLwipNetConnInfo_t palInternalSocketInfo[MEMP_NUM_NETCONN] = {0};
+
+ 
+// number taken from LWIP documentaiton reccomendations (http://www.ece.ualberta.ca/~cmpe401/docs/lwip.pdf)
+#define PAL_MAX_SEND_BUFFER_SIZE 1000
+
+ PAL_PRIVATE void* s_pal_networkInterfacesSupported[PAL_MAX_SUPORTED_NET_INTERFACES] = { 0 };
+
+ PAL_PRIVATE  uint32_t s_pal_numberOFInterfaces = 0;
+
+ 
+ /*! pal_plat_netconReceive
+  * This function is a workaround for LWIP non block receive,
+  * When calling netconn_recv() on a non-blocking connection with receive timeout=0 the netconn_recv function will block indefinately (unless data arrives). this is not correct behavior. 
+  * To work around this issue for to a non blocking connections we set the recieve timeout to 1 and set it back to the previous timeout value after the recv call.
+  * This is only for NON BLOCKING connections!!! all other sockets are left untouched.
+ * @param[in] netconn* conn handler
+ * @param[out] *netbuf - output buffer
+ \return The status form the netconn_recv call.
+ */
+PAL_PRIVATE int pal_plat_netconReceive(struct netconn* conn, struct netbuf **newBuf)
+{
+	int backupTimeout;
+	int result = PAL_SUCCESS;
+	bool isNonBlocking = netconn_is_nonblocking(conn);
+	if(isNonBlocking)
+	{
+		backupTimeout = netconn_get_recvtimeout(conn);
+		netconn_set_recvtimeout(conn, 1);
+		result = netconn_recv(conn, newBuf);
+		netconn_set_recvtimeout(conn, backupTimeout);
+	}
+	else
+	{
+		result = netconn_recv(conn, newBuf);
+	}
+
+	return result;
+}
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+
+// wrapper for callbacks because function signature is different.
+void palNetConAsyncCallback(struct netconn * connection, enum netconn_evt event, u16_t len)
+{
+    int index = 0;
+    for (index = 0; index < MEMP_NUM_NETCONN; index++)
+    {
+        if ( (true == palInternalSocketInfo[index].inUse ) && (palInternalSocketInfo[index].connection == connection))
+        {
+            if (NULL != palInternalSocketInfo[index].callback)
+            {
+                palInternalSocketInfo[index].callback(palInternalSocketInfo[index].callbackArgument);
+            }
+            break;
+        }
+    }
+}
+#endif
+
+
+
+
+palStatus_t pal_plat_socketsInit(void* context)
+{
+    (void)context; // parameter not used in this case - this avoids the warning
+    return PAL_SUCCESS;
+}
+
+
+palStatus_t pal_plat_registerNetworkInterface(void* context, uint32_t* interfaceIndex)
+{
+    palStatus_t result = PAL_SUCCESS;
+    uint32_t index = 0;
+    bool found = false;
+
+    for (index = 0; index < s_pal_numberOFInterfaces; index++) // if specific context already registered return exisitng index instead of registering again.
+    {
+        if (s_pal_networkInterfacesSupported[index] == context)
+        {
+            found = true;
+            *interfaceIndex = index;
+            break;
+        }
+    }
+
+    if (false == found)
+    {
+        if (s_pal_numberOFInterfaces < PAL_MAX_SUPORTED_NET_INTERFACES)
+        {
+            s_pal_networkInterfacesSupported[s_pal_numberOFInterfaces] = context;
+            *interfaceIndex = s_pal_numberOFInterfaces;
+            ++s_pal_numberOFInterfaces;
+        }
+        else
+        {
+            result = PAL_ERR_SOCKET_MAX_NUMBER_OF_INTERFACES_REACHED;
+        }
+    }
+
+    return result;
+}
+
+palStatus_t pal_plat_socketsTerminate(void* context)
+{
+    (void)context; // replace with macro
+    // clean up static sockets array ? (close all sockets?)
+    return PAL_SUCCESS;
+}
+
+
+PAL_PRIVATE palStatus_t translateErrnoToPALError(int errnoValue)
+{
+    palStatus_t status;
+    switch (errnoValue)
+    {
+    case ERR_MEM:
+        status = PAL_ERR_NO_MEMORY;
+        break;
+    case ERR_BUF:
+        status = PAL_ERR_SOCKET_NO_BUFFERS;
+        break;
+    case ERR_TIMEOUT:
+        status = PAL_ERR_SOCKET_WOULD_BLOCK;
+        break;
+    case ERR_RTE:
+        status = PAL_ERR_SOCKET_HOST_UNREACHABLE;
+        break;
+    case ERR_INPROGRESS:
+        status = PAL_ERR_SOCKET_IN_PROGRES;
+        break;
+    case ERR_VAL:
+        status = PAL_ERR_SOCKET_INVALID_VALUE;
+        break;
+    case ERR_WOULDBLOCK:
+        status = PAL_ERR_SOCKET_WOULD_BLOCK;
+        break;
+    case ERR_USE:
+        status = PAL_ERR_SOCKET_ADDRESS_IN_USE;
+        break;
+    case ERR_ISCONN:
+        status = PAL_ERR_SOCKET_ALREADY_CONNECTED;
+        break;
+    case ERR_ABRT:
+        status = PAL_ERR_SOCKET_CONNECTION_ABORTED;
+        break;
+    case ERR_RST:
+        status = PAL_ERR_SOCKET_CONNECTION_RESET;
+        break;
+    case ERR_CONN:
+        status = PAL_ERR_SOCKET_NOT_CONNECTED;
+        break;
+    case ERR_ARG:
+        status = PAL_ERR_INVALID_ARGUMENT;
+        break;
+    case ERR_CLSD:
+        status = PAL_ERR_SOCKET_CONNECTION_CLOSED;
+        break;
+    case ERR_IF:
+        status = PAL_ERR_SOCKET_INPUT_OUTPUT_ERROR;
+        break;
+
+    default:
+        status = PAL_ERR_SOCKET_GENERIC;
+        break;
+    }
+    return status;
+}
+
+
+palStatus_t pal_plat_socket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palSocket_t* socket)
+{
+    int result = PAL_SUCCESS;
+    enum netconn_type connType = NETCONN_INVALID;
+    struct netconn * con;
+    uint32_t numberOfInterfaces = 0;
+    palLwipNetConnInfo_t* socketInfo = NULL;
+    uint32_t index = 0;
+    
+
+
+    result = pal_plat_getNumberOfNetInterfaces(&numberOfInterfaces);
+    if (PAL_SUCCESS != result)
+    {
+        return result;
+    }
+
+
+    if (interfaceNum >= numberOfInterfaces && PAL_NET_DEFAULT_INTERFACE != interfaceNum)
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    if (domain != PAL_AF_INET)
+    {
+        return PAL_ERR_NOT_IMPLEMENTED;
+    }
+   
+    if ((PAL_SOCK_STREAM == type) || (PAL_SOCK_STREAM_SERVER == type))
+    {
+        connType = NETCONN_TCP;
+    }
+    else if (PAL_SOCK_DGRAM == type)
+    {
+        connType = NETCONN_UDP;
+    }
+    else
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+
+    for (index = 0; index < MEMP_NUM_NETCONN; index++) // allocate socket info structure.
+    {
+        if (false == palInternalSocketInfo[index].inUse)
+        {
+            palInternalSocketInfo[index].inUse = true;
+            socketInfo = &palInternalSocketInfo[index];
+            break;
+        }
+    }
+
+    if (NULL != socketInfo)
+    {
+        con = netconn_new(connType);
+        if (NULL != con)
+        {
+            // TODO(nirson01) : add binding to specific network interface  (interfaceNum)
+            if (nonBlockingSocket)
+            {
+                netconn_set_nonblocking(con, 1);
+            }
+            socketInfo->connection = con;
+        socketInfo->buffer = NULL;
+            *socket = (palSocket_t)socketInfo;
+        }
+        else
+        {
+            result = PAL_ERR_NO_MEMORY;
+        }
+    }
+    else
+    {
+        result = PAL_ERR_NO_MEMORY;
+    }
+
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastrucature is finalized)
+}
+
+
+palStatus_t pal_plat_setSocketOptions(palSocket_t socket, int optionName, const void* optionValue, palSocketLength_t optionLength)
+{
+    palStatus_t result = PAL_SUCCESS;
+    struct netconn* conn = NULL;
+    if (NULL == socket) // NULL is not a vlaid socket.
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    conn = ((palLwipNetConnInfo_t*)socket)->connection;
+    
+    if (PAL_SO_REUSEADDR == optionName)
+    {
+        ip_set_option(conn->pcb.ip, SOF_REUSEADDR);
+    }
+#if PAL_NET_TCP_AND_TLS_SUPPORT // socket options below supported only if TCP is supported.
+    else  if ((PAL_SO_KEEPALIVE == optionName) && (NETCONN_TCP == conn->type) && (conn->pcb.tcp != NULL))
+    {
+        if (*(int*)optionValue != 0)
+        {
+            ip_set_option(conn->pcb.ip, SOF_KEEPALIVE);
+        }
+        else 
+        {
+            ip_reset_option(conn->pcb.ip, SOF_KEEPALIVE);
+        }
+    }
+#if LWIP_TCP_KEEPALIVE // follwing options only supported if LWIP_TCP_KEEPALIVE is set to 1. 
+    else  if ((PAL_SO_KEEPIDLE == optionName) && (NETCONN_TCP == conn->type) && (conn->pcb.tcp != NULL))
+    {
+        conn->pcb.tcp->keep_idle = (*(int*)optionValue) * 1000;
+    }
+    else  if ((PAL_SO_KEEPINTVL == optionName) && (NETCONN_TCP == conn->type) && (conn->pcb.tcp != NULL))
+    {
+        conn->pcb.tcp->keep_intvl = (*(int*)optionValue) * 1000;
+    }
+
+#endif
+
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+#ifdef LWIP_SO_SNDTIMEO
+    else if (PAL_SO_SNDTIMEO == optionName)
+    {
+		netconn_set_sendtimeout(conn, *((const int *)optionValue));
+    }
+#endif
+#ifdef LWIP_SO_RCVTIMEO
+    else if (PAL_SO_RCVTIMEO == optionName)
+    {
+		netconn_set_recvtimeout(conn, *((const int *)optionValue));
+    }
+#endif
+    else
+    {
+        result = PAL_ERR_SOCKET_OPTION_NOT_SUPPORTED;
+    }
+    return result;
+}
+
+palStatus_t pal_plat_isNonBlocking(palSocket_t socket, bool* isNonBlocking)
+{
+    struct netconn* conn = NULL;
+    if (NULL == socket) // NULL is not a vlaid socket.
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    conn = ((palLwipNetConnInfo_t*)socket)->connection;
+    
+    if (netconn_is_nonblocking(conn))
+    {
+        *isNonBlocking = true;
+    }
+    else
+    {
+        *isNonBlocking = false;
+    }
+    return PAL_SUCCESS;
+
+}
+
+
+palStatus_t pal_plat_bind(palSocket_t socket, palSocketAddress_t* myAddress, palSocketLength_t addressLength)
+{
+    int result = PAL_SUCCESS;
+    struct netconn* conn = NULL;
+    err_t error = 0;
+    palIpV4Addr_t ipv4 = {0};
+    uint16_t port = 0;
+    if (NULL == socket) // NULL is not a vlaid socket.
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    conn = ((palLwipNetConnInfo_t*)socket)->connection;
+
+
+    result = pal_getSockAddrIPV4Addr(myAddress, ipv4);
+    if (PAL_SUCCESS == result)
+    {
+        result = pal_getSockAddrPort(myAddress, &port);
+        if (PAL_SUCCESS == result)
+        {
+
+            error = netconn_bind(conn, (ip_addr_t *)ipv4, port);
+            if (ERR_OK != error)
+            {
+                result = translateErrnoToPALError(error);
+            }
+        }
+    }
+    
+    return result;
+}
+
+
+palStatus_t pal_plat_receiveFrom(palSocket_t socket, void* buffer, size_t length, palSocketAddress_t* from, palSocketLength_t* fromLength, size_t* bytesReceived)
+{
+    int result = PAL_SUCCESS;
+    struct netbuf *newBuf = NULL;
+    palLwipNetConnInfo_t* socketInfo = (palLwipNetConnInfo_t*)socket;
+    struct netconn* conn = NULL;
+    struct ip_addr* fromAddr;
+    unsigned short fromPort;
+    size_t bufferLength = 0;
+    *bytesReceived = 0;
+    if (NULL == socket) // NULL is not a vlaid socket.
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    conn = socketInfo->connection;
+
+
+    if (NULL != socketInfo->buffer)
+    {
+        newBuf = socketInfo->buffer;
+        result = ERR_OK;
+    }
+    else
+    {
+    	result = pal_plat_netconReceive(conn, &newBuf);
+        if (ERR_OK != result) // Receive data
+        {
+            result = translateErrnoToPALError(result);
+        }
+    }
+
+    if ((ERR_OK == result) &&(NULL != newBuf) )
+    {
+            
+        bufferLength = netbuf_len(newBuf);
+        if (bufferLength <= length)
+        {
+            netbuf_copy(newBuf, buffer, bufferLength);
+            *bytesReceived = bufferLength;
+        }
+        else // more data recieved than buffer
+        {
+            netbuf_copy(newBuf, buffer, length);
+            *bytesReceived = length; 
+        }
+        if (NULL != from)
+        {
+            fromAddr = netbuf_fromaddr(newBuf);
+            fromPort = netbuf_fromport(newBuf);
+            result = pal_setSockAddrIPV4Addr(from, *((palIpV4Addr_t*)fromAddr));
+            if (PAL_SUCCESS == result)
+            {
+                result = pal_setSockAddrPort(from, fromPort);
+                if ((PAL_SUCCESS == result) && (NULL != fromLength))
+                {
+                    *fromLength = PAL_IPV4_ADDRESS_SIZE;
+                }
+            }   
+        }
+    }
+    else if(ERR_OK == result)// if we got NULL this means the conneciton was closed
+    {
+        if (NULL != fromLength)
+        {
+            *fromLength = 0;
+        }
+        result = PAL_ERR_SOCKET_CONNECTION_CLOSED;
+    }
+
+    if (NULL != socketInfo->buffer)
+    {
+        socketInfo->buffer = NULL;
+        socketInfo->offset = 0;
+        // deleted below through newBuf
+    }
+   
+    if (NULL !=newBuf )
+        netbuf_delete(newBuf);
+    return result;
+
+}
+
+palStatus_t pal_plat_sendTo(palSocket_t socket, const void* buffer, size_t length, const palSocketAddress_t* to, palSocketLength_t toLength, size_t* bytesSent)
+{
+    int result = 0;
+    struct netconn* conn = NULL;
+    struct netbuf *localNetbuf;
+    struct ip_addr toAddr;
+    palIpV4Addr_t ipv4;
+    unsigned short toPort;
+    *bytesSent = 0;
+    if (NULL == socket) // NULL is not a vlaid socket.
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    conn = ((palLwipNetConnInfo_t*)socket)->connection;
+
+    // netconn documentaiton (http://www.ece.ualberta.ca/~cmpe401/docs/lwip.pdf) says buffers over the size of the MTU should nto be sent. since this isn not always known 1000bytes is a good heuristic
+    
+    
+    if (length > PAL_MAX_SEND_BUFFER_SIZE)
+    {
+        result = PAL_ERR_SOCKET_SEND_BUFFER_TOO_BIG;
+        goto finish;
+    }
+
+    localNetbuf = netbuf_new();
+    if (NULL == localNetbuf)
+    {
+        result = PAL_ERR_NO_MEMORY;
+        goto finish;
+    }
+
+    result = netbuf_ref(localNetbuf, buffer, length);
+    if (PAL_SUCCESS == result)
+    {
+        result = pal_getSockAddrPort(to, &toPort);
+        if (PAL_SUCCESS == result)
+        {
+            result = pal_getSockAddrIPV4Addr(to, ipv4);
+            if (PAL_SUCCESS == result)
+            {
+                toAddr.addr = ipv4[0] | (ipv4[1] << 8) | (ipv4[2] << 16) | (ipv4[3] << 24);
+
+                result = netconn_connect(conn, &toAddr, toPort);
+                if (ERR_OK == result)
+                {
+                    result = netconn_send(conn, localNetbuf);
+                    if (ERR_OK != result)
+                    {
+                        result = translateErrnoToPALError(result);
+                    }
+                }
+                else
+                {
+                    result = translateErrnoToPALError(result);
+                }
+            }
+        }
+    }
+
+    netbuf_delete(localNetbuf);
+    *bytesSent = length;
+
+finish:
+
+    return result;
+}
+
+palStatus_t pal_plat_close(palSocket_t* socket)
+{
+    int result = 0;
+    palLwipNetConnInfo_t* socketInfo = NULL;
+    struct netconn* conn = NULL;
+    
+    if (NULL == *socket) // socket already closed - return success.
+    {
+        PAL_LOG(DBG, "socket close called on socket which was already closed");
+        return PAL_SUCCESS;
+    }
+    socketInfo = (palLwipNetConnInfo_t*)*socket;
+    conn = socketInfo->connection;
+    if (NETCONN_TCP == conn->type)
+    {
+        result = netconn_close(conn);
+        if (ERR_OK == result)
+        {
+           
+            *socket = NULL;
+        }
+        else 
+        {
+            result = translateErrnoToPALError(result);
+        }
+    }
+    else
+    {
+        *socket = NULL;
+    }
+
+    socketInfo->inUse = false;
+    socketInfo->offset = 0;
+    socketInfo->connection = NULL;
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+    socketInfo->callback = NULL;
+#endif
+    if (NULL != socketInfo->buffer )
+    {
+        netbuf_delete(socketInfo->buffer);
+    socketInfo->buffer = NULL;
+    }
+    netconn_delete(conn);
+    return result;
+}
+
+palStatus_t pal_plat_getNumberOfNetInterfaces( uint32_t* numInterfaces)
+{
+    *numInterfaces = s_pal_numberOFInterfaces;
+    return PAL_SUCCESS;
+}
+
+palStatus_t pal_plat_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t * interfaceInfo)
+{
+    palStatus_t result = PAL_SUCCESS;
+
+    uint16_t port = 0;
+    uint32_t numInterfaces = 0;
+
+    result = pal_plat_getNumberOfNetInterfaces(&numInterfaces);
+    if (PAL_SUCCESS != result)
+    {
+        return result;
+    }
+    if (interfaceNum == -1) // default interface number is 0;
+    {
+    interfaceNum = 0;
+    }
+    if (interfaceNum <numInterfaces) // only "default" interface supported at this point
+    {
+        struct netif* fsl_netif0 = (struct netif*)s_pal_networkInterfacesSupported[interfaceNum] ;
+        result = pal_setSockAddrIPV4Addr(&interfaceInfo->address, *((palIpV4Addr_t*)&(fsl_netif0->ip_addr.addr)));
+        if (PAL_SUCCESS == result)
+        {
+            result = pal_setSockAddrPort(&interfaceInfo->address, port);
+        }
+    }
+
+    return result;
+}
+
+typedef struct palSocketSelectInfo
+{
+    struct netconn * connection;
+    uint32_t selectStatus;
+} palSocketSelectInfo_t;
+
+PAL_PRIVATE palSocketSelectInfo_t s_select_state[PAL_NET_SOCKET_SELECT_MAX_SOCKETS] ;
+PAL_PRIVATE palSemaphoreID_t s_palSelectSemaphore = 0;
+//static bool s_palSelectSemaphoreInited = false;
+
+void palNetConSelectCallback(struct netconn * connection, enum netconn_evt event, u16_t len)
+{
+    uint32_t index = 0;
+#ifdef PAL_NET_ASYNCHRONOUS_SOCKET_API
+    for (index = 0; index < MEMP_NUM_NETCONN; index++)
+    {
+        if ((palInternalSocketInfo[index].inUse) && (palInternalSocketInfo[index].connection == connection) && (NULL != palInternalSocketInfo[index].callback))
+        {
+            palInternalSocketInfo[index].callback(palInternalSocketInfo[index].callbackArgument);
+            break;
+        }
+    }
+#endif
+    for (index = 0; index < PAL_NET_SOCKET_SELECT_MAX_SOCKETS; index++)
+    {
+        if (connection == s_select_state[index].connection)
+        {
+            s_select_state[index].selectStatus = 1; // add different flag per event.
+            /*
+            NETCONN_EVT_RCVPLUS,
+            NETCONN_EVT_RCVMINUS,
+            NETCONN_EVT_SENDPLUS,
+            NETCONN_EVT_SENDMINUS,
+            NETCONN_EVT_ERROR
+            */
+            break;
+        }
+    }
+    pal_osSemaphoreRelease(s_palSelectSemaphore);
+}
+
+
+#if PAL_NET_TCP_AND_TLS_SUPPORT // functionality below supported only in case TCP is supported.
+
+
+palStatus_t pal_plat_listen(palSocket_t socket, int backlog)
+{
+    palStatus_t result = PAL_SUCCESS;
+    struct netconn* conn = NULL;    
+    if (NULL == socket) // NULL is not a valid socket.
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    conn = ((palLwipNetConnInfo_t*)socket)->connection;
+    result = netconn_listen_with_backlog(conn, backlog);
+    if (ERR_OK != result )
+    {
+        result = translateErrnoToPALError(result);
+    }
+    return result;
+}
+
+
+palStatus_t pal_plat_accept(palSocket_t socket, palSocketAddress_t * address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket)
+{
+    palStatus_t result = PAL_SUCCESS;
+    struct netconn * new_conn = NULL;
+    ip_addr_t addr;
+    uint16_t port;
+    palLwipNetConnInfo_t* socketInfo = NULL;
+    uint32_t index = 0;
+    struct netconn* conn = NULL;
+    if (NULL == socket) // NULL is not a vlaid socket.
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    conn = ((palLwipNetConnInfo_t*)socket)->connection;
+
+
+
+    for (index = 0; index < MEMP_NUM_NETCONN; index++) // allocate socket info structure.
+    {
+        if (false == palInternalSocketInfo[index].inUse)
+        {
+            palInternalSocketInfo[index].inUse = true;
+            socketInfo = &palInternalSocketInfo[index];
+            break;
+        }
+    }
+    if (NULL == socketInfo)
+     {
+        result = PAL_ERR_NO_MEMORY;
+    }
+    else
+    {
+        result = netconn_accept(conn, &new_conn);
+        if (ERR_OK != result)
+        {
+            palInternalSocketInfo[index].inUse = false; // free resource since accept failed
+            result =  translateErrnoToPALError(result);
+        }
+        else
+        {
+
+            socketInfo->connection = new_conn;
+            socketInfo->callback = NULL;
+            socketInfo->buffer = NULL;
+            *acceptedSocket = (palSocket_t)socketInfo;
+
+            result = netconn_getaddr(new_conn, &addr, &port, 0);
+            if (ERR_OK != result) // failed to get peer address
+            {
+                result = translateErrnoToPALError(result);
+            }
+            else
+            {
+                result = pal_setSockAddrIPV4Addr(address, *((palIpV4Addr_t*)&(addr.addr)));
+                if (result == PAL_SUCCESS)
+                {
+                    pal_setSockAddrPort(address, port);
+                    if (result == PAL_SUCCESS)
+                    {
+                        *addressLen = PAL_IPV6_ADDRESS_SIZE;
+                    }
+                }
+            }
+        }
+    }
+    return result;
+}
+
+
+palStatus_t pal_plat_connect(palSocket_t socket, const palSocketAddress_t* address, palSocketLength_t addressLen)
+{
+    int result = 0;
+    palIpV4Addr_t ipv4;
+    uint16_t port;
+    ip_addr_t netconn_address = {0};
+    struct netconn* conn = NULL;
+    if (NULL == socket) // NULL is not a vlaid socket.
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    conn = ((palLwipNetConnInfo_t*)socket)->connection;
+
+
+    if ((NETCONN_TCP == conn->type) && (conn->pcb.tcp != NULL)) // only TRY to connect if socket state is 0.(closed)
+    {
+        if ((conn->pcb.tcp->state >= 4))//TCP state 4 and above is conn ESTABLISHED or connected
+        {
+            result = PAL_ERR_SOCKET_ALREADY_CONNECTED;
+        }
+        else if (conn->pcb.tcp->state > 0)//TCP state 1 and above is connecting
+        {
+            result = PAL_ERR_SOCKET_IN_PROGRES;
+        }
+        else // socket is not connect or connecting - try to connect.
+        {
+            result = pal_getSockAddrIPV4Addr(address, ipv4);
+            if (PAL_SUCCESS != result)
+                return result;
+            result = pal_getSockAddrPort(address, &port);
+            if (PAL_SUCCESS != result)
+                return result;
+            netconn_address.addr = ipv4[0] | (ipv4[1] << 8) | (ipv4[2] << 16) | (ipv4[3] << 24);
+
+            result = netconn_connect(conn, &netconn_address, port);
+            if (ERR_OK != result) // failed to get peer address
+            {
+                result = translateErrnoToPALError(result);
+            }
+        }
+    }
+else 
+{
+    result = PAL_ERR_INVALID_ARGUMENT;
+}
+
+    return result;
+}
+
+
+
+palStatus_t pal_plat_recv(palSocket_t socket, void *buf, size_t len, size_t* recievedDataSize)
+{
+    int result = 0;
+    struct netbuf *newBuf = NULL;
+    palLwipNetConnInfo_t* socketInfo = (palLwipNetConnInfo_t*)socket;
+    size_t bufferSize = 0;
+    struct netconn* conn = NULL;
+    if (NULL == socket) // NULL is not a vlaid socket.
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    conn = ((palLwipNetConnInfo_t*)socket)->connection;
+
+
+    if (NULL != socketInfo->buffer) // part of previous buffer not read yet.
+    {
+        uint32_t copied = netbuf_copy_partial(socketInfo->buffer, buf, (u16_t)len, socketInfo->offset);
+        socketInfo->offset += copied;
+        *recievedDataSize = copied;
+    }
+    else 
+    {
+    	result = pal_plat_netconReceive(conn, &newBuf);
+        if (ERR_OK != result) 
+        {
+              return translateErrnoToPALError(result);
+        }
+        else
+        {
+	        if (NULL != newBuf)
+            {
+		        socketInfo->buffer = newBuf;
+                bufferSize = netbuf_len(newBuf);
+
+                if (bufferSize <= len)
+                { 
+                      *recievedDataSize = bufferSize;
+                      netbuf_copy(newBuf, buf, bufferSize);
+                      socketInfo->offset = bufferSize;
+                 }
+                 else
+                 {
+                     *recievedDataSize = len;
+                     netbuf_copy(newBuf, buf, len);
+                     socketInfo->offset = len;
+                }
+         }
+         else
+         {
+             result = PAL_ERR_SOCKET_CONNECTION_CLOSED;
+         }
+        
+        }
+    }
+    if ((NULL != socketInfo->buffer) && (socketInfo->offset >= netbuf_len( socketInfo->buffer)))
+    {
+        netbuf_delete(socketInfo->buffer);
+        socketInfo->buffer = NULL;
+        socketInfo->offset = 0;
+    }
+    
+    return result;
+}
+
+
+palStatus_t pal_plat_send(palSocket_t socket, const void *buf, size_t len, size_t* sentDataSize)
+{
+    int result = 0;
+    size_t localSent;
+    size_t* actualSent = sentDataSize;
+     struct netconn* conn = NULL;
+    if (NULL == socket) // NULL is not a vlaid socket.
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    conn = ((palLwipNetConnInfo_t*)socket)->connection;
+    
+    if (NULL == actualSent)
+    {
+    actualSent =  &localSent;
+    }
+
+    // netconn documentaiton (http://www.ece.ualberta.ca/~cmpe401/docs/lwip.pdf) says buffers over the size of the MTU should not be sent.since this is not always known 1000bytes is a good heuristic
+    if (len > PAL_MAX_SEND_BUFFER_SIZE)
+    {
+        return PAL_ERR_SOCKET_SEND_BUFFER_TOO_BIG;
+    }
+    result = netconn_write_partly(conn, buf, len, NETCONN_COPY, actualSent);
+    if (ERR_OK != result )
+    {
+        result = translateErrnoToPALError(result);
+    }
+    else
+    {
+        *sentDataSize = len;
+    }
+
+    return result;
+}
+
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+
+palStatus_t pal_plat_asynchronousSocket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void* callbackArgument, palSocket_t* socket)
+{
+
+    int result = PAL_SUCCESS;
+    uint32_t index = 0;
+    palLwipNetConnInfo_t* socketInfo = NULL;
+    if (domain != PAL_AF_INET)
+        return PAL_ERR_NOT_IMPLEMENTED;
+    enum netconn_type connType = NETCONN_INVALID;
+    if ((PAL_SOCK_STREAM == type) || (PAL_SOCK_STREAM_SERVER == type))
+    {
+        connType = NETCONN_TCP;
+    }
+    else if (PAL_SOCK_DGRAM == type)
+    {
+        connType = NETCONN_UDP;
+    }
+    else
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    for (index = 0; index < MEMP_NUM_NETCONN; index++) // allocate socket info structure.
+    {
+        if (false == palInternalSocketInfo[index].inUse)
+        {
+            palInternalSocketInfo[index].inUse = true;
+            palInternalSocketInfo[index].connection = NULL;
+            palInternalSocketInfo[index].callback = callback;
+            palInternalSocketInfo[index].callbackArgument = callbackArgument;
+            socketInfo = &palInternalSocketInfo[index];
+            break;
+        }
+    }
+   if (NULL == socketInfo)
+   {
+     result = PAL_ERR_NO_MEMORY;
+   }
+
+    else
+    {
+        struct netconn * con = netconn_new_with_callback(connType, palNetConAsyncCallback);
+        if (NULL == con)
+        {
+            result = PAL_ERR_NO_MEMORY;
+        }
+        else
+        {
+        socketInfo->connection = con;
+         socketInfo->buffer = NULL;
+            // TODO(nirson01) : add binding to specific network interface  (interfaceNum)
+            if (nonBlockingSocket)
+            {
+                netconn_set_nonblocking(con, 1);
+            }
+            *socket = (palSocket_t)socketInfo;
+        }
+    }
+
+    
+
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastrucature is finalized)
+}
+
+#endif
+
+
+
+#if PAL_NET_DNS_SUPPORT
+
+palStatus_t pal_plat_getAddressInfo(const char *url, palSocketAddress_t *address, palSocketLength_t* length)
+{
+    
+    palStatus_t result = PAL_SUCCESS;
+    ip_addr_t addr = {0};
+
+ // placeholder: no real ip filderting for DNS is lwip 1.4.1 (should be implmeneted in lwip 2).
+#if PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_ANY
+    result = netconn_gethostbyname(url, &addr);
+#elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV4_ONLY
+    result = netconn_gethostbyname(url, &addr);
+#elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV6_ONLY
+    #error ipv6 filter not supported for lwip 1.4.1
+#else 
+#error PAL_NET_DNS_IP_SUPPORT is not defined to a valid value.
+#endif
+
+    if (ERR_OK != result)
+    {
+        result =  translateErrnoToPALError(result);
+    }
+    else
+    {
+        if (0 == addr.addr ) // invalid 0 address
+        {
+            result = PAL_ERR_SOCKET_DNS_ERROR;
+        }
+        else
+        {
+            result = pal_setSockAddrIPV4Addr(address, *(palIpV4Addr_t*)&addr);
+            if (PAL_SUCCESS == result)
+            {
+                result = pal_setSockAddrPort(address, 0); // we have no port fo the lookup -  zero it to avoif mistakes.
+                *length = PAL_NET_MAX_ADDR_SIZE;
+            }
+        }
+    }
+    return result;
+    
+}
+
+#endif
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/RTOS/pal_plat_rtos.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,891 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+/* PAL-RTOS porting for FreeRTOS-8.1.2
+*  This is porting code for PAL RTOS APIS for 
+*  FreeRTOS-8.1.2 version.
+*/
+
+#include "board.h"
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "semphr.h"
+#include "task.h"
+
+
+#include "pal.h"
+#include "pal_plat_rtos.h"
+#include <stdlib.h>
+
+
+#define PAL_RTOS_TRANSLATE_CMSIS_ERROR_CODE(cmsisCode)\
+    ((int32_t)(cmsisCode + PAL_ERR_RTOS_ERROR_BASE))
+
+#define PAL_TICK_TO_MILLI_FACTOR 1000
+
+extern palStatus_t pal_plat_getRandomBufferFromHW(uint8_t *randomBuf, size_t bufSizeBytes, size_t* actualRandomSizeBytes);
+
+/////////////////////////STATIC FUNCTION///////////////////////////
+/*! Get IPSR Register
+*
+* @param[in] Void
+* \returns uint32 - the content of the IPSR Register.
+*
+*/
+PAL_PRIVATE PAL_INLINE uint32_t pal_plat_GetIPSR(void);
+/////////////////////////END STATIC FUNCTION///////////////////////////
+
+//! Timer structure
+typedef struct palTimer{
+	palTimerID_t            timerID;
+	//    uint32_t                internalTimerData[PAL_TIMER_DATA_SIZE];  ///< pointer to internal data
+	TimerCallbackFunction_t function;
+	void*                   functionArgs;
+	uint32_t                timerType;
+} palTimer_t;
+
+//! Mutex structure
+typedef struct palMutex{
+	palMutexID_t            mutexID;
+}palMutex_t;
+
+//! Semaphore structure
+typedef struct palSemaphore{
+	palSemaphoreID_t        semaphoreID;
+	uint32_t                maxCount;
+}palSemaphore_t;
+
+typedef struct palThreadData
+{
+    palThreadFuncPtr userFunction;
+    void* userFunctionArgument;
+    TaskHandle_t sysThreadID;
+} palThreadData_t;
+
+#define PAL_MAX_CONCURRENT_THREADS 20
+
+PAL_PRIVATE palMutexID_t g_threadsMutex = NULLPTR;
+PAL_PRIVATE palThreadData_t* g_threadsArray[PAL_MAX_CONCURRENT_THREADS] = { 0 };
+
+#define PAL_THREADS_MUTEX_LOCK(status) \
+    { \
+        status = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); \
+        if (PAL_SUCCESS != status)\
+        { \
+            PAL_LOG(ERR, "%s mutex wait failed\n", __FUNCTION__); \
+        } \
+    }
+
+#define PAL_THREADS_MUTEX_UNLOCK(status) \
+    { \
+        status = pal_osMutexRelease(g_threadsMutex); \
+        if (PAL_SUCCESS != status)\
+        { \
+            PAL_LOG(ERR, "%s mutex release failed\n", __FUNCTION__); \
+        } \
+    }
+
+PAL_PRIVATE void threadFree(palThreadData_t** threadData);
+
+PAL_PRIVATE PAL_INLINE uint32_t pal_plat_GetIPSR(void)
+{
+	uint32_t result;
+
+#if defined (__CC_ARM)
+	__asm volatile
+	{
+		MRS result, ipsr
+	}
+#elif defined (__GNUC__)
+	__asm volatile ("MRS %0, ipsr" : "=r" (result) );
+#endif
+
+	return(result);
+}
+
+palStatus_t pal_plat_RTOSInitialize(void* opaqueContext)
+{
+    palStatus_t status = pal_osMutexCreate(&g_threadsMutex);
+    if (PAL_SUCCESS != status)
+    {
+        goto end;
+    }
+
+    PAL_THREADS_MUTEX_LOCK(status);
+    if (PAL_SUCCESS != status)
+    {
+        goto end;
+    }
+    for (int i = 0; i < PAL_MAX_CONCURRENT_THREADS; i++)
+    {
+        if (g_threadsArray[i])
+        {
+            threadFree(&g_threadsArray[i]);
+        }
+    }
+    PAL_THREADS_MUTEX_UNLOCK(status);
+    if (PAL_SUCCESS != status)
+    {
+        goto end;
+    }
+#if (PAL_USE_HW_RTC)
+    if (PAL_SUCCESS == status)
+    {
+        status = pal_plat_rtcInit();        
+    }
+#endif
+end:
+    return status;
+}
+
+palStatus_t pal_plat_RTOSDestroy(void)
+{
+    palStatus_t status = PAL_SUCCESS;
+    if (NULLPTR != g_threadsMutex)
+    {
+        status = pal_osMutexDelete(&g_threadsMutex);
+        g_threadsMutex = NULLPTR;
+    }
+#if (PAL_USE_HW_RTC)
+    if (PAL_SUCCESS == status)
+    {
+        status = pal_plat_rtcDeInit();
+    }
+#endif
+	return status;
+}
+
+palStatus_t pal_plat_osDelay(uint32_t milliseconds)
+{
+	vTaskDelay(milliseconds / portTICK_PERIOD_MS);
+	return PAL_SUCCESS;
+}
+
+
+uint64_t pal_plat_osKernelSysTick()
+{
+
+	uint64_t result;
+	if (pal_plat_GetIPSR() != 0)
+	{
+		result = xTaskGetTickCountFromISR();
+	}
+	else
+	{
+		result = xTaskGetTickCount();
+	}
+	return result;
+}
+
+uint64_t pal_plat_osKernelSysTickMicroSec(uint64_t microseconds)
+{
+	uint64_t sysTicks = microseconds * configTICK_RATE_HZ / (PAL_TICK_TO_MILLI_FACTOR * PAL_TICK_TO_MILLI_FACTOR);
+	return sysTicks;
+}
+
+uint64_t pal_plat_osKernelSysTickFrequency()
+{
+	return configTICK_RATE_HZ;
+}
+
+PAL_PRIVATE PAL_INLINE palThreadData_t** threadAllocate(void)
+{
+    palThreadData_t** threadData = NULL;
+    for (int i = 0; i < PAL_MAX_CONCURRENT_THREADS; i++)
+    {
+        if (!g_threadsArray[i])
+        {
+            g_threadsArray[i] = (palThreadData_t*)calloc(1, sizeof(palThreadData_t));
+            if (g_threadsArray[i])
+            {
+                threadData = &g_threadsArray[i];
+            }
+            break;
+        }
+    }
+    return threadData;
+}
+
+PAL_PRIVATE void threadFree(palThreadData_t** threadData)
+{
+    (*threadData)->userFunction = NULL;
+    (*threadData)->userFunctionArgument = NULL;
+    (*threadData)->sysThreadID = NULL;
+    free(*threadData);
+    *threadData = NULL;
+}
+
+PAL_PRIVATE palThreadData_t** threadFind(const TaskHandle_t sysThreadID)
+{
+    palThreadData_t** threadData = NULL;
+    for (int i = 0; i < PAL_MAX_CONCURRENT_THREADS; i++)
+    {
+        if (sysThreadID == g_threadsArray[i]->sysThreadID)
+        {
+            threadData = &g_threadsArray[i];
+            break;
+        }
+    }
+    return threadData;
+}
+
+PAL_PRIVATE void threadFunction(void* arg)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palThreadData_t** threadData;
+    palThreadFuncPtr userFunction;
+    void* userFunctionArgument;
+    
+    PAL_THREADS_MUTEX_LOCK(status);
+    if (PAL_SUCCESS != status)
+    {
+        goto end;
+    }
+    threadData = (palThreadData_t**)arg;
+    userFunction = (*threadData)->userFunction;
+    userFunctionArgument = (*threadData)->userFunctionArgument;
+    if (NULL == (*threadData)->sysThreadID) // maybe null if this thread has a higher priority than the thread which created this thread
+    {
+        (*threadData)->sysThreadID = xTaskGetCurrentTaskHandle(); // set the thread id
+    }    
+    PAL_THREADS_MUTEX_UNLOCK(status);
+    if (PAL_SUCCESS != status)
+    {
+        goto end;
+    }
+    
+    userFunction(userFunctionArgument); // invoke user function with user argument (use local vars) - note we're not under mutex lock anymore
+    
+    PAL_THREADS_MUTEX_LOCK(status);
+    if (PAL_SUCCESS != status)
+    {
+        goto end;
+    }
+    threadFree(threadData); // clean up
+    PAL_THREADS_MUTEX_UNLOCK(status)
+end:
+    vTaskDelete(NULL);
+}
+
+palStatus_t pal_plat_osThreadCreate(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, palThreadID_t* threadID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palThreadData_t** threadData;
+    TaskHandle_t sysThreadID = NULLPTR;    
+
+    PAL_THREADS_MUTEX_LOCK(status);
+    if (PAL_SUCCESS != status)
+    {
+        goto end;
+    }
+    threadData = threadAllocate(); // allocate thread data from the global array
+    PAL_THREADS_MUTEX_UNLOCK(status);
+    if (PAL_SUCCESS != status)
+    {
+        goto end;
+    }
+
+    if (NULL == threadData) // allocation failed or all array slots are occupied
+    {
+        status = PAL_ERR_RTOS_RESOURCE;
+        goto end;
+    }
+
+    (*threadData)->userFunction = function; // note that threadData is safe here (eventhough it's not mutex locked), no other thread will attempt to change it until the thread is either finished or terminated
+    (*threadData)->userFunctionArgument = funcArgument;
+    
+    //Note: the stack in this API is handled as an array of "StackType_t" which can be of different sizes for different ports.
+    //      in this specific port of (8.1.2) the "StackType_t" is defined to 4-bytes this is why we divide the "stackSize" parameter by "sizeof(uint32_t)".
+    //      inside freeRTOS code, the stack size is calculated according to the following formula: "((size_t)usStackDepth) * sizeof(StackType_t)"
+    //       where "usStackDepth" is equal to "stackSize / sizeof(uint32_t)"
+    BaseType_t result = xTaskGenericCreate((TaskFunction_t)threadFunction,
+        "palTask",
+        (stackSize / sizeof(uint32_t)),
+        threadData,
+        (int16_t)priority,
+        &sysThreadID,
+        NULL, //if stack pointer is NULL then allocate the stack according to stack size
+        NULL);
+
+    PAL_THREADS_MUTEX_LOCK(status);
+    if (PAL_SUCCESS != status)
+    {
+        goto end;
+    }
+    if (pdPASS == result)
+    {        
+        if ((NULL != *threadData) && (NULL == (*threadData)->sysThreadID)) // *threadData maybe null in case the thread has already finished and cleaned up, sysThreadID maybe null if the created thread is lower priority than the creating thread
+        {
+            (*threadData)->sysThreadID = sysThreadID; // set the thread id
+        }
+        *threadID = (palThreadID_t)sysThreadID;
+    }   
+    else
+    {
+        threadFree(threadData); // thread creation failed so clean up dynamic allocations etc.
+        status = PAL_ERR_GENERIC_FAILURE;
+    }
+    PAL_THREADS_MUTEX_UNLOCK(status);
+end:
+    return status;
+}
+
+palThreadID_t pal_plat_osThreadGetId(void)
+{
+    palThreadID_t threadID = (palThreadID_t)xTaskGetCurrentTaskHandle();
+    return threadID;
+}
+
+palStatus_t pal_plat_osThreadTerminate(palThreadID_t* threadID)
+{
+    palStatus_t status = PAL_ERR_RTOS_TASK;
+    TaskHandle_t sysThreadID = (TaskHandle_t)*threadID;
+    palThreadData_t** threadData;
+    if (xTaskGetCurrentTaskHandle() != sysThreadID) // self termination not allowed
+    {
+        PAL_THREADS_MUTEX_LOCK(status);
+        if (PAL_SUCCESS != status)
+        {
+            goto end;
+        }
+        threadData = threadFind(sysThreadID);
+        if (threadData) // thread may have ended or terminated already
+        {
+            vTaskDelete(sysThreadID);
+            threadFree(threadData);
+        }
+        PAL_THREADS_MUTEX_UNLOCK(status);        
+    }
+end:
+    return status;
+}
+
+PAL_PRIVATE palTimer_t* s_timerArrays[PAL_MAX_NUM_OF_TIMERS] = {0};
+
+PAL_PRIVATE void pal_plat_osTimerWarpperFunction( TimerHandle_t xTimer )
+{
+	int i;
+	palTimer_t* timer = NULL;
+	for(i=0 ; i< PAL_MAX_NUM_OF_TIMERS ; i++)
+	{
+		if (s_timerArrays[i]->timerID == (palTimerID_t)xTimer)
+		{
+			timer = s_timerArrays[i];
+			timer->function(timer->functionArgs);
+
+		}
+	}
+}
+
+palStatus_t pal_plat_osTimerCreate(palTimerFuncPtr function, void* funcArgument, palTimerType_t timerType, palTimerID_t* timerID)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTimer_t* timer = NULL;
+	int i;
+	if(NULL == timerID || NULL == function)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	timer = (palTimer_t*)malloc(sizeof(palTimer_t));
+
+	if (NULL == timer)
+	{
+		status = PAL_ERR_NO_MEMORY;
+	}
+	else
+	{
+		memset(timer,0,sizeof(palTimer_t));
+	}
+
+	if (PAL_SUCCESS == status)
+	{
+		for (i=0; i< PAL_MAX_NUM_OF_TIMERS; i++)
+		{
+			if (s_timerArrays[i] == NULL)
+			{
+				s_timerArrays[i] = timer;
+				break;
+			}
+		}
+		if (PAL_MAX_NUM_OF_TIMERS == i)
+		{
+			status = PAL_ERR_NO_MEMORY;
+		}
+		if (PAL_SUCCESS == status)
+		{
+			timer->function = (TimerCallbackFunction_t)function;
+			timer->functionArgs = funcArgument;
+			timer->timerType = timerType;
+
+			timer->timerID = (palTimerID_t)xTimerCreate(
+					"timer",
+					1, // xTimerPeriod - cannot be '0'
+					(const TickType_t)timerType, // 0 = osTimerOnce, 1 = osTimerPeriodic
+					NULL,
+					(TimerCallbackFunction_t)pal_plat_osTimerWarpperFunction
+			);
+		}
+		if (NULLPTR == timer->timerID)
+		{
+			free(timer);
+			timer = NULLPTR;
+			PAL_LOG(ERR, "Rtos timer create failure");
+			status = PAL_ERR_GENERIC_FAILURE;
+		}
+		else
+		{
+			*timerID = (palTimerID_t)timer;
+		}
+	}
+	return status;
+}
+
+palStatus_t pal_plat_osTimerStart(palTimerID_t timerID, uint32_t millisec)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTimer_t* timer = NULL;
+
+	if (NULLPTR == timerID)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	timer = (palTimer_t*)timerID;
+
+	if (pal_plat_GetIPSR() != 0)
+	{
+		BaseType_t pxHigherPriorityTaskWoken;
+		status = xTimerChangePeriodFromISR(
+				(TimerHandle_t)(timer->timerID),
+				(millisec / portTICK_PERIOD_MS),
+				&pxHigherPriorityTaskWoken
+		);
+	}
+	else
+	{
+		status =  xTimerChangePeriod((TimerHandle_t)(timer->timerID), (millisec / portTICK_PERIOD_MS), 0);
+	}
+
+	if (pdPASS != status)
+	{
+		status =  PAL_ERR_RTOS_PARAMETER;
+	}
+	if (pdPASS == status)
+	{
+		if (pal_plat_GetIPSR() != 0)
+		{
+			BaseType_t pxHigherPriorityTaskWoken;
+			status = xTimerStartFromISR((TimerHandle_t)(timer->timerID), &pxHigherPriorityTaskWoken);
+		}
+		else
+		{
+			status = xTimerStart((TimerHandle_t)(timer->timerID), 0);
+		}
+
+		if (pdPASS != status)
+		{
+			status =  PAL_ERR_RTOS_PARAMETER;
+		}
+		else
+		{
+			status = PAL_SUCCESS;
+		}
+	}
+	return status;
+}
+
+palStatus_t pal_plat_osTimerStop(palTimerID_t timerID)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palTimer_t* timer = NULL;
+
+	if(NULLPTR == timerID)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	timer = (palTimer_t*)timerID;
+
+	if (pal_plat_GetIPSR() != 0)
+	{
+		BaseType_t pxHigherPriorityTaskWoken;
+		status = xTimerStopFromISR((TimerHandle_t)(timer->timerID), &pxHigherPriorityTaskWoken);
+	}
+	else
+	{
+		status = xTimerStop((TimerHandle_t)(timer->timerID), 0);
+	}
+
+
+	if (pdPASS != status)
+	{
+		status = PAL_ERR_RTOS_PARAMETER;
+	}
+	else
+	{
+		status = PAL_SUCCESS;
+	}
+	return status;
+}
+
+palStatus_t pal_plat_osTimerDelete(palTimerID_t* timerID)
+{
+	palStatus_t status = PAL_ERR_RTOS_PARAMETER;
+	palTimer_t* timer = NULL;
+	int i;
+
+	if(NULL == timerID || NULLPTR == *timerID)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	timer = (palTimer_t*)*timerID;
+
+	if (timer->timerID)
+	{
+		for(i=0 ; i< PAL_MAX_NUM_OF_TIMERS ; i++)
+		{
+			if (s_timerArrays[i] == timer)
+			{
+				status = xTimerDelete((TimerHandle_t)(timer->timerID), 0);
+				free(timer);
+				s_timerArrays[i] = NULL;
+				*timerID = NULLPTR;
+				break;
+			}
+		}
+
+		if (pdPASS == status)
+		{
+			status = PAL_SUCCESS;
+		}
+		else
+		{
+			status = PAL_ERR_RTOS_PARAMETER;
+		}
+	}
+	else
+	{
+		status = PAL_ERR_RTOS_PARAMETER;
+	}
+
+	return status;
+}
+
+
+palStatus_t pal_plat_osMutexCreate(palMutexID_t* mutexID)
+{
+
+	palStatus_t status = PAL_SUCCESS;
+	palMutex_t* mutex = NULL;
+	if(NULL == mutexID)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	mutex = (palMutex_t*)malloc(sizeof(palMutex_t));
+	if (NULL == mutex)
+	{
+		status = PAL_ERR_NO_MEMORY;
+	}
+
+	if (PAL_SUCCESS == status)
+	{
+
+		mutex->mutexID = (uintptr_t) xSemaphoreCreateRecursiveMutex();
+		if (NULLPTR == mutex->mutexID)
+		{
+			free(mutex);
+			mutex = NULL;
+			PAL_LOG(ERR, "Rtos mutex create failure");
+			status = PAL_ERR_GENERIC_FAILURE;
+		}
+		*mutexID = (palMutexID_t)mutex;
+	}
+	return status;
+}
+
+
+palStatus_t pal_plat_osMutexWait(palMutexID_t mutexID, uint32_t millisec)
+{
+
+	palStatus_t status = PAL_SUCCESS;
+	palMutex_t* mutex = NULL;
+	BaseType_t res = pdTRUE;
+
+	if(NULLPTR == mutexID)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	mutex = (palMutex_t*)mutexID;
+	if (pal_plat_GetIPSR() != 0)
+	{
+		BaseType_t pxHigherPriorityTaskWoken;
+		res = xSemaphoreTakeFromISR(mutex->mutexID, &pxHigherPriorityTaskWoken);
+	}
+	else
+	{
+		res = xSemaphoreTakeRecursive((QueueHandle_t)(mutex->mutexID), (millisec / portTICK_PERIOD_MS) );
+	}
+
+	if (pdTRUE == res)
+	{
+		status = PAL_SUCCESS;
+	}
+	else
+	{
+		status = PAL_ERR_RTOS_TIMEOUT;
+	}
+
+	return status;
+}
+
+
+palStatus_t pal_plat_osMutexRelease(palMutexID_t mutexID)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palMutex_t* mutex = NULL;
+	BaseType_t res = pdTRUE;
+
+	if(NULLPTR == mutexID)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	mutex = (palMutex_t*)mutexID;
+	if (pal_plat_GetIPSR() != 0)
+	{
+		BaseType_t pxHigherPriorityTaskWoken;
+		res = xSemaphoreGiveFromISR(mutex->mutexID, &pxHigherPriorityTaskWoken);
+	}
+	else
+	{
+		res = xSemaphoreGiveRecursive((QueueHandle_t)(mutex->mutexID));
+	}
+
+	if (pdTRUE == res)
+	{
+		status = PAL_SUCCESS;
+	}
+	else
+	{
+		PAL_LOG(ERR, "Rtos mutex release failure %ld", res);
+		status = PAL_ERR_GENERIC_FAILURE;
+	}
+	return status;
+}
+
+palStatus_t pal_plat_osMutexDelete(palMutexID_t* mutexID)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palMutex_t* mutex = NULL;
+
+	if(NULL == mutexID || NULLPTR == *mutexID)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	mutex = (palMutex_t*)*mutexID;
+	if (NULLPTR != mutex->mutexID)
+	{
+		vSemaphoreDelete(mutex->mutexID);
+		free(mutex);
+		*mutexID = NULLPTR;
+		status = PAL_SUCCESS;
+	}
+	else
+	{
+		PAL_LOG(ERR, "Rtos mutex delete failure");
+		status = PAL_ERR_GENERIC_FAILURE;
+	}
+	return status;
+}
+
+palStatus_t pal_plat_osSemaphoreCreate(uint32_t count, palSemaphoreID_t* semaphoreID)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palSemaphore_t* semaphore = NULL;
+
+	if(NULL == semaphoreID)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	semaphore = (palSemaphore_t*)malloc(sizeof(palSemaphore_t));
+	if (NULL == semaphore)
+	{
+		status = PAL_ERR_NO_MEMORY;
+	}
+
+	if(PAL_SUCCESS == status)
+	{
+		semaphore->semaphoreID = (uintptr_t)xSemaphoreCreateCounting(PAL_SEMAPHORE_MAX_COUNT, count);
+		semaphore->maxCount = PAL_SEMAPHORE_MAX_COUNT;
+		if (NULLPTR == semaphore->semaphoreID)
+		{
+			free(semaphore);
+			semaphore = NULLPTR;
+			PAL_LOG(ERR, "Rtos semaphore create error");
+			status = PAL_ERR_GENERIC_FAILURE;
+		}
+		else
+		{
+			*semaphoreID = (palSemaphoreID_t)semaphore;
+		}
+	}
+	return status;
+}
+
+palStatus_t pal_plat_osSemaphoreWait(palSemaphoreID_t semaphoreID, uint32_t millisec, int32_t* countersAvailable)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palSemaphore_t* semaphore = NULL;
+	int32_t tmpCounters = 0;
+	BaseType_t res = pdTRUE;
+
+	if(NULLPTR == semaphoreID)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	semaphore = (palSemaphore_t*)semaphoreID;
+	if (pal_plat_GetIPSR() != 0)
+	{
+		BaseType_t pxHigherPriorityTaskWoken;
+		res = xSemaphoreTakeFromISR(semaphore->semaphoreID, &pxHigherPriorityTaskWoken);
+	}
+	else
+	{
+		if (millisec == PAL_RTOS_WAIT_FOREVER)
+		{
+			res = xSemaphoreTake(semaphore->semaphoreID, portMAX_DELAY);
+		}
+		else
+		{
+			res = xSemaphoreTake(semaphore->semaphoreID, millisec / portTICK_PERIOD_MS);
+		}
+	}
+
+	if (pdTRUE == res)
+	{
+		
+		tmpCounters = uxQueueMessagesWaiting((QueueHandle_t)(semaphore->semaphoreID));
+	}
+	else
+	{
+		tmpCounters = 0;
+		status = PAL_ERR_RTOS_TIMEOUT;
+	}
+
+	if (NULL != countersAvailable)
+	{
+		//because mbedOS returns the number available BEFORE the current take, we have to add 1 here.
+		*countersAvailable = tmpCounters;
+	}
+	return status;
+}
+
+palStatus_t pal_plat_osSemaphoreRelease(palSemaphoreID_t semaphoreID)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palSemaphore_t* semaphore = NULL;
+	BaseType_t res = pdTRUE;
+	int32_t tmpCounters = 0;
+
+	if(NULLPTR == semaphoreID)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	semaphore = (palSemaphore_t*)semaphoreID;
+
+	tmpCounters = uxQueueMessagesWaiting((QueueHandle_t)(semaphore->semaphoreID));
+
+	if(tmpCounters < semaphore->maxCount)
+	{
+		if (pal_plat_GetIPSR() != 0)
+		{
+			BaseType_t pxHigherPriorityTaskWoken;
+			res = xSemaphoreGiveFromISR(semaphore->semaphoreID, &pxHigherPriorityTaskWoken);
+		}
+		else
+		{
+			res = xSemaphoreGive(semaphore->semaphoreID);
+		}
+
+		if (pdTRUE != res)
+		{	
+			status = PAL_ERR_RTOS_PARAMETER;
+		}
+	}
+	else 
+	{
+		status = PAL_ERR_RTOS_RESOURCE;
+	}
+	
+	return status;
+}
+
+palStatus_t pal_plat_osSemaphoreDelete(palSemaphoreID_t* semaphoreID)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palSemaphore_t* semaphore = NULL;
+
+	if(NULL == semaphoreID || NULLPTR == *semaphoreID)
+	{
+		return PAL_ERR_INVALID_ARGUMENT;
+	}
+
+	semaphore = (palSemaphore_t*)*semaphoreID;
+	if (NULLPTR != semaphore->semaphoreID)
+	{
+		vSemaphoreDelete(semaphore->semaphoreID);
+		free(semaphore);
+		*semaphoreID = NULLPTR;
+		status = PAL_SUCCESS;
+	}
+	else
+	{
+		PAL_LOG(ERR, "Rtos semaphore destroy error");
+		status = PAL_ERR_GENERIC_FAILURE;
+	}
+	return status;
+}
+
+
+void *pal_plat_malloc(size_t len)
+{
+	return malloc(len);
+}
+
+
+void pal_plat_free(void * buffer)
+{
+	free(buffer);
+}
+
+
+palStatus_t pal_plat_osRandomBuffer(uint8_t *randomBuf, size_t bufSizeBytes, size_t* actualRandomSizeBytes)
+{
+    palStatus_t status = PAL_SUCCESS;
+
+	status = pal_plat_getRandomBufferFromHW(randomBuf, bufSizeBytes, actualRandomSizeBytes);
+    return status;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/Storage/FileSystem/pal_plat_fileSystem.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,724 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "pal.h"
+#include "pal_plat_fileSystem.h"
+#include "pal_plat_rtos.h"
+
+
+#if defined(__GNUC__) && !defined(__CC_ARM)
+#include <sys/stat.h>
+#include <sys/types.h>
+#endif // defined(__GNUC__) && !defined(__CC_ARM)
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "fsl_mpu.h"
+#include "ff.h"
+#include "diskio.h"
+#include "sdhc_config.h"
+
+
+#define CHK_FD_VALIDITY(x) ((FIL *)x)->fs->id != ((FIL *)x)->id
+#define PAL_FS_ALIGNMENT_TO_SIZE    4                                                          //!< This Size control the number of bytes written to the file (bug fix for writing unaligned memory to file)
+#define PAL_FS_COPY_BUFFER_SIZE 256                                                            //!< Size of the chunk to copy files
+PAL_PRIVATE BYTE g_platOpenModeConvert[] =
+{
+        0,
+        FA_READ | FA_OPEN_EXISTING,                //"r"
+        FA_WRITE | FA_READ| FA_OPEN_EXISTING,    //"r+"
+        FA_WRITE | FA_READ| FA_CREATE_NEW,         //"w+x"
+        FA_WRITE | FA_READ| FA_CREATE_ALWAYS    //"w+"
+};    //!< platform convert table for \b fopen() modes
+
+
+/*! \brief This function find the next file in a directory
+ *
+ * @param[in]    *dh - Directory handler to an open DIR
+ * @param[out]    CurrentEntry - entry for the file found in Directory (pre allocated)
+ *
+ * \return true - upon successful operation.\n
+ *
+ */
+PAL_PRIVATE bool pal_plat_findNextFile(DIR *dh, FILINFO  * CurrentEntry);
+
+/*! \brief This function translate the platform errors opcode to pal error codes
+ *
+ * @param[in]    errorOpCode - platform opcode to be translated
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+ */
+PAL_PRIVATE palStatus_t pal_plat_errorTranslation (int errorOpCode);
+
+/*! \brief This function build the full path name by adding the filename to the working path given in pathName arg
+ *
+ * @param[in]    *pathName - pointer to the null-terminated string that specifies the directory name.
+ * @param[in]   *fileName - pointer to the file name
+ * @param[out]    *fullPath - pointer to the full path including the filename (pre allocated)
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+ *         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t
+ *
+ */
+PAL_PRIVATE palStatus_t pal_plat_addFileNameToPath(const char *pathName, const char * fileName, char * fullPath);
+
+/*! \brief This function copy one file from source folder to destination folder
+ *
+ * @param[in]  pathNameSrc - Pointer to a null-terminated string that specifies the source dir.
+ * @param[in]  pathNameDest - Pointer to a null-terminated string that specifies the destination dir
+ * @param[in] fileName - pointer the the file name
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+ *         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t
+ *
+ * \note File should not be open.\n
+ *         If the Destination file exist then it shall be truncated
+ *
+ */
+PAL_PRIVATE palStatus_t pal_plat_fsCpFile(const char *pathNameSrc,  char *pathNameDest, char * fileName);
+
+palStatus_t pal_plat_fsMkdir(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    FRESULT status = FR_OK;
+    status = f_mkdir(pathName);
+    if (status != FR_OK)
+    {
+        ret = pal_plat_errorTranslation(status);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsRmdir(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    FRESULT status = FR_OK;
+
+    status = f_unlink(pathName);
+    if (status != FR_OK)
+    {
+        if ( status == FR_DENIED)
+        {
+            ret = PAL_ERR_FS_DIR_NOT_EMPTY;
+        }
+        else if (status == FR_NO_FILE)
+        {
+            ret = PAL_ERR_FS_NO_PATH;
+        }
+        else
+        {
+            ret = pal_plat_errorTranslation(status);
+        }
+    }
+
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFopen(const char *pathName, pal_fsFileMode_t mode, palFileDescriptor_t *fd)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    FRESULT status = FR_OK;
+    FIL * descriptor = NULL;
+
+    descriptor = (FIL *)pal_plat_malloc(sizeof(FIL));
+    if (descriptor)
+    {
+        *fd = (palFileDescriptor_t)descriptor;
+        status = f_open((FIL*)*fd, pathName, g_platOpenModeConvert[mode]);
+        if (FR_OK != status)
+        {
+            pal_plat_free(descriptor);
+            if(FR_NO_PATH == status)
+            {
+                ret = PAL_ERR_FS_NO_FILE;
+            }
+            else
+            {
+                ret = pal_plat_errorTranslation(status);
+            }
+        }
+    }
+
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFclose(palFileDescriptor_t *fd)
+{
+    FRESULT status = FR_OK;
+    palStatus_t ret = PAL_SUCCESS;
+
+
+    if (CHK_FD_VALIDITY(*fd))
+    {//Bad File Descriptor
+        ret = PAL_ERR_FS_BAD_FD;
+        return ret;
+    }
+
+    status = f_close((FIL *)*fd);
+    if (FR_OK != status)
+    {
+        ret = pal_plat_errorTranslation(status);
+    }
+    else
+    {
+        pal_plat_free((void*)*fd);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFread(palFileDescriptor_t *fd, void * buffer, size_t numOfBytes, size_t *numberOfBytesRead)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    FRESULT status = FR_OK;
+    uint8_t readaligment[PAL_FS_ALIGNMENT_TO_SIZE] = { 0 };
+    uint32_t index = 0;
+    size_t byteRead = 0;
+    uint8_t  leftover = 0;
+
+    if (CHK_FD_VALIDITY(*fd))
+    {//Bad File Descriptor
+        ret = PAL_ERR_FS_BAD_FD;
+        return ret;
+    }
+
+    leftover = numOfBytes % PAL_FS_ALIGNMENT_TO_SIZE;
+    for(index = 0; index < (numOfBytes / PAL_FS_ALIGNMENT_TO_SIZE); index++)
+    {
+        status = f_read((FIL *)*fd, readaligment, PAL_FS_ALIGNMENT_TO_SIZE, &byteRead);
+        if (FR_OK != status)
+        {
+            ret = pal_plat_errorTranslation(status);
+            break;
+        }
+        else
+        {
+            memcpy(&((uint8_t *)buffer)[*numberOfBytesRead], readaligment, PAL_FS_ALIGNMENT_TO_SIZE);
+            *numberOfBytesRead += byteRead;
+        }
+    }
+
+    if ((ret == PAL_SUCCESS) && (leftover > 0))
+    {
+        status = f_read((FIL *)*fd, readaligment, PAL_FS_ALIGNMENT_TO_SIZE, &byteRead);
+        if (FR_OK != status)
+        {
+            ret = pal_plat_errorTranslation(status);
+        }
+        else
+        {
+            memcpy(&((uint8_t *)buffer)[*numberOfBytesRead], readaligment, leftover);
+            *numberOfBytesRead += leftover;
+            ret = pal_fsFseek(fd, leftover - PAL_FS_ALIGNMENT_TO_SIZE ,PAL_FS_OFFSET_SEEKCUR);
+        }
+    }
+
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFwrite(palFileDescriptor_t *fd, const void *buffer, size_t numOfBytes, size_t *numberOfBytesWritten)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    FRESULT status = FR_OK;
+    uint32_t index = 0;
+    size_t bytesWritten = 0;
+    uint8_t  leftover = 0;
+
+    if (CHK_FD_VALIDITY(*fd))
+    {//Bad File Descriptor
+        ret = PAL_ERR_FS_BAD_FD;
+        return ret;
+    }
+
+    leftover = numOfBytes % PAL_FS_ALIGNMENT_TO_SIZE;
+    for (index = 0; index < (numOfBytes / PAL_FS_ALIGNMENT_TO_SIZE); index++)
+    {
+        status = f_write((FIL *)*fd, ((uint8_t *)buffer + *numberOfBytesWritten), PAL_FS_ALIGNMENT_TO_SIZE, &bytesWritten);
+        if (FR_OK != status)
+        {
+            ret = pal_plat_errorTranslation(status);
+            break;
+        }
+        else if (PAL_FS_ALIGNMENT_TO_SIZE != bytesWritten)
+        {
+            ret = PAL_ERR_FS_INSUFFICIENT_SPACE;
+        }
+        else
+        {
+            *numberOfBytesWritten += bytesWritten;
+        }
+    }
+
+    if ((ret == PAL_SUCCESS) && (leftover > 0))
+    {
+        status = f_write((FIL *)*fd, ((uint8_t *)buffer + *numberOfBytesWritten), leftover, &bytesWritten);
+        if (FR_OK != status)
+        {
+            ret = pal_plat_errorTranslation(status);
+        }
+        else if (leftover != bytesWritten)
+        {
+            ret = PAL_ERR_FS_INSUFFICIENT_SPACE;
+        }
+        else
+        {
+            *numberOfBytesWritten += bytesWritten;
+        }
+    }
+
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFseek(palFileDescriptor_t *fd, int32_t offset, pal_fsOffset_t whence)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    FRESULT status = FR_OK;
+    uint32_t  fatFSOffset = 0;
+
+    if (CHK_FD_VALIDITY(*fd))
+    {//Bad File Descriptor
+        ret = PAL_ERR_FS_BAD_FD;
+        return ret;
+    }
+
+
+    switch(whence)
+    {
+    case PAL_FS_OFFSET_SEEKCUR:
+        if (((-1)*offset  > f_tell((FIL*)*fd) && (offset < 0)) || (offset  > f_tell((FIL*)*fd) && (offset > 0)))
+        {
+            ret = PAL_ERR_FS_ERROR;
+        }
+        else
+        {
+            fatFSOffset = f_tell((FIL*)*fd) + offset;
+        }
+        break;
+
+    case PAL_FS_OFFSET_SEEKEND:
+        if ((-1)*offset  > f_size((FIL*)*fd) || (offset > 0))
+        {
+            ret = PAL_ERR_FS_ERROR;
+        }
+        else
+        {
+            fatFSOffset = f_size((FIL*)*fd) + offset;
+        }
+        break;
+
+    case PAL_FS_OFFSET_SEEKSET:
+        if (offset >  f_size((FIL*)*fd))
+        {
+            ret = PAL_ERR_FS_ERROR;
+        }
+        else
+        {
+            fatFSOffset = offset;
+        }
+        break;
+
+    default:
+        fatFSOffset = 0;
+        break;
+    }
+
+    if (ret == PAL_SUCCESS)
+    {
+        status = f_lseek ((FIL *)*fd, fatFSOffset);
+        if (FR_OK != status)
+        {
+            ret = pal_plat_errorTranslation(status);
+        }
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFtell(palFileDescriptor_t *fd, int32_t * pos)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    if (CHK_FD_VALIDITY(*fd))
+    {//Bad File Descriptor
+        ret = PAL_ERR_FS_BAD_FD;
+    }
+    else
+    {
+        *pos = f_tell((FIL*)*fd);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsUnlink(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    FRESULT status = FR_OK;
+
+    status = f_unlink(pathName);
+    if (status != FR_OK)
+    {
+        if (status == FR_DENIED)
+        {
+            ret = PAL_ERR_FS_DIR_NOT_EMPTY;
+        }
+        else
+        {
+            ret = pal_plat_errorTranslation(status);
+        }
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsRmFiles(const char *pathName)
+{
+    DIR dh; //Directory handler
+    palStatus_t ret = PAL_SUCCESS;
+    FRESULT status = FR_OK;
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; //Buffer for coping the name and folder
+    FILINFO  currentEntry = { 0 }; //file Entry
+
+    status = f_opendir(&dh, pathName);
+    if (status != FR_OK)
+    {
+        ret = pal_plat_errorTranslation(status);
+    }
+
+    if (ret == PAL_SUCCESS)
+    {
+        while(true)
+        {
+            if (!pal_plat_findNextFile(&dh, &currentEntry))
+            {
+                ret = PAL_ERR_FS_ERROR_IN_SEARCHING;
+                break;
+            }
+            pal_plat_addFileNameToPath(pathName, currentEntry.fname, buffer);
+            if (currentEntry.fname[0] != '\0')
+            {
+                if (currentEntry.fattrib & AM_DIR)
+                {
+                    ret = pal_fsRmFiles(buffer);
+                    if (ret != PAL_SUCCESS)
+                    {
+                        break;
+                    }
+                    ret = pal_fsRmDir(buffer);
+                    if (PAL_SUCCESS != ret)
+                    {
+                        break;
+                    }
+                }
+                else
+                {
+                    status = f_unlink (buffer);
+                    if (status != FR_OK)
+                    {
+                        ret = pal_plat_errorTranslation(status);
+                        break;
+                    }
+                }
+            }
+            else
+            {//End of directory reached  without errors break, close directory and exit
+                break;
+            }
+        }//while()
+
+        status = f_closedir (&dh); //Close DIR handler
+        if (status != FR_OK)
+        {
+            ret = pal_plat_errorTranslation(status);
+        }
+    }
+
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsCpFolder(const char *pathNameSrc,  char *pathNameDest)
+{
+    DIR src_dh; //Directory for the source Directory handler
+    palStatus_t ret = PAL_SUCCESS;
+    FILINFO currentEntry = { 0 }; //file Entry
+    FRESULT status = FR_OK;
+
+
+    status = f_opendir(&src_dh, pathNameSrc);
+    if (status != FR_OK)
+    {
+        ret = pal_plat_errorTranslation(status);
+    }
+
+
+    if (ret == PAL_SUCCESS)
+    {
+        while(true)
+        {
+            if (!pal_plat_findNextFile(&src_dh, &currentEntry))
+            {
+                ret = PAL_ERR_FS_ERROR_IN_SEARCHING;
+                break;
+            }
+            if (currentEntry.fname[0] != 0)
+            {
+                if (currentEntry.fattrib & AM_DIR) // skip all folder as this is flat copy only
+                {
+                    continue;
+                }
+                //copy the file to the destination
+                ret = pal_plat_fsCpFile(pathNameSrc, pathNameDest, currentEntry.fname);
+                if (ret != PAL_SUCCESS)
+                {
+                    break;
+                }
+            }
+            else
+            {//End of directory reached  without errors break and close directory and exit
+                break;
+            }
+        }//while()
+        f_closedir(&src_dh);
+    }
+
+    return ret;
+}
+
+
+PAL_PRIVATE palStatus_t pal_plat_fsCpFile(const char *pathNameSrc,  char *pathNameDest, char * fileName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    FIL src_fd, dst_fd;
+    char * buffer = NULL;
+    char buffer_name[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; //Buffer for coping the name and folder
+    size_t bytesCount = 0;
+    FRESULT status = FR_OK;
+
+    //Add file name to path
+    pal_plat_addFileNameToPath(pathNameSrc, fileName, buffer_name);
+    status = f_open(&src_fd, buffer_name, g_platOpenModeConvert[PAL_FS_FLAG_READONLY]);
+    if (status != FR_OK)
+    {
+        ret = pal_plat_errorTranslation(status);
+    }
+    else
+    {
+        //Add file name to path
+        pal_plat_addFileNameToPath(pathNameDest, fileName, buffer_name);
+        status = f_open(&dst_fd, buffer_name, g_platOpenModeConvert[PAL_FS_FLAG_READWRITETRUNC]);
+        if (status != FR_OK)
+        {
+            ret = pal_plat_errorTranslation(status);
+        }
+        else
+        {
+            buffer = (char*)pal_plat_malloc(PAL_FS_COPY_BUFFER_SIZE);
+            if (!buffer)
+            {
+                ret = PAL_ERR_RTOS_RESOURCE;
+            }
+        }
+    }
+
+    if (ret == PAL_SUCCESS)
+    {
+        while (1)
+        {
+            status = f_read(&src_fd, buffer, PAL_FS_COPY_BUFFER_SIZE, &bytesCount);
+
+            if (status != FR_OK)
+            {
+                break;
+            }
+
+            //Check if end of file reached
+            if (bytesCount == 0)
+            {
+                break;
+            }
+
+            status = f_write(&dst_fd, buffer, bytesCount, &bytesCount);
+            if (status != FR_OK)
+            {
+                break;
+            }
+        }
+        if (status != FR_OK)
+        {
+            ret = pal_plat_errorTranslation(status);
+        }
+    }
+
+
+
+    f_close(&src_fd);
+    f_close(&dst_fd);
+    if (buffer)
+    {
+        pal_plat_free(buffer);
+    }
+    return ret;
+}
+
+const char* pal_plat_fsGetDefaultRootFolder(pal_fsStorageID_t dataID)
+{
+    const char* returnedRoot = NULL;
+    if (PAL_FS_PARTITION_PRIMARY == dataID)
+    {
+        returnedRoot =  PAL_FS_MOUNT_POINT_PRIMARY;
+    }
+    else if (PAL_FS_PARTITION_SECONDARY == dataID)
+    {
+        returnedRoot =  PAL_FS_MOUNT_POINT_SECONDARY;
+    }
+    return returnedRoot;
+}
+
+
+PAL_PRIVATE bool pal_plat_findNextFile(DIR *dh, FILINFO  *CurrentEntry)
+{
+    bool ret = true;
+    bool skip = false;
+    bool foundFile = false;
+    FRESULT status;
+
+    do
+    {
+        status = f_readdir(dh, CurrentEntry);
+        if (status == FR_OK)
+        {
+            if ((CurrentEntry)->fname[0] == 0)
+            {//End Of Directory
+                ret = true;
+                break;
+            }
+
+            /* Skip the names "." and ".." as we don't want to remove them. also make sure that the current entry point to REGULER file*/
+            skip = (!strcmp((CurrentEntry)->fname, ".")) || (!strcmp((CurrentEntry)->fname, ".."));
+            if (skip)
+            {
+                continue;
+            }
+            else
+            {
+                foundFile = true;
+            }
+        }
+        else
+        {//NOT!!! EOF  other error
+            ret = false;
+            break; //Break from while
+        }
+    }
+    while((!foundFile) && (ret)); //While file has been found or ret is set to false
+    return ret;
+}
+
+PAL_PRIVATE palStatus_t pal_plat_addFileNameToPath(const char *pathName, const char * fileName, char * fullPath)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    if ((strlen(pathName) >= PAL_MAX_FOLDER_DEPTH_CHAR)  || (strlen(fileName) >= PAL_MAX_FULL_FILE_NAME))
+    {
+        ret = PAL_ERR_FS_FILENAME_LENGTH;
+    }
+    else if (fullPath)
+    {
+        strcpy(fullPath, pathName);
+        strcat(fullPath, "/");
+        strcat(fullPath, fileName);
+    }
+    else
+    {
+        ret = PAL_ERR_RTOS_RESOURCE;
+    }
+    return ret;
+}
+
+
+PAL_PRIVATE palStatus_t pal_plat_errorTranslation (int errorOpCode)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    switch(errorOpCode)
+    {
+    case 0:
+        break;
+    case FR_DENIED:
+    case FR_WRITE_PROTECTED:
+    case FR_LOCKED:
+        ret = PAL_ERR_FS_ACCESS_DENIED;
+        break;
+
+    case FR_NOT_READY :
+        ret = PAL_ERR_FS_BUSY;
+        break;
+
+    case FR_EXIST:
+        ret = PAL_ERR_FS_NAME_ALREADY_EXIST;
+        break;
+
+    case FR_INVALID_NAME:
+    case FR_INVALID_OBJECT:
+    case FR_INVALID_DRIVE:
+        ret = PAL_ERR_FS_INVALID_ARGUMENT;
+        break;
+
+    case  FR_NO_FILE:
+        ret = PAL_ERR_FS_NO_FILE;
+        break;
+
+    case FR_NO_PATH:
+        ret = PAL_ERR_FS_NO_PATH;
+        break;
+
+    default:
+        ret = PAL_ERR_FS_ERROR;
+        break;
+    }
+    return ret;
+}
+
+
+size_t pal_plat_fsSizeCheck(const char *stringToChk)
+{
+    size_t length = 0;
+    length = strlen(stringToChk);
+    return length;
+}
+
+
+
+palStatus_t pal_plat_fsFormat(pal_fsStorageID_t dataID)
+{
+	const char* partitionNames[] ={
+                                    PAL_FS_MOUNT_POINT_PRIMARY,
+                                    PAL_FS_MOUNT_POINT_SECONDARY
+	                               };
+    palStatus_t result = PAL_SUCCESS;
+    const char* partName = partitionNames[dataID];
+    FRESULT res = f_mkfs(partName, 0, 0);
+    if (FR_OK != res)
+    {
+        result = PAL_ERR_FS_ERROR;
+    }
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/Storage/Flash/pal_plat_internalFlash.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal.h"
+#include "pal_plat_internalFlash.h"
+#include "fsl_flash.h"
+
+////////////////////////////PRIVATE///////////////////////////////////
+PAL_PRIVATE flash_config_t g_flashDescriptor = {0};
+////////////////////////////END PRIVATE////////////////////////////////
+
+palStatus_t pal_plat_internalFlashInit(void)
+{
+    status_t status;
+    palStatus_t ret = PAL_SUCCESS;
+    status = FLASH_Init(&g_flashDescriptor);
+    if(kStatus_FLASH_Success != status)
+    {
+        ret = PAL_ERR_INTERNAL_FLASH_INIT_ERROR;
+    }
+	return ret;
+}
+
+
+palStatus_t pal_plat_internalFlashDeInit(void)
+{
+    memset(&g_flashDescriptor, 0, sizeof(g_flashDescriptor));
+	return PAL_SUCCESS;
+}
+
+
+palStatus_t pal_plat_internalFlashWrite(const size_t size, const uint32_t address, const uint32_t * buffer)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    status_t status = kStatus_Success;
+
+	/* We need to prevent flash accesses during program operation */
+	__disable_irq();
+	status = FLASH_Program(&g_flashDescriptor, address, (uint32_t *)buffer, size);
+	if (kStatus_Success == status)
+	{
+		// Must use kFlashMargin_User, or kFlashMargin_Factory for verify program
+		status = FLASH_VerifyProgram(&g_flashDescriptor, address, size, (uint32_t *)buffer, kFLASH_marginValueUser, NULL, NULL);
+		if(kStatus_Success != status)
+		{
+			ret = PAL_ERR_INTERNAL_FLASH_WRITE_ERROR;
+		}
+	}
+	__enable_irq();
+
+    return ret;
+}
+
+palStatus_t pal_plat_internalFlashRead(const size_t size, const uint32_t address, uint32_t * buffer)
+{
+    memcpy(buffer, (const void *)address, size);
+    return PAL_SUCCESS;
+}
+
+
+palStatus_t pal_plat_internalFlashErase(uint32_t address, size_t size)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    int16_t  status = kStatus_Success;
+
+    __disable_irq();
+    status = FLASH_Erase(&g_flashDescriptor, address, pal_plat_internalFlashGetSectorSize(address), kFLASH_apiEraseKey);
+    if (kStatus_Success == status)
+    {
+        status = FLASH_VerifyErase(&g_flashDescriptor, address, pal_plat_internalFlashGetSectorSize(address), kFLASH_marginValueNormal);
+    }
+
+    if (kStatus_Success != status)
+    {
+        ret = PAL_ERR_INTERNAL_FLASH_ERASE_ERROR;
+    }
+    __enable_irq();
+    return ret;
+}
+
+
+size_t pal_plat_internalFlashGetPageSize(void)
+{
+	return FSL_FEATURE_FLASH_PFLASH_BLOCK_WRITE_UNIT_SIZE;
+}
+
+
+size_t pal_plat_internalFlashGetSectorSize(uint32_t address)
+{
+    size_t devicesize = 0;
+    FLASH_GetProperty(&g_flashDescriptor, kFLASH_propertyPflashSectorSize, (uint32_t*)&devicesize);
+    return devicesize;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/FreeRTOS/Update/pal_plat_update.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal.h"
+#include "pal_plat_update.h"
+
+#include "fsl_device_registers.h"
+#include "fsl_debug_console.h"
+#include "board.h"
+#include "clock_config.h"
+#include "fsl_flash.h"
+
+
+  
+
+#define PAL_UPDATE_JOURNAL_SIZE 0x80000UL
+#define PAL_UPDATE_JOURNAL_START_OFFSET 0x80000UL
+
+#if (!defined(PAL_UPDATE_ACTIVE_METADATA_HEADER_OFFSET))
+#define PAL_UPDATE_ACTIVE_METADATA_HEADER_OFFSET 0x80000UL
+#endif
+
+#define SIZEOF_SHA256 256/8
+#define FIRMWARE_HEADER_MAGIC   0x5a51b3d4UL
+#define FIRMWARE_HEADER_VERSION 1
+
+PAL_PRIVATE FirmwareHeader_t g_palFirmwareHeader;
+PAL_PRIVATE bool g_headerWasWritten = false;
+
+PAL_PRIVATE flash_config_t g_flashDriver;
+
+
+/*
+ * call back functions
+ *
+ */
+
+PAL_PRIVATE palImageSignalEvent_t g_palUpdateServiceCBfunc;
+
+/*
+ * WARNING: please do not change this function!
+ * this function loads a call back function received from the upper layer (service).
+ * the call back should be called at the end of each function (except pal_plat_imageGetDirectMemAccess)
+ * the call back receives the event type that just happened defined by the ENUM  palImageEvents_t.
+ *
+ * if you will not call the call back at the end the service behaver will be undefined
+ */
+palStatus_t pal_plat_imageInitAPI(palImageSignalEvent_t CBfunction)
+{
+    if (!CBfunction)
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+	g_palUpdateServiceCBfunc = CBfunction;
+    g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_INIT);
+
+	return PAL_SUCCESS;
+}
+
+palStatus_t pal_plat_imageDeInit(void)
+{
+	palStatus_t status = PAL_SUCCESS;
+	return status;
+}
+
+
+palStatus_t pal_plat_imageGetMaxNumberOfImages(uint8_t *imageNumber)
+{
+	return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageSetVersion(palImageId_t imageId, const palConstBuffer_t* version)
+{
+	return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageGetDirectMemAccess(palImageId_t imageId, void** imagePtr, size_t *imageSizeInBytes)
+{
+	return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageActivate(palImageId_t imageId)
+{
+	return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+
+palStatus_t pal_plat_imageGetActiveHash(palBuffer_t *hash)
+{
+
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+//Retrieve the version of the active image to version buffer with size set to version bufferLength.
+palStatus_t pal_plat_imageGetActiveVersion (palBuffer_t* version)
+{
+	return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+//Writing the value of active image hash stored in hashValue to memory
+palStatus_t pal_plat_imageWriteHashToMemory(const palConstBuffer_t* const hashValue)
+{
+	return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+
+/*
+ * init apis
+ */
+
+
+
+//fill the image header data for writing, the writing will occur in the 1st image write
+palStatus_t pal_plat_imageSetHeader(palImageId_t imageId,palImageHeaderDeails_t *details)
+{
+    DEBUG_PRINT(">>%s\r\n",__FUNCTION__);
+    palStatus_t status = PAL_SUCCESS;
+    g_headerWasWritten = false; // set that the image was not written yet
+    memset(&g_palFirmwareHeader,0,sizeof(g_palFirmwareHeader));
+    g_palFirmwareHeader.totalSize = details->imageSize + sizeof(FirmwareHeader_t);
+    g_palFirmwareHeader.magic = FIRMWARE_HEADER_MAGIC;
+    g_palFirmwareHeader.version = FIRMWARE_HEADER_VERSION;
+    g_palFirmwareHeader.firmwareVersion = details->version;
+
+    memcpy(g_palFirmwareHeader.firmwareSHA256,details->hash.buffer,SIZEOF_SHA256);
+    /*
+     * calculating and setting the checksum of the header.
+     * Have to call to crcInit  before use.
+     */
+   // crcInit();
+   // g_palFirmwareHeader.checksum =  crcFast((const unsigned char *)&g_palFirmwareHeader, (int)sizeof(g_palFirmwareHeader));
+    return  status;
+}
+
+
+
+palStatus_t pal_plat_imageReserveSpace(palImageId_t imageId, size_t imageSize)
+{
+    status_t result = PAL_SUCCESS;
+    memset(&g_flashDriver, 0, sizeof(g_flashDriver));
+    result = FLASH_Init(&g_flashDriver);
+    if (kStatus_FLASH_Success != result)
+    {
+        g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_ERROR);
+        return PAL_ERR_UPDATE_ERROR;
+    }
+
+    result = FLASH_Erase(&g_flashDriver, PAL_UPDATE_JOURNAL_START_OFFSET, imageSize, kFLASH_apiEraseKey);
+    if (kStatus_FLASH_Success != result)
+    {
+        g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_ERROR);
+        return PAL_ERR_UPDATE_ERROR;
+    }
+
+    result = FLASH_VerifyErase(&g_flashDriver, PAL_UPDATE_JOURNAL_START_OFFSET, imageSize, kFLASH_marginValueUser);
+    if (kStatus_FLASH_Success != result)
+    {
+        g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_ERROR);
+        return PAL_ERR_UPDATE_ERROR;
+    }
+    g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_PREPARE);
+
+    return PAL_SUCCESS;
+}
+
+
+
+
+
+/*
+ * write API
+ */
+
+
+
+
+
+palStatus_t pal_plat_imageWrite(palImageId_t imageId, size_t offset, palConstBuffer_t *chunk)
+{
+    status_t result = PAL_SUCCESS;
+    uint32_t failAddr, failDat;
+    //if header was not written - write header
+    if (!g_headerWasWritten)
+    {
+        result = FLASH_Program(
+            &g_flashDriver,
+            PAL_UPDATE_JOURNAL_START_OFFSET,
+            (uint32_t *)(&g_palFirmwareHeader),
+            sizeof(g_palFirmwareHeader)
+            );
+		if (kStatus_FLASH_Success != result)
+		{
+		    g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_ERROR);
+		    return PAL_ERR_UPDATE_ERROR;
+		}
+		g_headerWasWritten = true;
+    }
+    result = FLASH_Program(
+        &g_flashDriver,
+        (PAL_UPDATE_JOURNAL_START_OFFSET + sizeof(g_palFirmwareHeader) + offset),
+        (uint32_t *)(chunk->buffer),
+        chunk->bufferLength
+        );
+    if (kStatus_FLASH_Success != result)
+    {
+        g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_ERROR);
+        return PAL_ERR_UPDATE_ERROR;
+    }
+
+    /* Program Check user margin levels */
+    result = FLASH_VerifyProgram(
+        &g_flashDriver,
+        (PAL_UPDATE_JOURNAL_START_OFFSET + sizeof(g_palFirmwareHeader) + offset),
+        chunk->bufferLength,
+        (const uint32_t *)(chunk->buffer),
+        kFLASH_marginValueUser,
+        &failAddr,
+        &failDat
+        );
+    if (kStatus_FLASH_Success != result)
+    {
+        g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_ERROR);
+        return PAL_ERR_UPDATE_ERROR;
+    }
+    g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_WRITE);
+    return PAL_SUCCESS;
+}
+
+
+/*
+ * read APIs
+ */
+
+
+
+
+palStatus_t pal_plat_imageReadToBuffer(palImageId_t imageId, size_t offset, palBuffer_t *chunk)
+{
+    uint32_t imageSize = g_palFirmwareHeader.totalSize - sizeof(g_palFirmwareHeader); //totalSize - headerSize
+    if ((offset + chunk->maxBufferLength) <= imageSize)
+    {
+        chunk->bufferLength = chunk->maxBufferLength;
+    }
+    else
+    {
+        chunk->bufferLength =chunk->maxBufferLength + imageSize - offset;
+    }
+    memcpy(chunk->buffer, (void*)(PAL_UPDATE_JOURNAL_START_OFFSET + sizeof(g_palFirmwareHeader) + offset) , chunk->bufferLength);
+    g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_READTOBUFFER);
+    return PAL_SUCCESS;
+}
+
+
+
+/*
+ * commit functions
+ * */
+
+
+
+palStatus_t pal_plat_imageFlush(palImageId_t package_id)
+{
+    DEBUG_PRINT(">>%s\r\n",__FUNCTION__);
+    g_palUpdateServiceCBfunc(PAL_IMAGE_EVENT_FINALIZE);
+    DEBUG_PRINT("<<%s\r\n",__FUNCTION__);
+    return PAL_SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Board_Specific/TARGET_OpenWRT_Generic/pal_plat_OpenWRT_Generic.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "pal_plat_rtos.h"
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h> // needed to FILE operations
+#include <stdlib.h>
+#include <string.h>
+
+
+#define TRACE_GROUP "PAL"
+
+
+palStatus_t pal_plat_getRandomBufferFromHW(uint8_t *randomBuf, size_t bufSizeBytes, size_t* actualRandomSizeBytes)
+{
+	palStatus_t status = PAL_SUCCESS;
+	FILE *fp;
+	size_t actualRead = 0;
+
+	fp = fopen("/dev/hwrng", "r");
+	if (NULL != fp)
+	{
+		actualRead = fread(randomBuf, 1, bufSizeBytes, fp);
+		if (0 == actualRead)
+		{
+			status = PAL_ERR_RTOS_TRNG_FAILED;
+		}
+		else if (actualRead != bufSizeBytes)
+		{
+			status = PAL_ERR_RTOS_TRNG_PARTIAL_DATA;
+		}
+		fclose(fp);
+	}
+	else
+	{
+		status = PAL_ERR_FS_NO_FILE;
+	}
+    
+	if (NULL != actualRandomSizeBytes)
+    {
+        *actualRandomSizeBytes = actualRead;
+    }
+	return status;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Board_Specific/TARGET_Yocto_Generic/pal_plat_Yocto_Generic.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "pal_plat_rtos.h"
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h> // needed to FILE operations
+#include <stdlib.h>
+#include <string.h>
+
+
+#define TRACE_GROUP "PAL"
+
+palStatus_t pal_plat_getRandomBufferFromHW(uint8_t *randomBuf, size_t bufSizeBytes, size_t* actualRandomSizeBytes)
+{
+	palStatus_t status = PAL_SUCCESS;
+	FILE *fp;
+	size_t actualRead = 0;
+
+	fp = fopen("/dev/hwrng", "r");
+	if (NULL != fp)
+	{
+		actualRead = fread(randomBuf, 1, bufSizeBytes, fp);
+		if (0 == actualRead)
+		{
+			status = PAL_ERR_RTOS_TRNG_FAILED;
+		}
+		else if (actualRead != bufSizeBytes)
+		{
+			status = PAL_ERR_RTOS_TRNG_PARTIAL_DATA;
+		}
+		fclose(fp);
+	}
+	else
+	{
+		status = PAL_ERR_FS_NO_FILE;
+	}
+
+    if (NULL != actualRandomSizeBytes)
+    {
+        *actualRandomSizeBytes = actualRead;
+    }
+	return status;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Board_Specific/TARGET_x86_x64/pal_plat_x86_x64.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include "pal_plat_rtos.h"
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+
+palStatus_t pal_plat_getRandomBufferFromHW(uint8_t *randomBuf, size_t bufSizeBytes, size_t* actualRandomSizeBytes)
+{
+	palStatus_t status = PAL_SUCCESS;
+	FILE *fp;
+	size_t actualRead = 0;
+
+	fp = fopen("/dev/random", "r");
+	if (NULL != fp)
+	{
+		actualRead = fread(randomBuf, 1, bufSizeBytes, fp);
+		if (0 == actualRead)
+		{
+			status = PAL_ERR_RTOS_TRNG_FAILED;
+		}
+		else if (actualRead != bufSizeBytes)
+		{
+			status = PAL_ERR_RTOS_TRNG_PARTIAL_DATA;
+		}
+		 fclose(fp);
+	}
+	else
+	{
+		status = PAL_ERR_FS_NO_FILE;
+	}
+
+    if (NULL != actualRandomSizeBytes)
+    {
+        *actualRandomSizeBytes = actualRead;
+    }
+	return status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Networking/pal_plat_network.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1172 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#define _GNU_SOURCE // This is for ppoll found in poll.h
+#include "pal.h"
+#include "pal_plat_network.h"
+#include "pal_rtos.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <ifaddrs.h>
+#include <errno.h>
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+#include <pthread.h>
+#include <poll.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <time.h>
+#include <assert.h>
+#endif
+
+#ifdef PAL_NET_TCP_AND_TLS_SUPPORT
+#include <netinet/tcp.h>
+#endif
+
+// invalid socket based on posix
+#define PAL_LINUX_INVALID_SOCKET (-1)
+
+
+typedef struct palNetInterfaceName{
+    char interfaceName[PAL_NET_MAX_IF_NAME_LENGTH];
+} palNetInterfaceName_t;
+
+PAL_PRIVATE palNetInterfaceName_t s_palNetworkInterfacesSupported[PAL_MAX_SUPORTED_NET_INTERFACES];
+
+PAL_PRIVATE  uint32_t s_palNumOfInterfaces = 0;
+PAL_PRIVATE  uint32_t s_pal_network_initialized = 0;
+
+PAL_PRIVATE palStatus_t translateErrorToPALError(int errnoValue)
+{
+    palStatus_t status;
+    switch (errnoValue)
+    {
+    case EAI_MEMORY:
+        status = PAL_ERR_NO_MEMORY;
+        break;
+    case EWOULDBLOCK:
+        status = PAL_ERR_SOCKET_WOULD_BLOCK;
+        break;
+    case ENOTSOCK:
+        status = PAL_ERR_SOCKET_INVALID_VALUE;
+        break;
+    case EPERM:
+    case EACCES:
+        status = PAL_ERR_SOCKET_OPERATION_NOT_PERMITTED;
+        break;
+    case ETIMEDOUT:
+        status = PAL_ERR_TIMEOUT_EXPIRED;
+        break;
+    case EISCONN:
+        status = PAL_ERR_SOCKET_ALREADY_CONNECTED;
+        break;
+    case EINPROGRESS:
+        status = PAL_ERR_SOCKET_IN_PROGRES;
+        break;
+    case EALREADY:
+        status = PAL_ERR_SOCKET_ALREADY_CONNECTED;
+        break;
+    case EINVAL:
+        status = PAL_ERR_SOCKET_INVALID_VALUE;
+        break;
+    case EADDRINUSE:
+        status = PAL_ERR_SOCKET_ADDRESS_IN_USE;
+        break;
+    case ECONNABORTED:
+        status = PAL_ERR_SOCKET_CONNECTION_ABORTED;
+        break;
+    case ENOBUFS:
+    case ENOMEM:
+        status = PAL_ERR_SOCKET_NO_BUFFERS;
+        break;
+    case EINTR:
+        status = PAL_ERR_SOCKET_INTERRUPTED;
+        break;
+    default:
+        status = PAL_ERR_SOCKET_GENERIC;
+        break;
+    }
+    return status;
+}
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+static pthread_t s_pollThread = NULLPTR;
+static palMutexID_t s_mutexSocketCallbacks = 0;
+static palMutexID_t s_mutexSocketEventFilter = 0;
+static palSemaphoreID_t s_socketCallbackSemaphore = 0;
+static palSemaphoreID_t s_socketCallbackSignalSemaphore = 0;
+
+
+
+// These must be updated only when protected by s_mutexSocketCallbacks
+static palAsyncSocketCallback_t s_callbacks[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {0};
+static void* s_callbackArgs[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = { 0 };
+static struct pollfd s_fds[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {{0,0,0}};
+static uint32_t s_callbackFilter[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {0};
+static nfds_t s_nfds = 0;
+static volatile bool s_socketThreadTerminateSignaled = false;
+
+// The below function is the signal handler API, doing nothing.
+// The idea is to signal the asyncSocketManager thread with pthread_kill(s_pollThread, SIGUSR1) command
+// which make the ppoll API to be interrupted.
+
+static uint64_t s_palUSR1Counter =0;
+static void sigusr2(int signo) {
+    (void)signo;
+    s_palUSR1Counter++;
+    pal_osSemaphoreRelease(s_socketCallbackSignalSemaphore);
+}
+
+static uint64_t s_palIOCounter =0;
+
+static void sig_io_handler(int signo) {
+    (void)signo;
+
+    s_palIOCounter++;
+    pal_osSemaphoreRelease(s_socketCallbackSignalSemaphore);
+}
+
+
+static const unsigned int PAL_SOCKETS_TERMINATE = 10000;
+
+
+PAL_PRIVATE void clearSocketFilter( int socketFD)
+{
+    palStatus_t result = PAL_SUCCESS;
+    int i = 0;
+    result = pal_osMutexWait(s_mutexSocketEventFilter, PAL_RTOS_WAIT_FOREVER);
+    if (PAL_SUCCESS != result)
+    {
+        PAL_LOG(ERR, "error waiting for mutex"); // we want to zero the flag even if this fails beacuse it is better to get an extra event than miss one.
+    }
+    for (i = 0; i < PAL_NET_TEST_MAX_ASYNC_SOCKETS; i++)
+    {
+
+        if (s_fds[i].fd == socketFD)
+        {
+            s_callbackFilter[i] = 0;
+            break;
+        }
+    }
+    result = pal_osMutexRelease(s_mutexSocketEventFilter);
+    if (PAL_SUCCESS != result)
+    {
+        PAL_LOG(ERR, "error releasing mutex");
+    }
+}
+
+
+// Thread function.
+PAL_PRIVATE void asyncSocketManager(void const* arg)
+{
+    PAL_UNUSED_ARG(arg); // unused
+    int res;
+    palAsyncSocketCallback_t callbacks[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {0};
+    void* callbackArgs[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {0};
+    struct pollfd fds[PAL_NET_TEST_MAX_ASYNC_SOCKETS] = {{0,0,0}};
+    nfds_t nfds = 0;
+    struct sigaction s;
+    sigset_t blockedSignals;
+    palStatus_t result = PAL_SUCCESS;
+    uint64_t lastIOCounter=0;
+    uint64_t lastUSRCounter=0;
+
+    const struct timespec timeout_zero = {0, 0};
+
+    // Initialize the signal handler. SIG_IGN and SIG_DFL do not work
+    s.sa_handler = sigusr2;
+    sigemptyset(&s.sa_mask);
+    s.sa_flags = 0;
+    sigaction(SIGUSR1, &s, NULL);
+
+    s.sa_handler = sig_io_handler;
+    sigemptyset(&s.sa_mask);
+    s.sa_flags =  SA_RESTART ;
+    sigaction(SIGIO, &s, NULL);
+
+    // Block the timer signal from interrupting ppoll(), as it does not have a signal handler.
+    // The timer signal is already blocked on all the threads created after pal_init(), but
+    // the ppoll() will change that situation with the given sigmask.
+    // Without this, the libc's default signal handler will kick in and kill the process.
+    sigemptyset(&blockedSignals);
+    sigaddset(&blockedSignals, PAL_TIMER_SIGNAL);
+
+    s_pollThread = pthread_self(); // save the thread id for signal usage
+    // Tell the calling thread that we have finished initialization
+    result = pal_osSemaphoreRelease(s_socketCallbackSemaphore);
+    if (result != PAL_SUCCESS)
+    {
+        PAL_LOG(ERR, "Error in async socket manager on semaphore release");
+    }
+
+
+    while (result == PAL_SUCCESS) //As long as all goes well loop forever
+    {
+        // block until a SIGIO signal is received
+        if (lastUSRCounter == s_palUSR1Counter) // no updates to the sockets that need to be polled (wait for next IO)  - if there were updates skip waiting and proceeed to poll
+        {
+            pal_osSemaphoreWait(s_socketCallbackSignalSemaphore, PAL_RTOS_WAIT_FOREVER, NULL);
+        }
+
+        // Critical section to update globals
+        result = pal_osMutexWait(s_mutexSocketCallbacks, PAL_RTOS_WAIT_FOREVER);
+        if (PAL_SUCCESS != result)
+        {
+            PAL_LOG(ERR, "Error in async socket manager on mutex wait");
+            break;
+        }
+
+        // Check for thread termination request
+        if(s_nfds == PAL_SOCKETS_TERMINATE)
+        {
+            result = pal_osMutexRelease(s_mutexSocketCallbacks);
+            if (result != PAL_SUCCESS)
+            {
+                PAL_LOG(ERR, "Error in async socket manager on mutex release during termination");
+            }
+            s_nfds = 0; // Reset s_ndfs
+            s_socketThreadTerminateSignaled = true; // mark that the thread has receieved the termination request
+            // Break out of while(1)
+            break;
+        }
+        // Update the list of sockets to watch from the global list
+        nfds = s_nfds;
+        if(nfds)
+        {
+            memcpy(callbacks, s_callbacks, nfds*sizeof(callbacks[0]));
+            memcpy(callbackArgs, s_callbackArgs, nfds * sizeof(void*));
+            memcpy(fds, s_fds, nfds*sizeof(fds[0]));
+
+            for (int i=0; i < nfds; i++)
+            {
+                fds[i].events = POLLIN|POLLOUT|POLLRDHUP|POLLERR;
+                fds[i].revents = 0;
+                s_callbackFilter[i] = 0;
+            }
+        }
+        result = pal_osMutexRelease(s_mutexSocketCallbacks);
+        if (result != PAL_SUCCESS)
+        {
+            PAL_LOG(ERR, "Error in async socket manager on mutex release");
+            break;
+        }
+
+        // Wait for a socket event or pthread_kill(s_pollThread, SIGUSR1) event
+        lastUSRCounter = s_palUSR1Counter;
+        res = ppoll(&fds[0], nfds, &timeout_zero, &blockedSignals);
+
+
+        // Notes:
+        // If a POLLIN event occurred and recv from the socket results in 0 bytes being read, it means that
+        // the remote socket was closed. Unless this is dealt with in the callback (for example by closing the
+        // socket) the next call to ppoll will also immediately return with the same result.
+        if(res >0 || errno == EINTR)
+        {
+            unsigned int i;
+            errno = 0;
+            // Some event was triggered, so iterate over all watched fds's and call the relevant callbacks.
+                if (lastIOCounter< s_palIOCounter)
+                {
+                    lastIOCounter = s_palIOCounter;
+                    for( i = 0; i < nfds; i++)
+                    {
+                        if(fds[i].revents)
+                        {
+                            uint32_t filter = POLLOUT|POLLHUP; // filter for specific event that is triggered for non-connected sockets- this event combination shouldn't exist in an active socket.
+
+
+                            if ((fds[i].revents != filter) && ((fds[i].revents != POLLOUT) || (fds[i].revents != s_callbackFilter[i])) ) // this is handlign for a special scenario when a specific event which shouldnt happen is sent to all unconnected sockets in Linux triggering an unwanted callback.
+                            {
+                                callbacks[i](callbackArgs[i]);
+                            }
+                            result = pal_osMutexWait(s_mutexSocketEventFilter, PAL_RTOS_WAIT_FOREVER);
+                            if (PAL_SUCCESS != result)
+                            {
+                                PAL_LOG(ERR, "error waiting for mutex");
+                            }
+                            else
+                            {
+                                s_callbackFilter[i] = fds[i].revents;
+                                result = pal_osMutexRelease(s_mutexSocketEventFilter);
+                                if (PAL_SUCCESS != result)
+                                {
+                                    PAL_LOG(ERR, "error releasing mutex");
+                                }
+                            }
+
+
+                        }
+                    }
+                }
+
+
+        }
+        else if (res == 0)
+        {
+            // Timeout
+        }
+        else
+        {
+            PAL_LOG(ERR, "Error in async socket manager");
+        }
+    }  // while
+}
+#endif // PAL_NET_ASYNCHRONOUS_SOCKET_API
+
+PAL_PRIVATE palStatus_t pal_plat_SockAddrToSocketAddress(const palSocketAddress_t* palAddr, struct sockaddr* output)
+{
+    palStatus_t result = PAL_SUCCESS;
+    uint16_t port = 0;
+    bool found = false;
+
+    result = pal_getSockAddrPort(palAddr, &port);
+    if (result != PAL_SUCCESS)
+    {
+        return result;
+    }
+
+#if PAL_SUPPORT_IP_V4
+    if (PAL_AF_INET == palAddr->addressType)
+    {
+        palIpV4Addr_t ipV4Addr = { 0 };
+        struct sockaddr_in* ip4addr = (struct sockaddr_in*)output;
+        ip4addr->sin_family = AF_INET;
+        ip4addr->sin_port = PAL_HTONS(port);
+        result = pal_getSockAddrIPV4Addr(palAddr, ipV4Addr);
+        if (result == PAL_SUCCESS)
+        {
+            memcpy(&ip4addr->sin_addr, ipV4Addr, sizeof(ip4addr->sin_addr));
+        }
+        found = true;
+    }
+
+#endif // PAL_SUPPORT_IP_V4
+#if PAL_SUPPORT_IP_V6
+    if (PAL_AF_INET6 == palAddr->addressType)
+    {
+        palIpV6Addr_t ipV6Addr = {0};
+        struct sockaddr_in6* ip6addr = (struct sockaddr_in6*)output;
+        ip6addr->sin6_family = AF_INET6;
+        ip6addr->sin6_scope_id = 0; // we assume there will not be several interfaces with the same IP.
+        ip6addr->sin6_flowinfo = 0;
+        ip6addr->sin6_port = PAL_HTONS(port);
+        result = pal_getSockAddrIPV6Addr(palAddr, ipV6Addr);
+        if (result == PAL_SUCCESS)
+        {
+            memcpy(&ip6addr->sin6_addr, ipV6Addr, sizeof(ip6addr->sin6_addr));
+        }
+        found = true;
+    }
+#endif
+
+    if (false == found)
+    {
+        return PAL_ERR_SOCKET_INVALID_ADDRESS;
+    }
+
+    return result;
+}
+
+PAL_PRIVATE palStatus_t pal_plat_socketAddressToPalSockAddr(struct sockaddr* input, palSocketAddress_t* out, palSocketLength_t* length)
+{
+    palStatus_t result = PAL_SUCCESS;
+    bool found = false;
+
+#if PAL_SUPPORT_IP_V4
+    if (input->sa_family == AF_INET)
+    {
+        palIpV4Addr_t ipV4Addr;
+        struct sockaddr_in* ip4addr = (struct sockaddr_in*)input;
+
+        memcpy(ipV4Addr, &ip4addr->sin_addr, PAL_IPV4_ADDRESS_SIZE);
+        result = pal_setSockAddrIPV4Addr(out, ipV4Addr);
+        if (result == PAL_SUCCESS)
+        {
+            result = pal_setSockAddrPort(out, PAL_NTOHS(ip4addr->sin_port));
+        }
+        *length = sizeof(struct sockaddr_in);
+        found = true;
+    }
+#endif //PAL_SUPPORT_IP_V4
+#if PAL_SUPPORT_IP_V6
+    if (input->sa_family == AF_INET6)
+    {
+        palIpV6Addr_t ipV6Addr;
+        struct sockaddr_in6* ip6addr = (struct sockaddr_in6*)input;
+        memcpy(ipV6Addr, &ip6addr->sin6_addr, PAL_IPV6_ADDRESS_SIZE);
+        result = pal_setSockAddrIPV6Addr(out, ipV6Addr);
+        if (result == PAL_SUCCESS)
+        {
+            result = pal_setSockAddrPort(out, PAL_NTOHS(ip6addr->sin6_port));
+        }
+        *length = sizeof(struct sockaddr_in6);
+        found = true;
+    }
+#endif // PAL_SUPPORT_IP_V6
+
+    if (false == found)
+    { // we got unspeicified in one of the tests, so Don't fail , but don't translate address.  // re-chcking
+        result = PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY;
+    }
+
+    return result;
+}
+
+palStatus_t pal_plat_socketsInit(void* context)
+{
+    PAL_UNUSED_ARG(context);
+    palStatus_t result = PAL_SUCCESS;
+
+    if (s_pal_network_initialized == 1)
+    {
+        return PAL_SUCCESS; // already initialized.
+    }
+
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+
+    result = pal_osMutexCreate(&s_mutexSocketCallbacks);
+    if (result != PAL_SUCCESS)
+    {
+        return result;
+    }
+
+    result = pal_osMutexCreate(&s_mutexSocketEventFilter);
+    if (PAL_SUCCESS != result)
+    {
+        return result;
+    }
+
+
+    result = pal_osSemaphoreCreate(0, &s_socketCallbackSignalSemaphore);
+    if (result != PAL_SUCCESS)
+    {
+        // todo: clean up the mess created so far
+        return result;
+    }
+
+    // Sleep at first wait
+    result = pal_osSemaphoreCreate(0, &s_socketCallbackSemaphore);
+    if (result != PAL_SUCCESS)
+    {
+        if (pal_osMutexDelete(&s_mutexSocketCallbacks) != PAL_SUCCESS) //cleanup allocated resources
+        {
+            // TODO print error using logging mechanism when available.
+        }
+        return result;
+    }
+
+    s_socketThreadTerminateSignaled = false;
+    palThreadID_t threadID = NULLPTR;
+    result = pal_osThreadCreateWithAlloc(asyncSocketManager, NULL, PAL_osPriorityReservedSockets, PAL_NET_TEST_ASYNC_SOCKET_MANAGER_THREAD_STACK_SIZE, NULL, &threadID);
+    if (PAL_SUCCESS != result)
+    {
+        if (PAL_ERR_RTOS_PRIORITY == result)
+        {
+            result = PAL_ERR_SOCKET_OPERATION_NOT_PERMITTED;
+        }
+        else
+        {
+            result = PAL_ERR_SOCKET_GENERIC;
+        }
+    }
+    else
+    {
+        // Wait here for the thread to be initialized.
+        result = pal_osSemaphoreWait(s_socketCallbackSemaphore, PAL_RTOS_WAIT_FOREVER, NULL);
+        if (PAL_SUCCESS != result)
+        {
+            goto end;
+        }
+        result = pal_osSemaphoreDelete(&s_socketCallbackSemaphore);
+        if (PAL_SUCCESS != result)
+        {
+            goto end;
+        }
+    }
+#endif
+
+end:
+    if (PAL_SUCCESS == result)
+    {
+        s_pal_network_initialized = 1;
+    }
+
+
+    return result;
+}
+
+palStatus_t pal_plat_registerNetworkInterface(void* context, uint32_t* interfaceIndex)
+{
+    palStatus_t result = PAL_SUCCESS;
+    uint32_t index = 0;
+    bool found = false;
+
+    for (index = 0; index < s_palNumOfInterfaces; index++) // if specific context already registered return existing index instead of registering again.
+    {
+        if (memcmp(s_palNetworkInterfacesSupported[index].interfaceName, (const char *)context, strlen(s_palNetworkInterfacesSupported[index].interfaceName)) == 0)
+        {
+            found = true;
+            *interfaceIndex = index;
+            break;
+        }
+    }
+    if (false == found)
+    {
+        if (s_palNumOfInterfaces < PAL_MAX_SUPORTED_NET_INTERFACES)
+        {
+            strncpy(s_palNetworkInterfacesSupported[s_palNumOfInterfaces].interfaceName, (const char *)context, PAL_NET_MAX_IF_NAME_LENGTH-1);
+            s_palNetworkInterfacesSupported[s_palNumOfInterfaces].interfaceName[PAL_NET_MAX_IF_NAME_LENGTH-1] = '\0';
+            *interfaceIndex = s_palNumOfInterfaces;
+            ++s_palNumOfInterfaces;
+        }
+        else
+        {
+            result = PAL_ERR_SOCKET_MAX_NUMBER_OF_INTERFACES_REACHED;
+        }
+    }
+
+    return result;
+}
+
+palStatus_t pal_plat_socketsTerminate(void* context)
+{
+    PAL_UNUSED_ARG(context);
+    palStatus_t result = PAL_SUCCESS;
+    palStatus_t firstError = PAL_SUCCESS;
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+    // Critical section to update globals
+    result = pal_osMutexWait(s_mutexSocketCallbacks, PAL_RTOS_WAIT_FOREVER);
+    if (result != PAL_SUCCESS)
+    {
+        // TODO print error using logging mechanism when available.
+        firstError = result;
+    }
+
+    s_nfds = PAL_SOCKETS_TERMINATE;
+    result = pal_osSemaphoreRelease(s_socketCallbackSignalSemaphore);
+    if ((PAL_SUCCESS != result) && (PAL_SUCCESS == firstError))
+    {
+        // TODO print error using logging mechanism when available.
+        firstError = result;
+    }
+    // Tell the poll thread to interrupt so that it can check for termination.
+    if(s_pollThread != NULLPTR)
+    {
+        pthread_kill(s_pollThread, SIGUSR1);
+    }
+    
+    result = pal_osMutexRelease(s_mutexSocketCallbacks);
+    if ((PAL_SUCCESS != result) && (PAL_SUCCESS == firstError))
+    {
+        // TODO print error using logging mechanism when available.
+        firstError = result;
+    }
+
+    while (!s_socketThreadTerminateSignaled)
+    {
+        pal_osDelay(10);
+    }
+
+    result = pal_osSemaphoreDelete(&s_socketCallbackSignalSemaphore);
+    if ((PAL_SUCCESS != result) && (PAL_SUCCESS == firstError))
+    {
+        // TODO print error using logging mechanism when available.
+        firstError = result;
+    }
+
+    result = pal_osMutexDelete(&s_mutexSocketEventFilter);
+    if ((PAL_SUCCESS != result) && (PAL_SUCCESS == firstError))
+    {
+        // TODO print error using logging mechanism when available.
+        firstError = result;
+    }
+
+    result = pal_osMutexDelete(&s_mutexSocketCallbacks);
+    if ((PAL_SUCCESS != result ) && (PAL_SUCCESS == firstError))
+    {
+        // TODO print error using logging mechanism when available.
+        firstError = result;
+    }
+#endif // PAL_NET_ASYNCHRONOUS_SOCKET_API
+
+    s_pal_network_initialized = 0;
+
+    return firstError;
+}
+
+/*
+ * NOTE!!!!
+ * When creating socket in Linux, we ignore interfaceNum provided.
+ * The socket should be bound to interface pal_plat_bind API (bind to address reflects the bound between
+ * socket and interface).
+ */
+palStatus_t pal_plat_socket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palSocket_t* sockt)
+{
+    int result = PAL_SUCCESS;
+    intptr_t sockfd;
+    int sockBehavior = 0;
+
+    PAL_VALIDATE_ARGUMENTS(interfaceNum >= s_palNumOfInterfaces && PAL_NET_DEFAULT_INTERFACE != interfaceNum);
+
+    // These are the same in Linux
+    if(type == PAL_SOCK_STREAM_SERVER)
+    {
+        type = PAL_SOCK_STREAM;
+    }
+
+    // Compile time check that PAL values are the same as Linux values
+    PAL_ASSERT_STATIC(AF_INET == PAL_AF_INET);
+    PAL_ASSERT_STATIC(AF_INET6 == PAL_AF_INET6);
+    PAL_ASSERT_STATIC(AF_UNSPEC == PAL_AF_UNSPEC);
+    PAL_ASSERT_STATIC(SOCK_DGRAM == (unsigned int)PAL_SOCK_DGRAM);
+    PAL_ASSERT_STATIC(SOCK_STREAM == (unsigned int)PAL_SOCK_STREAM);
+
+    if (nonBlockingSocket)
+    {
+        sockBehavior = SOCK_NONBLOCK;
+    }
+
+    // SOCK_NONBLOCK since Linux 2.6.27
+    sockfd = socket(domain, type | sockBehavior , 0);
+    // Note - though it is not an error, if we get sockfd == 0 then we probably (accidentally closed fd 0 somewhere else)
+    if (sockfd == PAL_LINUX_INVALID_SOCKET)
+    {
+        result = translateErrorToPALError(errno);
+    }
+    else
+    {
+        *sockt = (palSocket_t)sockfd;
+    }
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+// Assume input timeout value is in milliseconds.
+palStatus_t pal_plat_setSocketOptions(palSocket_t socket, int optionName, const void* optionValue, palSocketLength_t optionLength)
+{
+    int result = PAL_SUCCESS;
+    int linuxName;
+    PAL_UNUSED_ARG(optionLength);
+
+
+    struct timeval timeout;
+    timeout.tv_sec =  0;
+    timeout.tv_usec = 0;
+
+    switch (optionName)
+    {
+    case PAL_SO_SNDTIMEO:
+        linuxName = SO_SNDTIMEO;
+        timeout.tv_sec = (*(int *)optionValue)/1000 ;
+        timeout.tv_usec = ((*(int *)optionValue)%1000)*1000 ;
+        break;
+    case PAL_SO_RCVTIMEO:
+        linuxName = SO_RCVTIMEO;
+        timeout.tv_sec = (*(int *)optionValue)/1000 ;
+        timeout.tv_usec = ((*(int *)optionValue)%1000)*1000 ;
+        break;
+#ifdef PAL_NET_TCP_AND_TLS_SUPPORT
+    case PAL_SO_KEEPALIVE:
+        linuxName = SO_KEEPALIVE;
+        break;
+    case PAL_SO_KEEPIDLE:
+        linuxName = TCP_KEEPIDLE;
+        break;
+    case PAL_SO_KEEPINTVL:
+        linuxName = TCP_KEEPINTVL;
+        break;
+#endif
+    case PAL_SO_REUSEADDR:
+        linuxName = SO_REUSEADDR;
+        break;
+    default:
+        // Unsupported option
+        result = PAL_ERR_SOCKET_OPTION_NOT_SUPPORTED;
+    }
+
+    if (PAL_SUCCESS == result)
+    {
+        if (PAL_SO_SNDTIMEO == optionName || PAL_SO_RCVTIMEO == optionName)
+        {
+            result = setsockopt ((intptr_t)socket, SOL_SOCKET, linuxName, &timeout, sizeof(timeout));
+        }
+#ifdef PAL_NET_TCP_AND_TLS_SUPPORT
+        else if (PAL_SO_KEEPIDLE == optionName || PAL_SO_KEEPINTVL == optionName)
+        {
+            result = setsockopt ((intptr_t)socket, SOL_TCP, linuxName, (int *)optionValue, optionLength);
+        }
+#endif
+        else
+        {
+            result = setsockopt ((intptr_t)socket, SOL_SOCKET, linuxName, (int *)optionValue, optionLength);
+        }
+
+        if(-1 == result)
+        {
+            result = translateErrorToPALError(errno);
+        }
+    }
+
+    return result;
+}
+
+palStatus_t pal_plat_isNonBlocking(palSocket_t socket, bool* isNonBlocking)
+{
+    int flags = fcntl((intptr_t)socket, F_GETFL);
+
+    if (0 != (flags & O_NONBLOCK))
+    {
+        *isNonBlocking = true;
+    }
+    else
+    {
+        *isNonBlocking = false;
+    }
+    return PAL_SUCCESS;
+}
+
+
+palStatus_t pal_plat_bind(palSocket_t socket, palSocketAddress_t* myAddress, palSocketLength_t addressLength)
+{
+    int result = PAL_SUCCESS;
+    int res = 0;
+    struct sockaddr_storage internalAddr = {0} ;
+
+    result = pal_plat_SockAddrToSocketAddress(myAddress, (struct sockaddr *)&internalAddr);
+    if (result == PAL_SUCCESS)
+    {
+        res = bind((intptr_t)socket, (struct sockaddr *)&internalAddr, addressLength);
+        if (res == -1)
+        {
+            result = translateErrorToPALError(errno);
+        }
+    }
+
+    return result;
+}
+
+
+palStatus_t pal_plat_receiveFrom(palSocket_t socket, void* buffer, size_t length, palSocketAddress_t* from, palSocketLength_t* fromLength, size_t* bytesReceived)
+{
+    palStatus_t result = PAL_SUCCESS;
+    ssize_t res;
+    struct sockaddr_storage internalAddr;
+    socklen_t addrlen;
+
+    clearSocketFilter((intptr_t)socket);
+    addrlen = sizeof(struct sockaddr_storage);
+    res = recvfrom((intptr_t)socket, buffer, length, 0 ,(struct sockaddr *)&internalAddr, &addrlen);
+    if(res == -1)
+    {
+        result = translateErrorToPALError(errno);
+    }
+    else // only return address / bytesReceived in case of success
+    {
+        if ((NULL != from) && (NULL != fromLength))
+        {
+            result = pal_plat_socketAddressToPalSockAddr((struct sockaddr *)&internalAddr, from, fromLength);
+        }
+        *bytesReceived = res;
+    }
+
+    return result;
+}
+
+palStatus_t pal_plat_sendTo(palSocket_t socket, const void* buffer, size_t length, const palSocketAddress_t* to, palSocketLength_t toLength, size_t* bytesSent)
+{
+    palStatus_t result = PAL_SUCCESS;
+    ssize_t res;
+
+    clearSocketFilter((intptr_t)socket);
+    res = sendto((intptr_t)socket, buffer, length, 0, (struct sockaddr *)to, toLength);
+    if(res == -1)
+    {
+        result = translateErrorToPALError(errno);
+    }
+    else
+    {
+        *bytesSent = res;
+    }
+
+    return result;
+}
+
+palStatus_t pal_plat_close(palSocket_t* socket)
+{
+    palStatus_t result = PAL_SUCCESS;
+    int res;
+    unsigned int i,j;
+
+    if  (*socket == (void *)PAL_LINUX_INVALID_SOCKET) // socket already closed - return success.
+    {
+        PAL_LOG(DBG, "socket close called on socket which was already closed");
+        return result;
+    }
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+    // Critical section to update globals
+    result = pal_osMutexWait(s_mutexSocketCallbacks, PAL_RTOS_WAIT_FOREVER);
+    if (result != PAL_SUCCESS)
+    {
+        // TODO print error using logging mechanism when available.
+        return result;
+    }
+
+    for(i= 0 ; i < s_nfds; i++)
+    {
+        // check if we have we found the socket being closed
+        if (s_fds[i].fd == (intptr_t)*socket)
+        {
+            // Remove from async socket list
+            // Close the gap in the socket data structures.
+            for(j = i; j < s_nfds - 1; j++)
+            {
+                s_fds[j].fd = s_fds[j+1].fd;
+                s_fds[j].events = s_fds[j+1].events;
+                s_callbacks[j] = s_callbacks[j+1];
+                s_callbackArgs[j] = s_callbackArgs[j+1];
+            }
+            // Blank out the last one
+            s_fds[j].fd = 0;
+            s_callbacks[j] = 0;
+            s_callbackArgs[j] = 0;
+            s_nfds--;
+            // Tell the poll thread to remove the socket
+            pthread_kill(s_pollThread, SIGUSR1);
+            break;
+        }
+    }
+    result = pal_osMutexRelease(s_mutexSocketCallbacks);
+    if (result != PAL_SUCCESS)
+    {
+        // TODO print error using logging mechanism when available.
+        return result;
+    }
+#endif // PAL_NET_ASYNCHRONOUS_SOCKET_API
+    // In Linux it is ok to close a socket while it is being polled, but may not be on other os's
+    res = close((intptr_t) *socket);
+    if(res == -1)
+        result = translateErrorToPALError(errno);
+    else
+    {
+        *socket = (void *)PAL_LINUX_INVALID_SOCKET;
+    }
+    return result;
+}
+
+palStatus_t pal_plat_getNumberOfNetInterfaces( uint32_t* numInterfaces)
+{
+    *numInterfaces =  s_palNumOfInterfaces;
+    return PAL_SUCCESS;
+}
+
+palStatus_t pal_plat_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t * interfaceInfo)
+{
+    palStatus_t result = PAL_SUCCESS;
+    struct ifaddrs *ifap,*ifa;
+    int res,n;
+    uint32_t found = 0;
+
+    PAL_VALIDATE_ARGUMENTS (interfaceNum >= s_palNumOfInterfaces);
+
+    res = getifaddrs(&ifap);
+    if(res < 0)
+    {
+        result = translateErrorToPALError(errno);
+    }
+    else
+    {
+        for (ifa = ifap, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++)
+        {
+            if (ifa->ifa_addr == NULL)
+                continue;
+            int family = ifa->ifa_addr->sa_family;
+            if (strcmp(s_palNetworkInterfacesSupported[interfaceNum].interfaceName, ifa->ifa_name) == 0)
+            {
+                if (family == AF_INET || family == AF_INET6)
+                {
+                    found = 1;
+                    if (family == AF_INET)
+                    {
+                        interfaceInfo->addressSize = sizeof(struct sockaddr_in);
+                    }
+                    else
+                    {
+                        interfaceInfo->addressSize = sizeof(struct sockaddr_in6);
+                    }
+
+                    strncpy(interfaceInfo->interfaceName, s_palNetworkInterfacesSupported[interfaceNum].interfaceName, strlen(s_palNetworkInterfacesSupported[interfaceNum].interfaceName));
+
+                    result = pal_plat_socketAddressToPalSockAddr(ifa->ifa_addr, &interfaceInfo->address, &interfaceInfo->addressSize);
+
+                    break;
+                }
+            }
+        }
+        // free what was allocated by getifaddrs
+        freeifaddrs(ifap);
+    }
+
+    //interface not found error
+    if (found != 1 && result == PAL_SUCCESS)
+    {
+        PAL_LOG(ERR, "Network failed reading interface info");
+        result = PAL_ERR_GENERIC_FAILURE;
+    }
+
+    return result;
+}
+
+
+#if PAL_NET_TCP_AND_TLS_SUPPORT // functionality below supported only in case TCP is supported.
+palStatus_t pal_plat_listen(palSocket_t socket, int backlog)
+{
+    palStatus_t result = PAL_SUCCESS;
+    int res;
+
+    res = listen((intptr_t)socket,backlog);
+    if(res == -1)
+    {
+        result = translateErrorToPALError(errno);
+    }
+    return result;
+}
+
+
+palStatus_t pal_plat_accept(palSocket_t socket, palSocketAddress_t * address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket)
+{
+    intptr_t res = 0;
+    palStatus_t result = PAL_SUCCESS;
+    struct sockaddr_storage internalAddr = {0} ;
+    socklen_t internalAddrLen = sizeof(internalAddr);
+
+    // XXX: the whole addressLen -concept is broken as the address is fixed size anyway.
+    if (*addressLen < sizeof(palSocketAddress_t))
+    {
+        return PAL_ERR_SOCKET_INVALID_ADDRESS;
+    }
+
+    res = accept((intptr_t)socket,(struct sockaddr *)&internalAddr, &internalAddrLen);
+    if(res == -1)
+    {
+        result = translateErrorToPALError(errno);
+    }
+    else
+    {
+        *acceptedSocket = (palSocket_t*)res;
+        *addressLen = sizeof(palSocketAddress_t);
+        result = pal_plat_socketAddressToPalSockAddr((struct sockaddr *)&internalAddr, address, &internalAddrLen);
+    }
+
+    return result;
+}
+
+
+palStatus_t pal_plat_connect(palSocket_t socket, const palSocketAddress_t* address, palSocketLength_t addressLen)
+{
+    int result = PAL_SUCCESS;
+    int res;
+    struct sockaddr_storage internalAddr = {0} ;
+
+    result = pal_plat_SockAddrToSocketAddress(address, (struct sockaddr *)&internalAddr);
+    if (result == PAL_SUCCESS)
+    {
+        res = connect((intptr_t)socket,(struct sockaddr *)&internalAddr, addressLen);
+        if(res == -1)
+        {
+            result = translateErrorToPALError(errno);
+        }
+    }
+
+    return result;
+}
+
+palStatus_t pal_plat_recv(palSocket_t socket, void *buffer, size_t len, size_t* recievedDataSize)
+{
+    palStatus_t result = PAL_SUCCESS;
+    ssize_t res;
+
+    clearSocketFilter((intptr_t)socket);
+    res = recv((intptr_t)socket, buffer, len, 0);
+    if(res ==  -1)
+    {
+        result = translateErrorToPALError(errno);
+    }
+    else
+    {
+        if (0 == res)
+        {
+            result = PAL_ERR_SOCKET_CONNECTION_CLOSED;
+        }
+        *recievedDataSize = res;
+    }
+    return result;
+}
+
+palStatus_t pal_plat_send(palSocket_t socket, const void *buf, size_t len, size_t *sentDataSize)
+{
+    palStatus_t result = PAL_SUCCESS;
+    ssize_t res;
+
+    clearSocketFilter((intptr_t)socket);
+
+    res = send((intptr_t)socket, buf, len, 0);
+    if(res == -1)
+    {
+        result = translateErrorToPALError(errno);
+    }
+    else
+    {
+        *sentDataSize = res;
+    }
+
+    return result;
+}
+
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+palStatus_t pal_plat_asynchronousSocket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void* callbackArgument, palSocket_t* socket)
+{
+
+    int err;
+    int flags;
+    palStatus_t result = pal_plat_socket(domain,  type,  nonBlockingSocket,  interfaceNum, socket);
+
+
+
+        // initialize the socket to be ASYNC so we get SIGIO's for it
+        // XXX: this needs to be conditionalized as the blocking IO might have some use also.
+        err = fcntl((intptr_t)*socket, F_SETOWN, getpid());
+        assert(err != -1);
+
+        flags = fcntl((intptr_t)*socket, F_GETFL, 0);
+        assert(flags >= 0);
+
+        flags |= O_ASYNC;
+
+        err = fcntl((intptr_t)*socket, F_SETFL, flags);
+
+        if (err == -1)
+        {
+            result = translateErrorToPALError(errno);
+        }
+
+
+    if (result == PAL_SUCCESS)
+    {
+        // Critical section to update globals
+        result = pal_osMutexWait(s_mutexSocketCallbacks, PAL_RTOS_WAIT_FOREVER);
+        if (result != PAL_SUCCESS)
+        {
+            // TODO print error using logging mechanism when available.
+            return result;
+        }
+        s_fds[s_nfds].fd = (intptr_t)*socket;
+        s_fds[s_nfds].events = POLLIN|POLLERR;  //TODO POLLOUT missing is not documented
+        s_callbacks[s_nfds] = callback;
+        s_callbackArgs[s_nfds] = callbackArgument;
+        s_nfds++;
+        result = pal_osMutexRelease(s_mutexSocketCallbacks);
+        if (result != PAL_SUCCESS)
+        {
+            // TODO print error using logging mechanism when available.
+            return result;
+        }
+        // Tell the poll thread to add the new socket
+        pthread_kill(s_pollThread, SIGUSR1);
+    }
+
+    return result;
+
+}
+
+#endif
+
+#if PAL_NET_DNS_SUPPORT
+
+palStatus_t pal_plat_getAddressInfo(const char *url, palSocketAddress_t *address, palSocketLength_t* length)
+{
+    palStatus_t result = PAL_SUCCESS;
+    palSocketAddress_t localAddress = {0};
+    palSocketAddress_t zeroAddress = {0};
+    struct addrinfo *pAddrInf = NULL;
+    struct addrinfo hints = {0};
+    int res;
+    int supportedAddressType1 = 0;
+    int supportedAddressType2 = 0;
+    hints.ai_family = AF_UNSPEC;
+
+#if PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_ANY
+    supportedAddressType1 = AF_INET;
+    supportedAddressType2 = AF_INET6;
+    hints.ai_family = AF_UNSPEC;
+#elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV4_ONLY
+    supportedAddressType1 = AF_INET;
+    supportedAddressType2 = AF_INET;
+    hints.ai_family = AF_INET;
+#elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV6_ONLY
+    supportedAddressType1 = AF_INET6;
+    supportedAddressType2 = AF_INET6;
+    hints.ai_family = AF_INET6;
+#else
+#error PAL_NET_DNS_IP_SUPPORT is not defined to a valid value.
+#endif
+
+    res = getaddrinfo(url, NULL, &hints, &pAddrInf);
+    if(res < 0)
+    {
+        result = translateErrorToPALError(errno);
+    }
+    else
+    {
+        if ((pAddrInf != NULL) && (pAddrInf->ai_family == supportedAddressType1 || pAddrInf->ai_family == supportedAddressType2))
+        {
+            result = pal_plat_socketAddressToPalSockAddr((struct sockaddr*)pAddrInf->ai_addr, &localAddress, length);
+
+            if (0 == memcmp(localAddress.addressData, zeroAddress.addressData, PAL_NET_MAX_ADDR_SIZE) ) // invalid 0 address
+            {
+                result = PAL_ERR_SOCKET_DNS_ERROR;
+            }
+            else
+            {
+                *address = localAddress;
+            }
+        }
+        else
+        {
+            result = PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY;
+        }
+
+        freeaddrinfo(pAddrInf);
+    }
+
+    return result;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/RTOS/pal_plat_rtos.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1310 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#define _GNU_SOURCE // This is for ppoll found in poll.h
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <mqueue.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/utsname.h>
+
+#include "pal.h"
+#include "pal_plat_rtos.h"
+
+ /*
+ * The realtime clock is in nano seconds resolution. This is too much for us, so we use "longer" ticks.
+ * Below are relevant defines.
+ * make sure they all coherent. Can use one at the other, but will add some unneeded calculations.
+ */
+#define NANOS_PER_TICK 100
+#define TICKS_PER_MICRO  10L
+#define TICKS_PER_MILLI  TICKS_PER_MICRO * 1000
+#define TICKS_PER_SECOND TICKS_PER_MILLI * 1000
+
+// priorities must be positive, so shift all by this margin. we might want to do smarter convert.
+#define LINUX_THREAD_PRIORITY_BASE 10
+
+//  message Queues names related staff:
+#define MQ_FILENAME_LEN 10
+
+#ifndef CLOCK_MONOTONIC_RAW //a workaround for the operWRT port that missing this include
+#define CLOCK_MONOTONIC_RAW 4 //http://elixir.free-electrons.com/linux/latest/source/include/uapi/linux/time.h
+#endif
+
+#define PAL_THREAD_PRIORITY_TRANSLATE(x) ((int16_t)(x + 7))
+
+typedef struct palThreadData
+{
+    palThreadFuncPtr userFunction;
+    void* userFunctionArgument;
+} palThreadData_t;
+
+/*
+ * Internal struct to handle timers.
+ */
+struct palTimerInfo
+{
+    struct palTimerInfo *next;
+    timer_t handle;
+    palTimerFuncPtr function;
+    void *funcArgs;
+    palTimerType_t timerType;
+};
+
+
+PAL_PRIVATE char g_mqName[MQ_FILENAME_LEN];
+PAL_PRIVATE int g_mqNextNameNum = 0;
+
+// Mutex to prevent simultaneus modification of the linked list of the timers in g_timerList.
+PAL_PRIVATE palMutexID_t g_timerListMutex = 0;
+
+// A singly linked list of the timers, access may be done only if holding the g_timerListMutex.
+// The list is needed as the timers use async signals and when the signal is finally delivered, the
+// palTimerInfo timer struct may be already deleted. The signals themselves carry pointer to timer,
+// so whenever a signal is received, the thread will look if the palTimerInfo is still on the list,
+// and if it is, uses the struct to find the callback pointer and arguments.
+PAL_PRIVATE volatile struct palTimerInfo *g_timerList = NULL;
+
+extern palStatus_t pal_plat_getRandomBufferFromHW(uint8_t *randomBuf, size_t bufSizeBytes, size_t* actualRandomSizeBytes);
+
+PAL_PRIVATE palStatus_t startTimerThread();
+PAL_PRIVATE palStatus_t stopTimerThread();
+PAL_PRIVATE void palTimerThread(void const *args);
+
+inline PAL_PRIVATE void nextMessageQName()
+{
+    g_mqNextNameNum++;
+    for (int j = 4, divider = 10000; j < 9; j++, divider /= 10)
+    {
+        g_mqName[j] = '0' + (g_mqNextNameNum / divider) %10 ; //just to make sure we don't write more then 1 digit.
+    }
+    g_mqName[9] = '\0';
+}
+
+
+/*! Initiate a system reboot.
+ */
+void pal_plat_osReboot(void)
+{
+    // Syncronize cached files to persistant storage.
+    sync();
+    // Reboot the device
+    reboot(RB_AUTOBOOT);
+}
+
+/*! Initialize all data structures (semaphores, mutexs, memory pools, message queues) at system initialization.
+*	In case of a failure in any of the initializations, the function returns with an error and stops the rest of the initializations.
+* @param[in] opaqueContext The context passed to the initialization (not required for generic CMSIS, pass NULL in this case).
+* \return PAL_SUCCESS(0) in case of success, PAL_ERR_CREATION_FAILED in case of failure.
+*/
+palStatus_t pal_plat_RTOSInitialize(void* opaqueContext)
+{
+    palStatus_t status = PAL_SUCCESS;
+    (void)opaqueContext;
+    strncpy(g_mqName, "/pal00001", MQ_FILENAME_LEN);
+    g_mqNextNameNum = 1;   // used for the next name
+#if (PAL_USE_HW_RTC)
+    status = pal_plat_rtcInit();
+#endif
+
+    // Setup the signal handler thread which will be shared with all the timers
+
+    status = pal_osMutexCreate(&g_timerListMutex);
+
+    if (status == PAL_SUCCESS) {
+
+        sigset_t blocked;
+
+        sigemptyset(&blocked);
+        sigaddset(&blocked, PAL_TIMER_SIGNAL);
+
+        // Make PAL_TIMER_SIGNAL blocked from this thread and the others
+        // created onwards. Note: there is no handler for that on purpose, as
+        // the signal is handled by the timer thread itself by sigwaitinfo().
+        int err = pthread_sigmask(SIG_BLOCK, &blocked, NULL);
+
+        if (err != 0) {
+
+            status = PAL_ERR_SYSCALL_FAILED;
+        }
+    }
+
+    if (status == PAL_SUCCESS) {
+
+        status = startTimerThread();
+    }
+
+    return status;
+}
+
+/*! De-Initialize thread objects.
+ */
+palStatus_t pal_plat_RTOSDestroy(void)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+#if PAL_USE_HW_RTC
+    ret = pal_plat_rtcDeInit();
+#endif
+
+    // Is there really a point to check these, as if the shutdown fails, what can we do?
+    // Nobody is going to call the shutdown again.
+    if (ret == PAL_SUCCESS) {
+        ret = stopTimerThread();
+    }
+
+    if (ret == PAL_SUCCESS) {
+        ret = pal_osMutexDelete(&g_timerListMutex);
+    }
+
+    return ret;
+}
+
+/*return The RTOS kernel system timer counter, in microseconds
+ */
+
+uint64_t pal_plat_osKernelSysTick(void) // optional API - not part of original CMSIS API.
+{
+    /*Using clock_gettime is more accurate, but then we have to convert it to ticks. we are using a tick every 100 nanoseconds*/
+    struct timespec ts;
+    uint64_t ticks;
+    //TODO: error handling
+    clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+
+    ticks = (uint64_t) (ts.tv_sec * (uint64_t)TICKS_PER_SECOND
+            + (ts.tv_nsec / NANOS_PER_TICK));
+    return ticks;
+}
+
+/* Convert the value from microseconds to kernel sys ticks.
+ * This is the same as CMSIS macro osKernelSysTickMicroSec.
+ * since we return microsecods as ticks, just return the value
+ */
+uint64_t pal_plat_osKernelSysTickMicroSec(uint64_t microseconds)
+{
+
+    //convert to nanoseconds
+    return microseconds * TICKS_PER_MICRO;
+}
+
+/*! Get the system tick frequency.
+ * \return The system tick frequency.
+ */
+inline uint64_t pal_plat_osKernelSysTickFrequency(void)
+{
+    /* since we use clock_gettime, with resolution of 100 nanosecond per tick*/
+    return TICKS_PER_SECOND;
+}
+
+PAL_PRIVATE void threadCleanupHandler(void* arg)
+{
+    free(arg);
+}
+
+PAL_PRIVATE void* threadFunction(void* arg)
+{
+    /*
+    * note: even if a thread is only scheduled but has not started running, it will be cancelled only once it starts running and once it reaches a cancellation point, 
+    *       hence the clean up handler will always be executed thus avoiding a memory leak.
+    *       see section 2.9.5 @ http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html
+    */
+    pthread_cleanup_push(threadCleanupHandler, arg); // register a cleanup handler to be executed once the thread is finished/terminated (threads can terminate only when reaching a cancellation point)
+    palThreadData_t* threadData = (palThreadData_t*)arg;
+    threadData->userFunction(threadData->userFunctionArgument);
+    pthread_cleanup_pop(1); // in case the thread has not terminated execute the cleanup handler (passing a non zero value to pthread_cleanup_pop)
+    return NULL;
+}
+
+palStatus_t pal_plat_osThreadCreate(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, palThreadID_t* threadID)
+{
+    palStatus_t status = PAL_ERR_GENERIC_FAILURE;
+    pthread_t sysThreadID = (pthread_t)NULL;
+    struct sched_param schedParam;
+    pthread_attr_t attr;
+    pthread_attr_t* ptrAttr = NULL;
+    palThreadData_t* threadData;
+    int err = pthread_attr_init(&attr);
+    if (0 != err)
+    {
+        goto finish;
+    }
+    ptrAttr = &attr;
+
+    err = pthread_attr_setstacksize(ptrAttr, stackSize);
+    if (0 != err)
+    {
+        goto finish;
+    }
+
+    err = pthread_attr_setschedpolicy(ptrAttr, SCHED_RR);
+    if (0 != err)
+    {
+        goto finish;
+    }
+
+#if (PAL_SIMULATOR_TEST_ENABLE == 0) // disable ONLY for Linux PC simulator 
+    err = pthread_attr_setinheritsched(ptrAttr, PTHREAD_EXPLICIT_SCHED);
+    if (0 != err)
+    {
+        goto finish;
+    }
+#endif    
+    
+    err = pthread_attr_setdetachstate(ptrAttr, PTHREAD_CREATE_DETACHED);
+    if (0 != err)
+    {
+        goto finish;
+    }    
+    
+    schedParam.sched_priority = PAL_THREAD_PRIORITY_TRANSLATE(priority);
+    err = pthread_attr_setschedparam(ptrAttr, &schedParam);
+    if (0 != err)
+    {
+        goto finish;
+    }
+
+    threadData = (palThreadData_t*)malloc(sizeof(palThreadData_t));
+    if (NULL == threadData)
+    {
+        status = PAL_ERR_RTOS_RESOURCE;
+        goto finish;
+    }
+    threadData->userFunction = function;
+    threadData->userFunctionArgument = funcArgument;
+
+    err = pthread_create(&sysThreadID, ptrAttr, threadFunction, (void*)threadData);
+    if (0 != err)
+    {        
+        free(threadData);
+        status = (EPERM == err) ? PAL_ERR_RTOS_PRIORITY : PAL_ERR_RTOS_RESOURCE;
+        goto finish;
+    }
+
+    *threadID = (palThreadID_t)sysThreadID;
+    status = PAL_SUCCESS;
+
+finish:
+    if (NULL != ptrAttr)
+    {
+        err = pthread_attr_destroy(ptrAttr);
+        if (0 != err)
+        {
+            PAL_LOG(ERR, "pal_plat_osThreadCreate failed to destroy pthread_attr_t\n");
+        }
+    }
+    return status;
+}
+
+palThreadID_t pal_plat_osThreadGetId(void)
+{
+    palThreadID_t threadID = (palThreadID_t)pthread_self();
+    return threadID;
+}
+
+palStatus_t pal_plat_osThreadTerminate(palThreadID_t* threadID)
+{
+    palStatus_t status = PAL_ERR_RTOS_TASK;
+    int err;
+    pthread_t sysThreadID = (pthread_t)*threadID;
+    if (!pthread_equal(pthread_self(), sysThreadID)) // self termination not allowed
+    {
+        err = pthread_cancel(sysThreadID);
+        if ((0 == err) || (ESRCH == err))
+        {
+            status = PAL_SUCCESS;
+        }
+        else
+        {
+            status = PAL_ERR_RTOS_RESOURCE;
+        }
+    }
+    return status;
+}
+
+/*! Wait for a specified period of time in milliseconds.
+ *
+ * @param[in] milliseconds The number of milliseconds to wait before proceeding.
+ *
+ * \return The status in the form of palStatus_t; PAL_SUCCESS(0) in case of success, a negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_osDelay(uint32_t milliseconds)
+{
+    struct timespec sTime;
+    struct timespec rTime; // this will return how much sleep time still left in case of interrupted sleep
+    int stat;
+    //init rTime, as we will copy it over to stime inside the do-while loop.
+    rTime.tv_sec = milliseconds / 1000;
+    rTime.tv_nsec = PAL_MILLI_TO_NANO(milliseconds);
+
+    do
+    {
+        sTime.tv_sec = rTime.tv_sec;
+        sTime.tv_nsec = rTime.tv_nsec;
+        stat = nanosleep(&sTime, &rTime);
+    } while ((-1 == stat) && (EINTR ==errno)) ;
+    return (stat == 0) ? PAL_SUCCESS : PAL_ERR_GENERIC_FAILURE;
+}
+
+
+/*
+* Internal struct to handle timers.
+*/
+
+typedef struct palTimerThreadContext
+{
+    // semaphore used for signaling both the thread startup and thread closure
+    palSemaphoreID_t startStopSemaphore;
+
+    // If set, the timer thread will stop its loop, signal the startStopSemaphore
+    // and run out of thread function. This is set and accessed while holding the
+    // g_timerListMutex.
+    volatile bool threadStopRequested;
+
+} palTimerThreadContext_t;
+
+
+static palThreadID_t s_palHighResTimerThreadID = NULLPTR;
+static palTimerThreadContext_t s_palTimerThreadContext = {0};
+
+/*
+* Thread for handling the signals from all timers by calling the attached callback
+*/
+
+PAL_PRIVATE void palTimerThread(void const *args)
+{
+    palTimerThreadContext_t* context = (palTimerThreadContext_t*)args;
+
+    int err = 0;
+
+    sigset_t signal_set_to_wait;
+
+    sigemptyset(&signal_set_to_wait);
+    sigaddset(&signal_set_to_wait, PAL_TIMER_SIGNAL);
+
+    // signal the caller that thread has started
+    pal_osSemaphoreRelease(context->startStopSemaphore);
+
+    // loop until signaled with threadStopRequested
+    while (1) {
+
+        siginfo_t info;
+
+        // wait for signal from a timer
+        err = sigwaitinfo(&signal_set_to_wait, &info);
+
+        // A positive return value is the signal number, negative value is a sign of some
+        // signal handler interrupting the OS call and errno should be then EINTR.
+        // The other two documented errors, EAGAIN or EINVAL should not happen as we're
+        // not using the timeout, but have them logged just in case.
+        if (err <= 0) {
+            if (errno != EINTR) {
+                PAL_LOG(ERR, "palTimerThread: sigwaitinfo failed with %d\n", errno);
+            }
+        } else {
+
+            // before using the timer list or threadStopRequested flag, we need to claim the mutex
+            pal_osMutexWait(g_timerListMutex, PAL_RTOS_WAIT_FOREVER);
+
+            if (context->threadStopRequested) {
+
+                // release mutex and bail out
+                pal_osMutexRelease(g_timerListMutex);
+                break;
+
+            } else {
+
+                // the sival_ptr contains the pointer of timer which caused it
+                struct palTimerInfo* signal_timer = (struct palTimerInfo*)info.si_value.sival_ptr;
+
+                struct palTimerInfo *temp_timer = (struct palTimerInfo*)g_timerList;
+
+                palTimerFuncPtr found_function = NULL;
+                void *found_funcArgs;
+
+                // Check, if the timer still is on the list. It may have been deleted, if the
+                // signal delivery / client callback has taken some time.
+                while (temp_timer != NULL) {
+
+                    if (temp_timer == signal_timer) {
+
+                        // Ok, found the timer from list, backup the parameters as we release
+                        // the mutex after this loop, before calling the callback and the
+                        // temp_timer may very well get deleted just after the mutex is released.
+
+                        found_function = temp_timer->function;
+                        found_funcArgs = temp_timer->funcArgs;
+
+                        break;
+                    } else {
+                        temp_timer = temp_timer->next;
+                    }
+                }
+
+                // Release the list mutex before callback to avoid callback deadlocking other threads
+                // if they try to create a timer.
+                pal_osMutexRelease(g_timerListMutex);
+
+                // the function may be NULL here if the timer was already freed
+                if (found_function) {
+                    // finally call the callback function
+                    found_function(found_funcArgs);
+                }
+            }
+        }
+    }
+
+    // signal the caller that thread is now stopping and it can continue the pal_destroy()
+    pal_osSemaphoreRelease(context->startStopSemaphore);
+}
+
+PAL_PRIVATE palStatus_t startTimerThread()
+{
+    palStatus_t status;
+
+    status = pal_osSemaphoreCreate(0, &s_palTimerThreadContext.startStopSemaphore);
+
+    if (status == PAL_SUCCESS) {
+
+        s_palTimerThreadContext.threadStopRequested = false;
+
+        status = pal_osThreadCreateWithAlloc(palTimerThread, &s_palTimerThreadContext, PAL_osPriorityReservedHighResTimer,
+                                                PAL_RTOS_HIGH_RES_TIMER_THREAD_STACK_SIZE, NULL, &s_palHighResTimerThreadID);
+
+        if (status == PAL_SUCCESS) {
+
+            // the timer thread will signal on semaphore when it has started
+            pal_osSemaphoreWait(s_palTimerThreadContext.startStopSemaphore, PAL_RTOS_WAIT_FOREVER, NULL);
+
+        } else {
+            // cleanup the semaphore
+            pal_osSemaphoreDelete(&s_palTimerThreadContext.startStopSemaphore);
+        }
+    }
+
+    return status;
+}
+
+PAL_PRIVATE palStatus_t stopTimerThread()
+{
+    palStatus_t status;
+
+    union sigval value;
+    value.sival_ptr = NULL;
+
+    status = pal_osMutexWait(g_timerListMutex, PAL_RTOS_WAIT_FOREVER);
+
+    if (status == PAL_SUCCESS) {
+
+        // set the flag to end the thread
+        s_palTimerThreadContext.threadStopRequested = true;
+
+        // ping the timer thread that it should start shutdown
+        pthread_t sysThreadID = (pthread_t)s_palHighResTimerThreadID;
+        int err;
+
+        do {
+
+            err = pthread_sigqueue(sysThreadID, PAL_TIMER_SIGNAL, value);
+
+        } while (err == EAGAIN); // retry (spin, yuck!) if the signal queue is full
+
+        pal_osMutexRelease(g_timerListMutex);
+
+        // pthread_sigqueue() failed, which is a sign of thread being dead, so a wait
+        // on semaphore would cause a deadlock.
+        if (err == 0) {
+
+            // wait for for acknowledgement that timer thread is going down
+            pal_osSemaphoreWait(s_palTimerThreadContext.startStopSemaphore, PAL_RTOS_WAIT_FOREVER, NULL);
+        }
+
+        pal_osSemaphoreDelete(&s_palTimerThreadContext.startStopSemaphore);
+
+        // and clean up the thread
+        status = pal_osThreadTerminate(&s_palHighResTimerThreadID);
+    }
+    return status;
+}
+
+
+/*! Create a timer.
+ *
+ * @param[in] function A function pointer to the timer callback function.
+ * @param[in] funcArgument An argument for the timer callback function.
+ * @param[in] timerType The timer type to be created, periodic or oneShot.
+ * @param[out] timerID The ID of the created timer, zero value indicates an error.
+ *
+ * \return PAL_SUCCESS when the timer was created successfully. A specific error in case of failure.
+ */
+palStatus_t pal_plat_osTimerCreate(palTimerFuncPtr function, void* funcArgument,
+        palTimerType_t timerType, palTimerID_t* timerID)
+{
+
+    palStatus_t status = PAL_SUCCESS;
+    struct palTimerInfo* timerInfo = NULL;
+    {
+        struct sigevent sig;
+        timer_t localTimer;
+
+        if ((NULL == timerID) || (NULL == (void*) function))
+        {
+            return PAL_ERR_INVALID_ARGUMENT;
+        }
+
+        timerInfo = (struct palTimerInfo*) malloc(sizeof(struct palTimerInfo));
+        if (NULL == timerInfo)
+        {
+            status = PAL_ERR_NO_MEMORY;
+            goto finish;
+        }
+
+        timerInfo->function = function;
+        timerInfo->funcArgs = funcArgument;
+        timerInfo->timerType = timerType;
+
+        memset(&sig, 0, sizeof(sig));
+
+        sig.sigev_notify = SIGEV_SIGNAL;
+        sig.sigev_signo = PAL_TIMER_SIGNAL;
+
+        // the signal handler uses this to find the correct timer context
+        sig.sigev_value.sival_ptr = timerInfo;
+
+        int ret = timer_create(CLOCK_MONOTONIC, &sig, &localTimer);
+        if (-1 == ret)
+        {
+            if (EINVAL == errno)
+            {
+                status = PAL_ERR_INVALID_ARGUMENT;
+                goto finish;
+            }
+            if (ENOMEM == errno)
+            {
+                status = PAL_ERR_NO_MEMORY;
+                goto finish;
+            }
+            PAL_LOG(ERR, "Rtos timer create error %d", ret);
+            status = PAL_ERR_GENERIC_FAILURE;
+            goto finish;
+        }
+
+        // managed to create the timer - finish up
+        timerInfo->handle = localTimer;
+        *timerID = (palTimerID_t) timerInfo;
+
+        pal_osMutexWait(g_timerListMutex, PAL_RTOS_WAIT_FOREVER);
+
+        // add the new timer to head of the singly linked list
+        timerInfo->next = (struct palTimerInfo *)g_timerList;
+
+        g_timerList = timerInfo;
+
+        pal_osMutexRelease(g_timerListMutex);
+    }
+    finish: if (PAL_SUCCESS != status)
+    {
+        if (NULL != timerInfo)
+        {
+            free(timerInfo);
+            *timerID = (palTimerID_t) NULL;
+        }
+    }
+    return status;
+}
+
+/* Convert milliseconds into seconds and nanoseconds inside a timespec struct
+ */
+PAL_PRIVATE void convertMilli2Timespec(uint32_t millisec, struct timespec* ts)
+{
+    ts->tv_sec = millisec / 1000;
+    ts->tv_nsec = PAL_MILLI_TO_NANO(millisec);
+}
+
+/*! Start or restart a timer.
+ *
+ * @param[in] timerID The handle for the timer to start.
+ * @param[in] millisec The time in milliseconds to set the timer to.
+ *
+ * \return The status in the form of palStatus_t; PAL_SUCCESS(0) in case of success, a negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_osTimerStart(palTimerID_t timerID, uint32_t millisec)
+{
+    palStatus_t status = PAL_SUCCESS;
+    if (NULL == (struct palTimerInfo *) timerID)
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    struct palTimerInfo* timerInfo = (struct palTimerInfo *) timerID;
+    struct itimerspec its;
+
+    convertMilli2Timespec(millisec, &(its.it_value));
+
+    if (palOsTimerPeriodic == timerInfo->timerType)
+    {
+        convertMilli2Timespec(millisec, &(its.it_interval));
+    }
+    else
+    {  // one time timer
+        convertMilli2Timespec(0, &(its.it_interval));
+    }
+
+    if (-1 == timer_settime(timerInfo->handle, 0, &its, NULL))
+    {
+        status = PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+/*! Stop a timer.
+ *
+ * @param[in] timerID The handle for the timer to stop.
+ *
+ * \return The status in the form of palStatus_t; PAL_SUCCESS(0) in case of success, a negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_osTimerStop(palTimerID_t timerID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    if (NULL == (struct palTimerInfo *) timerID)
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    struct palTimerInfo* timerInfo = (struct palTimerInfo *) timerID;
+    struct itimerspec its;
+
+    // set timer to 0 to disarm it.
+    convertMilli2Timespec(0, &(its.it_value));
+
+    convertMilli2Timespec(0, &(its.it_interval));
+
+    if (-1 == timer_settime(timerInfo->handle, 0, &its, NULL))
+    {
+        status = PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+/*! Delete the timer object
+ *
+ * @param[inout] timerID The handle for the timer to delete. In success, *timerID = NULL.
+ *
+ * \return PAL_SUCCESS when the timer was deleted successfully, PAL_ERR_RTOS_PARAMETER when the timerID is incorrect.
+ */
+palStatus_t pal_plat_osTimerDelete(palTimerID_t* timerID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    if (NULL == timerID)
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    struct palTimerInfo* timerInfo = (struct palTimerInfo *) *timerID;
+
+    if (NULL == timerInfo)
+    {
+        status = PAL_ERR_RTOS_PARAMETER;
+    }
+
+    // the list of timers is protected by a mutex to avoid concurrency issues
+    pal_osMutexWait(g_timerListMutex, PAL_RTOS_WAIT_FOREVER);
+
+    // remove the timer from the list before freeing it
+    struct palTimerInfo *prev_timer = NULL;
+    struct palTimerInfo *temp_timer = (struct palTimerInfo *)g_timerList;
+
+    while (temp_timer) {
+
+        if (temp_timer == timerInfo) {
+            // found the timer from list, now it needs to be removed from there
+
+            if (prev_timer) {
+                // there was a previous item, so update its next to this objects next
+                prev_timer->next = temp_timer->next;
+            } else {
+                // the item was the first/only one, so update the list head instead
+                g_timerList = temp_timer->next;
+            }
+            // all done now
+            break;
+
+        } else {
+            prev_timer = temp_timer;
+            temp_timer = temp_timer->next;
+        }
+    }
+
+    timer_t lt = timerInfo->handle;
+    if (-1 == timer_delete(lt))
+    {
+        status = PAL_ERR_RTOS_RESOURCE;
+    }
+
+    pal_osMutexRelease(g_timerListMutex);
+
+    free(timerInfo);
+    *timerID = (palTimerID_t) NULL;
+
+    return status;
+}
+
+/*! Create and initialize a mutex object.
+ *
+ * @param[out] mutexID The created mutex ID handle, zero value indicates an error.
+ *
+ * \return PAL_SUCCESS when the mutex was created successfully, a specific error in case of failure.
+ */
+palStatus_t pal_plat_osMutexCreate(palMutexID_t* mutexID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    pthread_mutex_t* mutex = NULL;
+    {
+        int ret;
+        if (NULL == mutexID)
+        {
+            return PAL_ERR_INVALID_ARGUMENT;
+        }
+
+        mutex = malloc(sizeof(pthread_mutex_t));
+        if (NULL == mutex)
+        {
+            status = PAL_ERR_NO_MEMORY;
+            goto finish;
+        }
+
+        pthread_mutexattr_t mutexAttr;
+        pthread_mutexattr_init(&mutexAttr);
+        pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_RECURSIVE);
+        ret = pthread_mutex_init(mutex, &mutexAttr);
+
+        if (0 != ret)
+        {
+            if (ENOMEM == ret)
+            {
+                status = PAL_ERR_NO_MEMORY;
+            }
+            else
+            {
+                PAL_LOG(ERR, "Rtos mutex create status %d", ret);
+                status = PAL_ERR_GENERIC_FAILURE;
+            }
+            goto finish;
+        }
+        *mutexID = (palMutexID_t) mutex;
+    }
+    finish: if (PAL_SUCCESS != status)
+    {
+        if (NULL != mutex)
+        {
+            free(mutex);
+        }
+    }
+    return status;
+}
+
+/* Wait until a mutex becomes available.
+ *
+ * @param[in] mutexID The handle for the mutex.
+ * @param[in] millisec The timeout for the waiting operation if the timeout expires before the semaphore is released and an error is returned from the function.
+ *
+ * \return The status in the form of palStatus_t; PAL_SUCCESS(0) in case of success, one of the following error codes in case of failure:
+ * 		  PAL_ERR_RTOS_RESOURCE - Mutex not available but no timeout set.
+ * 		  PAL_ERR_RTOS_TIMEOUT - Mutex was not available until timeout expired.
+ * 		  PAL_ERR_RTOS_PARAMETER - Mutex ID is invalid.
+ * 		  PAL_ERR_RTOS_ISR - Cannot be called from interrupt service routines.
+ */
+palStatus_t pal_plat_osMutexWait(palMutexID_t mutexID, uint32_t millisec)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int err;
+    if (NULL == ((pthread_mutex_t*) mutexID))
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    pthread_mutex_t* mutex = (pthread_mutex_t*) mutexID;
+
+    if (PAL_RTOS_WAIT_FOREVER != millisec)
+    {
+        /* calculate the wait absolute time */
+        struct timespec ts;
+        clock_gettime(CLOCK_REALTIME, &ts);
+
+        ts.tv_sec += (millisec / PAL_MILLI_PER_SECOND);
+        ts.tv_nsec += PAL_MILLI_TO_NANO(millisec);
+        ts.tv_sec += ts.tv_nsec / PAL_NANO_PER_SECOND; // if there is some overflow in the addition of nanoseconds.
+        ts.tv_nsec = ts.tv_nsec % PAL_NANO_PER_SECOND;
+
+        while ((err = pthread_mutex_timedlock(mutex, &ts)) != 0 && err == EINTR)
+        {
+            continue; /* Restart if interrupted by handler */
+        }
+    }
+    else
+    { // wait for ever
+        err = pthread_mutex_lock(mutex);
+    }
+
+    if (0 != err)
+    {
+        if (err == ETIMEDOUT)
+        {
+            status = PAL_ERR_RTOS_TIMEOUT;
+        }
+        else
+        {
+            PAL_LOG(ERR, "Rtos mutex wait status %d", err);
+            status = PAL_ERR_GENERIC_FAILURE;
+        }
+    }
+
+    return status;
+}
+
+/* Release a mutex that was obtained by osMutexWait.
+ *
+ * @param[in] mutexID The handle for the mutex.
+ *
+ * \return The status in the form of palStatus_t; PAL_SUCCESS(0) in case of success, a negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_osMutexRelease(palMutexID_t mutexID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int result = 0;
+
+    pthread_mutex_t* mutex = (pthread_mutex_t*) mutexID;
+    if (NULL == mutex)
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    result = pthread_mutex_unlock(mutex);
+    if (0 != result)
+    {
+        // only reason this might fail - process don't have permission for mutex.
+        PAL_LOG(ERR, "Rtos mutex release failure - %d",result);
+        status = PAL_ERR_GENERIC_FAILURE;
+    }
+    return status;
+}
+
+/*Delete a mutex object.
+ *
+ * @param[inout] mutexID The ID of the mutex to delete. In success, *mutexID = NULL.
+ *
+ * \return PAL_SUCCESS when the mutex was deleted successfully, one of the following error codes in case of failure:
+ * 		  PAL_ERR_RTOS_RESOURCE - Mutex already released.
+ * 		  PAL_ERR_RTOS_PARAMETER - Mutex ID is invalid.
+ * 		  PAL_ERR_RTOS_ISR - Cannot be called from interrupt service routines.
+ * \note After this call, mutex_id is no longer valid and cannot be used.
+ */
+palStatus_t pal_plat_osMutexDelete(palMutexID_t* mutexID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    uint32_t ret;
+    if (NULL == mutexID)
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+    pthread_mutex_t* mutex = (pthread_mutex_t*) *mutexID;
+
+    if (NULL == mutex)
+    {
+        status = PAL_ERR_RTOS_RESOURCE;
+    }
+    ret = pthread_mutex_destroy(mutex);
+    if ((PAL_SUCCESS == status) && (0 != ret))
+    {
+        PAL_LOG(ERR,"pal_plat_osMutexDelete 0x%x",ret);
+        status = PAL_ERR_RTOS_RESOURCE;
+    }
+    if (NULL != mutex)
+    {
+        free(mutex);
+    }
+
+    *mutexID = (palMutexID_t) NULL;
+    return status;
+}
+
+/* Create and initialize a semaphore object.
+ *
+ * Semaphore is shared between threads, but not process.
+ *
+ * @param[in] count The number of available resources.
+ * @param[out] semaphoreID The ID of the created semaphore, zero value indicates an error.
+ *
+ * \return PAL_SUCCESS when the semaphore was created successfully, a specific error in case of failure.
+ */
+palStatus_t pal_plat_osSemaphoreCreate(uint32_t count,
+        palSemaphoreID_t* semaphoreID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    sem_t* semaphore = NULL;
+
+    {
+        if (NULL == semaphoreID)
+        {
+            return PAL_ERR_INVALID_ARGUMENT;
+        }
+        semaphore = malloc(sizeof(sem_t));
+        if (NULL == semaphore)
+        {
+            status = PAL_ERR_NO_MEMORY;
+            goto finish;
+        }
+        /* create the semaphore as shared between threads */
+        int ret = sem_init(semaphore, 0, count);
+        if (-1 == ret)
+        {
+            if (EINVAL == errno)
+            {
+                /* count is too big */
+                status = PAL_ERR_INVALID_ARGUMENT;
+            }
+            else
+            {
+                PAL_LOG(ERR, "Rtos semaphore init error %d", ret);
+                status = PAL_ERR_GENERIC_FAILURE;
+            }
+            goto finish;
+        }
+
+        *semaphoreID = (palSemaphoreID_t) semaphore;
+    }
+    finish: if (PAL_SUCCESS != status)
+    {
+        if (NULL != semaphore)
+        {
+            free(semaphore);
+        }
+        *semaphoreID = (palSemaphoreID_t) NULL;
+    }
+    return status;
+}
+
+/* Wait until a semaphore token becomes available.
+ *
+ * @param[in] semaphoreID The handle for the semaphore.
+ * @param[in] millisec The timeout for the waiting operation if the timeout expires before the semaphore is released and an error is returned from the function.
+ * @param[out] countersAvailable The number of semaphores available (before the wait), if semaphores are not available (timeout/error) zero is returned.
+ *
+ * \return The status in the form of palStatus_t; PAL_SUCCESS(0) in case of success, one of the following error codes in case of failure:
+ * 		PAL_ERR_RTOS_TIMEOUT - Semaphore was not available until timeout expired.
+ *	    PAL_ERR_RTOS_PARAMETER - Semaphore ID is invalid.
+ *	    PAL_ERR_INVALID_ARGUMENT - countersAvailable is NULL
+ *
+ *	    NOTES: 1. counterAvailable returns 0 in case there are no semaphores available or there are other threads waiting on it.
+ *	              Value is not thread safe - it might be changed by the time it is read/returned.
+ *	           2. timed wait is using absolute time.
+ */
+palStatus_t pal_plat_osSemaphoreWait(palSemaphoreID_t semaphoreID,
+        uint32_t millisec, int32_t* countersAvailable)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int tmpCounters = 0;
+    {
+        int err;
+        sem_t* sem = (sem_t*) semaphoreID;
+        if ((NULL == sem))
+        {
+            return PAL_ERR_INVALID_ARGUMENT;
+        }
+
+        if (PAL_RTOS_WAIT_FOREVER != millisec)
+        {
+            /* calculate the wait absolute time */
+            struct timespec ts;
+            clock_gettime(CLOCK_REALTIME, &ts);
+            ts.tv_sec += millisec / PAL_MILLI_PER_SECOND;
+            ts.tv_nsec += PAL_MILLI_TO_NANO(millisec);
+            ts.tv_sec += ts.tv_nsec / PAL_NANO_PER_SECOND; // in case there is overflow in the nanoseconds.
+            ts.tv_nsec = ts.tv_nsec % PAL_NANO_PER_SECOND;
+
+            while ((err = sem_timedwait(sem, &ts)) == -1 && errno == EINTR)
+                continue; /* Restart if interrupted by handler */
+        }
+        else
+        { // wait for ever
+            do
+            {
+                err = sem_wait(sem);
+
+                /* loop again if the wait was interrupted by a signal */
+            } while ((err == -1) && (errno == EINTR));
+        }
+
+        if (-1 == err)
+        {
+            tmpCounters = 0;
+            if (errno == ETIMEDOUT)
+            {
+                status = PAL_ERR_RTOS_TIMEOUT;
+            }
+            else
+            { /* seems this is not a valid semaphore */
+                status = PAL_ERR_RTOS_PARAMETER;
+            }
+            goto finish;
+        }
+        /* get the counter number, shouldn't fail, as we already know this is valid semaphore */
+        sem_getvalue(sem, &tmpCounters);
+    }
+    finish:
+    if (NULL != countersAvailable)
+    {
+        *countersAvailable = tmpCounters;
+    }
+    return status;
+}
+
+/*! Release a semaphore token.
+ *
+ * @param[in] semaphoreID The handle for the semaphore.
+ *
+ * \return The status in the form of palStatus_t; PAL_SUCCESS(0) in case of success, a negative value indicating a specific error code in case of failure.
+ */
+palStatus_t pal_plat_osSemaphoreRelease(palSemaphoreID_t semaphoreID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    sem_t* sem = (sem_t*) semaphoreID;
+
+    if (NULL == sem)
+    {
+        return PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    if (-1 == sem_post(sem))
+    {
+        if (EINVAL == errno)
+        {
+            status = PAL_ERR_RTOS_PARAMETER;
+        }
+        else
+        { /* max value of semaphore exeeded */
+            PAL_LOG(ERR, "Rtos semaphore release error %d", errno);
+            status = PAL_ERR_GENERIC_FAILURE;
+        }
+    }
+
+    return status;
+}
+
+/*! Delete a semaphore object.
+ *
+ * @param[inout] semaphoreID: The ID of the semaphore to delete. In success, *semaphoreID = NULL.
+ *
+ * \return PAL_SUCCESS when the semaphore was deleted successfully, one of the following error codes in case of failure:
+ * 		  PAL_ERR_RTOS_RESOURCE - Semaphore already released.
+ * 		  PAL_ERR_RTOS_PARAMETER - Semaphore ID is invalid.
+ * \note After this call, the semaphore_id is no longer valid and cannot be used.
+ */
+palStatus_t pal_plat_osSemaphoreDelete(palSemaphoreID_t* semaphoreID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    {
+        if (NULL == semaphoreID)
+        {
+            return PAL_ERR_INVALID_ARGUMENT;
+        }
+
+        sem_t* sem = (sem_t*) (*semaphoreID);
+        if (NULL == sem)
+        {
+            status = PAL_ERR_RTOS_RESOURCE;
+            goto finish;
+        }
+        if (-1 == sem_destroy(sem))
+        {
+            status = PAL_ERR_RTOS_PARAMETER;
+            goto finish;
+        }
+
+        if (NULL != sem)
+        {
+            free(sem);
+        }
+        *semaphoreID = (palSemaphoreID_t) NULL;
+    }
+    finish: return status;
+}
+
+/*! Perform an atomic increment for a signed32 bit value.
+ *
+ * @param[in,out] valuePtr The address of the value to increment.
+ * @param[in] increment The number by which to increment.
+ *
+ * \returns The value of the valuePtr after the increment operation.
+ */
+int32_t pal_plat_osAtomicIncrement(int32_t* valuePtr, int32_t increment)
+{
+    int32_t res = __sync_add_and_fetch(valuePtr, increment);
+    return res;
+}
+
+
+void *pal_plat_malloc(size_t len)
+{
+    return malloc(len);
+}
+
+
+void pal_plat_free(void * buffer)
+{
+    return free(buffer);
+}
+
+palStatus_t pal_plat_osRandomBuffer(uint8_t *randomBuf, size_t bufSizeBytes, size_t* actualRandomSizeBytes)
+{
+    palStatus_t status = PAL_SUCCESS;
+	status = pal_plat_getRandomBufferFromHW(randomBuf, bufSizeBytes, actualRandomSizeBytes);
+    return status;
+}
+
+#if (PAL_USE_HW_RTC)
+#include <linux/rtc.h>
+#include <sys/ioctl.h>
+#include <time.h>
+palMutexID_t rtcMutex = NULLPTR;
+
+#if RTC_PRIVILEGE
+static const char default_rtc[] = "/dev/rtc0";
+
+PAL_PRIVATE  uint64_t pal_convertTimeStructToSeconds(const struct rtc_time *dateTime)
+{
+    /* Number of days from begin of the non Leap-year*/
+    uint64_t monthDays[] = {0, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};
+    uint64_t seconds, daysCount = 0;
+    /* Compute number of days from 1970 till given year*/
+    daysCount = (dateTime->tm_year + 1900 - 1970) * PAL_DAYS_IN_A_YEAR;
+    /* Add leap year days */
+    daysCount += (((dateTime->tm_year + 1900) / 4) - (1970U / 4));
+    /* Add number of days till given month*/
+    daysCount += monthDays[dateTime->tm_mon];
+    /* Add days in given month minus one */
+    daysCount += (dateTime->tm_mday - 1);
+    if (!(((dateTime->tm_year + 1900) & 3U)) && (dateTime->tm_mon <= 2U))
+    {
+    	daysCount--;
+    }
+
+    seconds = (daysCount * PAL_SECONDS_PER_DAY) + (dateTime->tm_hour * PAL_SECONDS_PER_HOUR) +
+              (dateTime->tm_min * PAL_SECONDS_PER_MIN) + dateTime->tm_sec;
+
+    return seconds;
+}
+#endif
+
+palStatus_t pal_plat_osGetRtcTime(uint64_t *rtcGetTime)
+{
+	palStatus_t ret = PAL_SUCCESS;
+#if RTC_PRIVILEGE
+    struct rtc_time GetTime ={0};
+    if(rtcGetTime != NULL)
+    {
+        int fd, retval = 0;
+        fd = open(default_rtc, O_RDONLY);
+        if (fd == -1)
+        {
+            ret = PAL_ERR_RTOS_RTC_OPEN_DEVICE_ERROR;
+        }
+        else
+        {
+            retval = ioctl(fd, RTC_RD_TIME , &GetTime);
+            if (retval == -1)
+            {
+                ret = PAL_ERR_RTOS_RTC_OPEN_IOCTL_ERROR;
+            }
+            else
+            {
+                *rtcGetTime = pal_convertTimeStructToSeconds(&GetTime);
+            }
+            close(fd);
+        }
+    }
+    else
+    {
+        ret = PAL_ERR_NULL_POINTER;
+    }
+#else
+    *rtcGetTime = time(NULL);
+#endif
+    return ret;
+}
+
+palStatus_t pal_plat_osSetRtcTime(uint64_t rtcSetTime)
+{
+	palStatus_t ret = 0;
+	int retval = 0;
+#if RTC_PRIVILEGE
+    int fd = 0;
+    int retval = 0;
+    struct tm * convertedTime = gmtime((time_t*)&rtcSetTime);
+
+    fd = open (default_rtc, O_RDONLY);
+    retval = ioctl(fd, RTC_SET_TIME, (struct rtc_time*)convertedTime);
+    if (retval == -1)
+    {
+        ret = PAL_ERR_RTOS_RTC_OPEN_IOCTL_ERROR;
+    }
+    close(fd);
+#else
+    ret = pal_osMutexWait(rtcMutex, 5 * PAL_MILLI_PER_SECOND * PAL_ONE_SEC);
+    if(ret == PAL_SUCCESS)
+    {
+        retval = stime((time_t*)&rtcSetTime);
+        if (retval == -1)
+        {
+            ret = PAL_ERR_RTOS_NO_PRIVILEGED; //need to give privilege mode "sudo setcap -v cap_sys_time=+epi [filename]"
+        }
+        pal_osMutexRelease(rtcMutex);
+    }
+#endif
+    return ret;
+}
+
+palStatus_t pal_plat_rtcInit(void)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if(NULLPTR == rtcMutex)
+    {
+        ret = pal_osMutexCreate(&rtcMutex);
+    }
+    return ret;
+}
+
+palStatus_t pal_plat_rtcDeInit(void)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if(NULLPTR != rtcMutex)
+    {
+        ret = pal_osMutexDelete(&rtcMutex);
+        rtcMutex = NULLPTR;
+    }
+    return ret;
+}
+
+#endif //#if (PAL_USE_HW_RTC)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Storage/FileSystem/pal_plat_fileSystem.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,621 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/mount.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <dirent.h>
+#include <stdlib.h>
+
+//PAL Includes
+#include "pal.h"
+#include "pal_plat_fileSystem.h"
+#include "pal_plat_rtos.h"
+
+
+#define PAL_FS_COPY_BUFFER_SIZE 256                                                            //!< Size of the chunk to copy files
+
+PAL_PRIVATE const char* g_platOpenModeConvert[] = {"0", "r", "r+", "w+x", "w+"};                    //!< platform convert table for \b fopen() modes
+PAL_PRIVATE const int g_platSeekWhenceConvert[] = {0, SEEK_SET, SEEK_CUR, SEEK_END};                //!< platform convert table for \b fseek() relative position modes
+
+
+
+/*! \brief This function find the next file in a directory
+ *
+ * @param[in]    *dh - Directory handler to an open DIR
+ * @param[out]    CurrentEntry - entry for the file found in Directory (pre allocated)
+ *
+ * \return true - upon successful operation.\n
+ *
+ */
+PAL_PRIVATE bool pal_plat_findNextFile(DIR *dh, struct dirent ** CurrentEntry);
+
+/*! \brief This function translate the platform errors opcode to pal error codes
+ *
+ * @param[in]    errorOpCode - platform opcode to be translated
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+ */
+PAL_PRIVATE palStatus_t pal_plat_errorTranslation (int errorOpCode);
+
+
+/*! \brief This function build the full path name by adding the filename to the working path given in pathName arg
+ *
+ * @param[in]    *pathName - pointer to the null-terminated string that specifies the directory name.
+ * @param[in]   *fileName - pointer to the file name
+ * @param[out]    *fullPath - pointer to the full path including the filename (pre allocated)
+ * @param[in]   fullPathSize - size of fullPath
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+ *         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t
+ *
+ */
+PAL_PRIVATE palStatus_t pal_plat_addFileNameToPath(const char *pathName, const char * fileName, char * fullPath, size_t fullPathSize);
+
+/*! \brief This function copy one file from source folder to destination folder
+*
+* @param[in]  pathNameSrc - Pointer to a null-terminated string that specifies the source dir.
+* @param[in]  pathNameDest - Pointer to a null-terminated string that specifies the destination dir
+* @param[in] fileName - pointer the the file name
+*
+* \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t
+*
+* \note File should not be open.\n
+*         If the Destination file exist then it shall be truncated
+*
+*/
+PAL_PRIVATE palStatus_t pal_plat_fsCpFile(const char *pathNameSrc,  char *pathNameDest, char * fileName);
+
+palStatus_t pal_plat_fsMkdir(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    int platStatus = 0;
+
+    platStatus = mkdir(pathName, 0777);
+    if (platStatus)
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsRmdir(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    if (rmdir(pathName))
+    {
+        if(errno == ENOENT)
+        {
+            ret = PAL_ERR_FS_NO_PATH;
+        }
+        else
+        {
+            ret = pal_plat_errorTranslation(errno);
+        }
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFopen(const char *pathName, pal_fsFileMode_t mode, palFileDescriptor_t *fd)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    *fd = (palFileDescriptor_t)fopen(pathName, g_platOpenModeConvert[mode]);
+    if ((*fd) == NULLPTR)
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFclose(palFileDescriptor_t *fd)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if (fclose((FILE *)*fd))
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFread(palFileDescriptor_t *fd, void * buffer, size_t numOfBytes, size_t *numberOfBytesRead)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    *numberOfBytesRead = fread(buffer, 1, numOfBytes, (FILE *)*fd);
+    if (*numberOfBytesRead != numOfBytes)
+    {
+        if (ferror((FILE *)*fd))
+        {
+            ret = PAL_ERR_FS_ERROR;
+        }
+        clearerr((FILE *)*fd);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFwrite(palFileDescriptor_t *fd, const void *buffer, size_t numOfBytes, size_t *numberOfBytesWritten)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    *numberOfBytesWritten = fwrite(buffer, 1, numOfBytes, (FILE *)*fd);
+    errno = 0;
+    if (*numberOfBytesWritten != numOfBytes)
+    {
+        ret = pal_plat_errorTranslation(errno);
+        if(ret == PAL_SUCCESS)
+        {
+            ret = PAL_ERR_FS_ACCESS_DENIED;
+        }
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFseek(palFileDescriptor_t *fd, int32_t offset, pal_fsOffset_t whence)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if (fseek((FILE *)*fd, offset, g_platSeekWhenceConvert[whence]))
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFtell(palFileDescriptor_t *fd, int32_t * pos)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    long retPos = 0;
+    *pos = 0;
+    retPos = ftell((FILE *)*fd);
+    if (retPos < 0)
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+    else
+    {
+        *pos = retPos;
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsUnlink(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    if (unlink(pathName))
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsRmFiles(const char *pathName)
+{
+    DIR *dh = NULL; //Directory handler
+    palStatus_t ret = PAL_SUCCESS;
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; //Buffer for coping the name and folder
+    struct dirent * currentEntry = NULL; //file Entry
+
+
+    dh = opendir(pathName);
+
+    if (dh)
+    {
+        while(true)
+        {
+            if (!pal_plat_findNextFile(dh, &currentEntry))
+            {
+                ret = PAL_ERR_FS_ERROR_IN_SEARCHING;
+                break;
+            }
+            if (currentEntry)
+            {
+                pal_plat_addFileNameToPath(pathName, currentEntry->d_name, buffer, sizeof(buffer));
+                if (currentEntry->d_type == DT_DIR)
+                {
+                    pal_fsRmFiles(buffer);
+                    if (rmdir(buffer))
+                    {
+                        ret = pal_plat_errorTranslation(errno);
+                        break;
+                    }
+                }
+                else
+                {
+                    if (unlink(buffer))
+                    {
+                        ret = pal_plat_errorTranslation(errno);
+                        break;
+                    }
+                }
+            }
+            else
+            {//End of directory reached  without errors break, close directory and exit
+                break;
+            }
+        }//while()
+    }
+    else//if (dh)
+    {
+        ret = PAL_ERR_FS_NO_PATH;
+    }
+
+    if (dh)
+    {
+        closedir(dh); //Close DIR handler
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsCpFolder(const char *pathNameSrc,  char *pathNameDest)
+{
+    DIR *src_dh = NULL; //Directory for the source Directory handler
+    palStatus_t ret = PAL_SUCCESS;
+    struct dirent * currentEntry = NULL; //file Entry
+
+
+    src_dh = opendir(pathNameSrc);
+    if (src_dh == NULL)
+    {
+        ret = PAL_ERR_FS_NO_PATH;
+    }
+    else 
+    {
+        while(true)
+        {
+            if (!pal_plat_findNextFile(src_dh, &currentEntry))
+            {
+                ret = PAL_ERR_FS_ERROR_IN_SEARCHING;
+                break;
+            }
+            if (currentEntry)
+            {
+                if (currentEntry->d_type == DT_DIR)
+                {
+                    continue;
+                }
+                //copy the file to the destination
+                ret = pal_plat_fsCpFile(pathNameSrc, pathNameDest, currentEntry->d_name);
+                if (ret != PAL_SUCCESS)
+                {
+                    break;
+                }
+            }
+            else
+            {//End of directory reached  without errors break and close directory and exit
+                break;
+            }
+        }//while()
+    }
+
+    if (src_dh)
+    {
+        closedir(src_dh);
+    }
+    return ret;
+}
+
+
+PAL_PRIVATE palStatus_t pal_plat_fsCpFile(const char *pathNameSrc,  char *pathNameDest, char * fileName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    palFileDescriptor_t src_fd = 0;
+    palFileDescriptor_t dst_fd = 0;
+    char buffer_name[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; //Buffer for coping the name and folder
+    char * buffer = NULL;
+    size_t bytesCount = 0;
+
+    //Add file name to path
+    pal_plat_addFileNameToPath(pathNameSrc, fileName, buffer_name, sizeof(buffer_name));
+    src_fd = (palFileDescriptor_t)fopen(buffer_name, g_platOpenModeConvert[PAL_FS_FLAG_READONLY]);
+    if (src_fd == 0)
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+    else
+    {
+        //Add file name to path
+        pal_plat_addFileNameToPath(pathNameDest, fileName, buffer_name, sizeof(buffer_name));
+        dst_fd = (palFileDescriptor_t)fopen(buffer_name, g_platOpenModeConvert[PAL_FS_FLAG_READWRITETRUNC]);
+        if (dst_fd == 0)
+        {
+            ret = pal_plat_errorTranslation(errno);
+        }
+        else
+        {
+            buffer = (char*)pal_plat_malloc(PAL_FS_COPY_BUFFER_SIZE);
+            if (!buffer)
+            {
+                ret = PAL_ERR_RTOS_RESOURCE;
+            }
+        }
+    }
+
+    if (ret == PAL_SUCCESS)
+    {
+        while (1)
+        {
+            ret = pal_fsFread(&src_fd, buffer, PAL_FS_COPY_BUFFER_SIZE, &bytesCount);
+            if (ret != PAL_SUCCESS)
+            {
+                break;
+            }
+
+            //Check if end of file reached
+            if (bytesCount == 0)
+            {
+                break;
+            }
+
+            ret = pal_fsFwrite(&dst_fd, buffer, bytesCount, &bytesCount);
+            if (ret != PAL_SUCCESS)
+            {
+                break;
+            }
+        }
+    }
+
+    if (src_fd != 0)
+    {
+        pal_fsFclose(&src_fd);
+    }
+    if (dst_fd != 0)
+    {
+        pal_fsFclose(&dst_fd);
+    }
+    if (buffer)
+    {
+        pal_plat_free(buffer);
+    }
+    return ret;
+}
+
+
+const char* pal_plat_fsGetDefaultRootFolder(pal_fsStorageID_t dataID)
+{
+    const char* returnedRoot = NULL;
+    if (PAL_FS_PARTITION_PRIMARY == dataID)
+    {
+        returnedRoot = PAL_FS_MOUNT_POINT_PRIMARY;
+    }
+    else if (PAL_FS_PARTITION_SECONDARY == dataID)
+    {
+        returnedRoot = PAL_FS_MOUNT_POINT_SECONDARY;
+    }
+
+    return returnedRoot;
+}
+
+
+PAL_PRIVATE bool pal_plat_findNextFile(DIR *dh, struct dirent ** CurrentEntry)
+{
+    bool ret = true;
+    bool skip = false;
+    bool foundFile = false;
+
+    do
+    {
+        errno = 0;
+        *CurrentEntry = readdir(dh);
+        if (*CurrentEntry)
+        {
+            /* Skip the names "." and ".." as we don't want to remove them. also make sure that the current entry point to REGULER file*/
+            skip = (!strcmp((*CurrentEntry)->d_name, ".")) || (!strcmp((*CurrentEntry)->d_name, ".."));
+            if (skip)
+            {
+                continue;
+            }
+            else
+            {
+                foundFile = true;
+            }
+        }
+        else
+        {//Check if EOF reached
+            if (errno)
+            {//NOT!!! EOF  other error
+                ret = false;
+            }
+            break; //Break from while
+        }
+    }
+    while((!foundFile) && (ret)); //While file has been found or ret is set to false
+    return ret;
+}
+
+PAL_PRIVATE palStatus_t pal_plat_addFileNameToPath(const char *pathName, const char * fileName, char * fullPath, size_t fullPathSize)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if ((strlen(pathName) >= PAL_MAX_FOLDER_DEPTH_CHAR)  || (strlen(fileName) >= PAL_MAX_FULL_FILE_NAME))
+    {
+        ret = PAL_ERR_FS_FILENAME_LENGTH;
+    }
+    else if (fullPath)
+    {
+        strncpy(fullPath, pathName, fullPathSize - 1);
+        fullPath[fullPathSize - 1] = '\0';
+        strncat(fullPath, "/", fullPathSize - strlen(fullPath) - 1);
+        strncat(fullPath, fileName, fullPathSize - strlen(fullPath) - 1);
+    }
+    else
+    {
+        ret = PAL_ERR_RTOS_RESOURCE;
+    }
+    return ret;
+}
+
+
+
+
+PAL_PRIVATE palStatus_t pal_plat_errorTranslation (int errorOpCode)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    switch(errorOpCode)
+    {
+    case 0:
+        break;
+    case EACCES:
+    case EFAULT:
+    case EROFS:
+        ret = PAL_ERR_FS_ACCESS_DENIED;
+        break;
+
+    case EBUSY :
+        ret = PAL_ERR_FS_BUSY;
+        break;
+
+    case EEXIST:
+        ret = PAL_ERR_FS_NAME_ALREADY_EXIST;
+        break;
+
+    case ENAMETOOLONG:
+        ret = PAL_ERR_FS_FILENAME_LENGTH;
+        break;
+
+    case EBADF:
+        ret = PAL_ERR_FS_BAD_FD;
+        break;
+
+    case EINVAL:
+        ret = PAL_ERR_FS_INVALID_ARGUMENT;
+        break;
+
+    case EISDIR:
+        ret = PAL_ERR_FS_FILE_IS_DIR;
+        break;
+
+    case ENOTEMPTY:
+        ret = PAL_ERR_FS_DIR_NOT_EMPTY;
+        break;
+
+    case ENOENT:
+        ret = PAL_ERR_FS_NO_FILE;
+        break;
+
+    default:
+        ret = PAL_ERR_FS_ERROR;
+        break;
+    }
+    return ret;
+}
+
+
+size_t pal_plat_fsSizeCheck(const char *stringToChk)
+{
+    size_t length = 0;
+    length = strlen(stringToChk);
+    return length;
+}
+
+
+palStatus_t pal_plat_fsFormat(pal_fsStorageID_t dataID)
+{
+    char rootFolder[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    palStatus_t result = PAL_SUCCESS;
+    result = pal_fsGetMountPoint(dataID, PAL_MAX_FILE_AND_FOLDER_LENGTH, rootFolder);
+    if (PAL_SUCCESS == result)
+    {
+        int ret;
+        FILE* fp = NULL;
+        char buffer[PAL_FORMAT_CMD_MAX_LENGTH] = {0};
+        char deviceName[PAL_DEVICE_NAME_MAX_LENGTH] = {0};
+        
+		ret = snprintf(buffer, sizeof(buffer),"df -h | grep %s | awk -F\' \' \'{print $1}\' 2>&1",rootFolder); // get the partition name or the error
+		PAL_LOG(DBG,"system call command is %s ret = %d\r\n",buffer,ret);
+		if (ret > 0) // snprintf succeeded
+		{
+			fp = popen(buffer,"r");
+			if (NULL != fp)
+			{
+				if(NULL != fgets(deviceName, sizeof(deviceName),fp))
+				{
+					if (deviceName[strnlen(deviceName, sizeof(deviceName))-1] == '\n')
+					{
+						deviceName[strnlen(deviceName, sizeof(deviceName))-1] = '\0'; // remove the '\n' if found
+					}
+					ret = umount(rootFolder);
+					if (0 == ret)
+					{
+						ret = snprintf(buffer, sizeof(buffer), PAL_FS_FORMAT_COMMAND, PAL_PARTITION_FORMAT_TYPE, deviceName);
+						if (ret > 0)
+						{
+							ret = system(buffer);
+							if (-1 != ret)
+							{
+								ret = mount(deviceName, rootFolder, PAL_PARTITION_FORMAT_TYPE, 0 ,PARTITION_FORMAT_ADDITIONAL_PARAMS);
+								if (ret < 0)
+								{
+									PAL_LOG(ERR,"(%s:%d)cannot mount %s on %s using " PAL_PARTITION_FORMAT_TYPE,__FILE__,__LINE__,deviceName,rootFolder);
+									result = PAL_ERR_GENERIC_FAILURE;
+								}
+							}
+							else
+							{
+								PAL_LOG(ERR,"(%s:%d)system call to format failed ",__FILE__,__LINE__);
+								result = PAL_ERR_SYSCALL_FAILED;
+							}
+						}
+						else
+						{
+							PAL_LOG(ERR,"(%s:%d)cannot create command with snprintf ",__FILE__,__LINE__);
+							result = PAL_ERR_BUFFER_TOO_SMALL;
+						}
+					}
+					else
+					{
+						PAL_LOG(ERR,"(%s:%d)cannot unmount %s",__FILE__,__LINE__,rootFolder);
+						result = PAL_ERR_GENERIC_FAILURE;
+					}
+				}
+
+				else
+				{
+					PAL_LOG(ERR,"(%s:%d)cannot read from pipe",__FILE__,__LINE__);
+					result = PAL_ERR_GENERIC_FAILURE;
+				}
+				pclose(fp);
+			}
+			else
+			{
+				PAL_LOG(ERR,"(%s:%d)popen had failed ",__FILE__,__LINE__);
+				result = PAL_ERR_SYSCALL_FAILED;
+			}
+		}
+		else
+		{
+			PAL_LOG(ERR,"(%s:%d)cannot create command with snprintf ",__FILE__,__LINE__);
+			result = PAL_ERR_BUFFER_TOO_SMALL;
+        }
+    }
+    return result;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/Linux/Update/pal_plat_update.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal_plat_update.h"
+
+
+palStatus_t pal_plat_imageInitAPI(palImageSignalEvent_t CBfunction)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageDeInit(void)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageGetMaxNumberOfImages(uint8_t *imageNumber)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageSetVersion(palImageId_t imageId, const palConstBuffer_t* version)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageGetDirectMemAccess(palImageId_t imageId, void** imagePtr, size_t *imageSizeInBytes)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageActivate(palImageId_t imageId)
+{
+
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageGetActiveHash(palBuffer_t* hash)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageGetActiveVersion (palBuffer_t* version)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageWriteHashToMemory(const palConstBuffer_t* const hashValue)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageSetHeader(palImageId_t imageId, palImageHeaderDeails_t* details)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageReserveSpace(palImageId_t imageId, size_t imageSize)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageWrite(palImageId_t imageId, size_t offset, palConstBuffer_t *chunk)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageReadToBuffer(palImageId_t imageId, size_t offset, palBuffer_t *chunk)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+//
+palStatus_t pal_plat_imageFlush(palImageId_t package_id)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Networking/pal_plat_network.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1260 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#include "pal.h"
+#include "pal_plat_network.h"
+
+#include "mbed.h"
+
+typedef void(*palSelectCallbackFunction_t)();
+
+#if defined (__CC_ARM) || defined(__IAR_SYSTEMS_ICC__)
+
+void palSelectCallbackNull(void* arg)
+{
+}
+
+#define NULL_FUNCTION palSelectCallbackNull
+
+
+#elif defined (__GNUC__)
+
+#define NULL_FUNCTION NULL
+
+#endif
+
+
+#define PAL_SOCKET_OPTION_ERROR (-1)
+
+
+typedef enum {
+    PAL_PLAT_SOCKET_NOT_CONNECTED = 0,
+    PAL_PLAT_SOCKET_CONNECTING = 1,
+    PAL_PLAT_SOCKET_CONNECTED = 2
+
+} palConnectState;
+
+
+void palConnectCallBack()
+{
+}
+
+        class PALSocketWrapper
+        {
+        public:
+            PALSocketWrapper() : initialized(false), activeSocket(NULL), isNonBlockingOnCreation(false), callbackFunction(NULL_FUNCTION), callbackArgument(NULL), selectCallbackFunction(NULL), connectState(PAL_PLAT_SOCKET_NOT_CONNECTED), socketTypeVal(PAL_SOCK_DGRAM), attachCallbackObject(NULL), rxBuffer(0), rxBufferSet(false)
+        {
+
+            }
+            nsapi_error_t initialize(Socket* socket, palSocketType_t socketType,bool isNonBlocking, palAsyncSocketCallback_t callback, void* argument);
+            palAsyncSocketCallback_t getCallback( ) const;
+            void* getCallbackArgument() const ;
+            bool isNonBlocking() const ;
+            bool isConnected() const ;
+            void attachCallback();
+            Socket* getActiveSocket();
+            palSocketType_t getSocketType() const;
+            char getAndResetRxBuffer();
+            bool isRxBufferSet() const;
+            palStatus_t setRxBuffer(char data);
+            void updateCallback(/*palAsyncSocketCallback_t callback, void* argument,*/ palSelectCallbackFunction_t selectCallback);
+            virtual ~PALSocketWrapper()
+            {
+                if (NULL != activeSocket  )
+                {
+                    activeSocket->close();
+                    delete activeSocket;
+                }
+            }
+
+            // nsapi socket funcitons exposed:
+            nsapi_error_t close();
+            nsapi_error_t bind(const SocketAddress &address);
+            void set_blocking(bool blocking);
+            void set_timeout(int timeout);
+            nsapi_error_t setsockopt(int level, int optname, const void *optval, unsigned optlen);
+            nsapi_error_t getsockopt(int level, int optname, void *optval, unsigned *optlen);
+            void attach(mbed::Callback<void()> func);
+            //void sigio(mbed::Callback<void()> func); // switch attach to sigio for verison 5.4
+            // nsapi UDP socket funcitons exposed:
+            nsapi_size_or_error_t recvfrom(SocketAddress *address, void *data, nsapi_size_t size);
+            nsapi_size_or_error_t sendto(const SocketAddress &address, const void *data, nsapi_size_t size);
+            //nsapi TCP socket funcitons exposed:
+            nsapi_error_t connect(const SocketAddress &address);
+            nsapi_size_or_error_t send(const void *data, nsapi_size_t size);
+            nsapi_size_or_error_t recv(void *data, nsapi_size_t size);
+            //nsapi TCP server socket funcitons exposed:
+            nsapi_error_t listen(int backlog = 1);
+            nsapi_error_t accept(TCPSocket *connection, SocketAddress *address = NULL);
+
+
+        private:
+            bool initialized;
+            Socket* activeSocket;
+            bool isNonBlockingOnCreation;
+            palAsyncSocketCallback_t callbackFunction;
+            void* callbackArgument;
+            palSelectCallbackFunction_t selectCallbackFunction;
+            palConnectState connectState;
+            palSocketType_t socketTypeVal;
+            Callback<void()> attachCallbackObject;
+            events::EventQueue* shared_event_queue;
+            char rxBuffer;
+            bool rxBufferSet;
+        };
+
+        void PALSocketWrapper::updateCallback( palSelectCallbackFunction_t selectCallback )
+        {
+            bool shouldSetCallback = false;
+            if ((NULL == selectCallbackFunction) && (NULL == callbackFunction)) //callback already set - no need to set again
+            {
+                shouldSetCallback = true;
+            }
+
+            selectCallbackFunction = selectCallback;
+
+            if ((NULL != selectCallbackFunction) || (NULL != callbackFunction))
+            {
+                if (shouldSetCallback)
+                {
+                    Callback<void()> mycall(this, &PALSocketWrapper::attachCallback);
+                    activeSocket->sigio(mycall);
+                }
+            }
+            else
+            {
+                activeSocket->sigio(NULL);
+            }
+        }
+
+        Socket* PALSocketWrapper::getActiveSocket()
+        {
+            return activeSocket;
+        }
+
+        char PALSocketWrapper::getAndResetRxBuffer()
+        {
+            rxBufferSet = false;
+            return rxBuffer;
+        }
+
+        bool PALSocketWrapper::isRxBufferSet() const
+        {
+            return rxBufferSet;
+        }
+
+        palStatus_t PALSocketWrapper::setRxBuffer( char data)
+        {
+            PAL_VALIDATE_CONDITION_WITH_ERROR((true == rxBufferSet), PAL_ERR_SOCKET_GENERIC);
+
+            rxBuffer = data;
+            rxBufferSet = true;
+
+            return PAL_SUCCESS;
+        }
+
+        palAsyncSocketCallback_t PALSocketWrapper::getCallback() const
+        {
+            return callbackFunction;
+        }
+
+        palSocketType_t  PALSocketWrapper::getSocketType() const
+        {
+            return socketTypeVal;
+        }
+
+
+        void * PALSocketWrapper::getCallbackArgument() const
+        {
+            return callbackArgument;
+        }
+
+        bool PALSocketWrapper::isNonBlocking() const
+        {
+            return isNonBlockingOnCreation;
+        }
+
+        bool PALSocketWrapper::isConnected() const
+        {
+            return ((PAL_PLAT_SOCKET_CONNECTED == connectState) && (PAL_SOCK_STREAM == socketTypeVal));
+        }
+
+        void PALSocketWrapper::attachCallback()
+        {
+            if (NULL != callbackFunction)
+            {
+                // Since the socket callback may be called from interrupt context, depending on the
+                // network interface used, we need to debounce the client callback to happen from
+                // a thread context to keep client side implementation platform agnostic.
+                assert(shared_event_queue);
+                shared_event_queue->call(callbackFunction, callbackArgument);
+            }
+            if (NULL != selectCallbackFunction)
+            {
+                // Note: this is not tested yet
+                assert(shared_event_queue);
+                shared_event_queue->call(selectCallbackFunction);
+            }
+            if (PAL_PLAT_SOCKET_CONNECTING == connectState)
+            {
+                connectState = PAL_PLAT_SOCKET_CONNECTED;// if we got a callback while connecting assume we are connected
+                if (palConnectCallBack == selectCallbackFunction)
+                {
+                    selectCallbackFunction = NULL;
+                }
+            }
+        }
+
+        nsapi_error_t  PALSocketWrapper::initialize(Socket* socket, palSocketType_t socketType, bool isNonBlocking, palAsyncSocketCallback_t callback, void* argument)
+        {
+        // check that we got a valid socket and the socket type is supported
+            PAL_VALIDATE_CONDITION_WITH_ERROR(((true == initialized) || (NULL == socket) ||
+                                              ((socketType != PAL_SOCK_STREAM) && (socketType != PAL_SOCK_STREAM_SERVER) &&
+                                               (socketType != PAL_SOCK_DGRAM))),NSAPI_ERROR_PARAMETER);
+
+
+            // Pre fetch and store the shared queue used for bouncing the callbacks out of interrupt
+            // context, as the user of it may be ran from interrupt and it can't go and start
+            // creating worker threads from there.
+            // Note: the code uses mbed_highprio_event_queue() instead of mbed_event_queue()
+            // as the high priority queue and its thread is likely there already thanks to
+            // arm_hal_timer.cpp. Technically the client side does not really care, if the events
+            // were delayed a bit by other events or not.
+            shared_event_queue = mbed_highprio_event_queue();
+            PAL_VALIDATE_CONDITION_WITH_ERROR((shared_event_queue == NULL),NSAPI_ERROR_UNSUPPORTED);
+
+            Callback<void()> mycall(this, &PALSocketWrapper::attachCallback);
+            attachCallbackObject = mycall;
+            activeSocket = socket;
+            socketTypeVal = socketType;
+            isNonBlockingOnCreation = isNonBlocking;
+            activeSocket->set_blocking(!isNonBlocking);
+            if (NULL != callback)
+            {
+                callbackFunction = callback;
+                callbackArgument = argument;
+                activeSocket->sigio(attachCallbackObject);
+            }
+
+            initialized = true;
+            return NSAPI_ERROR_OK;
+        }
+
+        nsapi_error_t PALSocketWrapper::close()
+        {
+            nsapi_error_t status= NSAPI_ERROR_OK;
+            if (NULL != activeSocket)
+            {
+                status = activeSocket->close();
+                delete activeSocket;
+                activeSocket = NULL;
+            }
+            return  status;
+        }
+
+        nsapi_error_t PALSocketWrapper::bind(const SocketAddress &address)
+        {
+            nsapi_error_t status = NSAPI_ERROR_OK;
+            PAL_VALIDATE_CONDITION_WITH_ERROR((false == initialized), NSAPI_ERROR_PARAMETER);
+            status= activeSocket->bind(address);
+            return  status;
+        }
+
+        void PALSocketWrapper::set_blocking(bool blocking)
+        {
+            activeSocket->set_blocking(blocking);
+        }
+
+        void PALSocketWrapper::set_timeout(int timeout)
+        {
+            activeSocket->set_timeout(timeout);
+        }
+
+        nsapi_error_t PALSocketWrapper::setsockopt(int level, int optname, const void *optval, unsigned optlen)
+        {
+            nsapi_error_t status = NSAPI_ERROR_OK;
+            PAL_VALIDATE_CONDITION_WITH_ERROR((false == initialized),NSAPI_ERROR_PARAMETER);
+            status = activeSocket->setsockopt(level,  optname, optval,  optlen);
+            return  status;
+        }
+
+        nsapi_error_t PALSocketWrapper::getsockopt(int level, int optname, void *optval, unsigned *optlen)
+        {
+            nsapi_error_t status = NSAPI_ERROR_OK;
+            PAL_VALIDATE_CONDITION_WITH_ERROR((false == initialized),NSAPI_ERROR_PARAMETER);
+            status = activeSocket->getsockopt( level,  optname,  optval,  optlen);
+            return  status;
+        }
+
+        void PALSocketWrapper::attach(mbed::Callback<void()> func)
+        {
+            activeSocket->sigio(func);
+        }
+        //void sigio(mbed::Callback<void()> func); // switch attach to sigio for verison 5.4
+        // nsapi UDP socket funcitons exposed:
+        nsapi_size_or_error_t PALSocketWrapper::recvfrom(SocketAddress *address, void *data, nsapi_size_t size)
+        {
+            nsapi_size_or_error_t status = NSAPI_ERROR_OK;
+            PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_DGRAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // udp sockets only
+
+            status = ((UDPSocket*)activeSocket)->recvfrom(address, data,  size);
+            return  status;
+        }
+
+        nsapi_size_or_error_t PALSocketWrapper::sendto(const SocketAddress &address, const void *data, nsapi_size_t size)
+        {
+            nsapi_size_or_error_t status = NSAPI_ERROR_OK;
+            PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_DGRAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // udp sockets only
+            status = ((UDPSocket*)activeSocket)->sendto(address, data, size);
+            return  status;
+        }
+
+        //nsapi TCP socket funcitons exposed:
+        nsapi_error_t PALSocketWrapper::connect(const SocketAddress &address)
+        {
+            nsapi_error_t status = NSAPI_ERROR_OK;
+            PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM != socketTypeVal)), NSAPI_ERROR_PARAMETER);  // tcp sockets only
+
+            connectState = PAL_PLAT_SOCKET_CONNECTING;
+            updateCallback(palConnectCallBack); // make sure callback is enabled to see if we get callback to signal connections end
+            status = ((TCPSocket*)activeSocket)->connect(address);
+            if (status >= 0 || status == NSAPI_ERROR_IS_CONNECTED)
+            {
+                connectState = PAL_PLAT_SOCKET_CONNECTED;
+                updateCallback(NULL); // make sure callback is enabled to see if we get callback to signal connections end
+            }
+            else if ((NSAPI_ERROR_WOULD_BLOCK != status) && (NSAPI_ERROR_IN_PROGRESS != status) && (NSAPI_ERROR_ALREADY != status))
+            {
+                connectState = PAL_PLAT_SOCKET_NOT_CONNECTED;
+            }
+            return  status;
+        }
+
+        nsapi_size_or_error_t PALSocketWrapper::send(const void *data, nsapi_size_t size)
+        {
+            nsapi_size_or_error_t status = NSAPI_ERROR_OK;
+            PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM != socketTypeVal)), NSAPI_ERROR_PARAMETER); // tcp sockets only
+
+            status = ((TCPSocket*)activeSocket)->send( data, size);
+            return  status;
+        }
+
+        nsapi_size_or_error_t PALSocketWrapper::recv(void *data, nsapi_size_t size)
+        {
+            nsapi_size_or_error_t status = NSAPI_ERROR_OK;
+            PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM != socketTypeVal)),NSAPI_ERROR_PARAMETER); // tcp sockets only
+            status = ((TCPSocket*)activeSocket)->recv(data, size);
+            return  status;
+        }
+        //nsapi TCP server socket funcitons exposed:
+        nsapi_error_t PALSocketWrapper::listen(int backlog )
+        {
+            nsapi_error_t status = NSAPI_ERROR_OK;
+            PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM_SERVER != socketTypeVal)), NSAPI_ERROR_PARAMETER); // udp sockets only
+            status = ((TCPServer*)activeSocket)->listen(backlog);
+            return  status;
+        }
+
+        nsapi_error_t PALSocketWrapper::accept(TCPSocket *connection, SocketAddress *address)
+        {
+            nsapi_error_t status = NSAPI_ERROR_OK;
+            PAL_VALIDATE_CONDITION_WITH_ERROR(((false == initialized) || (PAL_SOCK_STREAM_SERVER != socketTypeVal)),NSAPI_ERROR_PARAMETER); // udp sockets only
+
+            status = ((TCPServer*)activeSocket)->accept(connection, address);
+            return  status;
+        }
+
+
+
+
+PAL_PRIVATE NetworkInterface* s_pal_networkInterfacesSupported[PAL_MAX_SUPORTED_NET_INTERFACES] = { 0 };
+
+PAL_PRIVATE  uint32_t s_pal_numberOFInterfaces = 0;
+
+PAL_PRIVATE  uint32_t s_pal_network_initialized = 0;
+
+PAL_PRIVATE palStatus_t translateErrorToPALError(int errnoValue)
+{
+    palStatus_t status;
+    switch (errnoValue)
+    {
+    case NSAPI_ERROR_NO_MEMORY:
+        status = PAL_ERR_NO_MEMORY;
+        break;
+    case NSAPI_ERROR_PARAMETER:
+        status = PAL_ERR_SOCKET_INVALID_VALUE;
+        break;
+    case NSAPI_ERROR_WOULD_BLOCK:
+        status = PAL_ERR_SOCKET_WOULD_BLOCK;
+        break;
+    case NSAPI_ERROR_DNS_FAILURE:
+        status = PAL_ERR_SOCKET_DNS_ERROR;
+        break;
+    case NSAPI_ERROR_DHCP_FAILURE:
+        status = PAL_ERR_SOCKET_HDCP_ERROR;
+        break;
+    case NSAPI_ERROR_AUTH_FAILURE:
+        status = PAL_ERR_SOCKET_AUTH_ERROR;
+        break;
+    case NSAPI_ERROR_NO_ADDRESS:
+        status = PAL_ERR_SOCKET_INVALID_ADDRESS;
+        break;
+    case NSAPI_ERROR_NO_CONNECTION:
+        status = PAL_ERR_SOCKET_NOT_CONNECTED;
+        break;
+    case NSAPI_ERROR_DEVICE_ERROR:
+        status = PAL_ERR_SOCKET_INPUT_OUTPUT_ERROR;
+        break;
+    case NSAPI_ERROR_UNSUPPORTED:
+        status = PAL_ERR_NOT_SUPPORTED;
+        break;
+    case NSAPI_ERROR_NO_SOCKET:
+        status = PAL_ERR_SOCKET_ALLOCATION_FAILED;
+        break;
+    case NSAPI_ERROR_IN_PROGRESS:
+    case NSAPI_ERROR_ALREADY:
+        status = PAL_ERR_SOCKET_IN_PROGRES;
+        break;
+    case NSAPI_ERROR_IS_CONNECTED:
+        status = PAL_SUCCESS;
+        break;
+    default:
+        status = PAL_ERR_SOCKET_GENERIC;
+        break;
+    }
+    return status;
+}
+
+palStatus_t pal_plat_socketsInit(void* context)
+{
+    (void)context; // replace with macro
+    int result = PAL_SUCCESS;
+    if (s_pal_network_initialized == 1)
+    {
+        return PAL_SUCCESS; // already initialized.
+    }
+
+    s_pal_network_initialized = 1;
+
+    return result;
+}
+
+palStatus_t pal_plat_registerNetworkInterface(void* context, uint32_t* interfaceIndex)
+{
+    palStatus_t result = PAL_SUCCESS;
+    uint32_t index = 0;
+    bool found = false;
+
+    for (index = 0; index < s_pal_numberOFInterfaces; index++) // if specific context already registered return exisitng index instead of registering again.
+    {
+        if (s_pal_networkInterfacesSupported[index] == context)
+        {
+            found = true;
+            *interfaceIndex = index;
+            break;
+        }
+    }
+
+    if (false == found)
+    {
+        if (s_pal_numberOFInterfaces < PAL_MAX_SUPORTED_NET_INTERFACES)
+        {
+            s_pal_networkInterfacesSupported[s_pal_numberOFInterfaces] = (NetworkInterface*)context;
+            *interfaceIndex = s_pal_numberOFInterfaces;
+            ++s_pal_numberOFInterfaces;
+        }
+        else
+        {
+            result = PAL_ERR_SOCKET_MAX_NUMBER_OF_INTERFACES_REACHED;
+        }
+    }
+
+    return result;
+}
+
+palStatus_t pal_plat_socketsTerminate(void* context)
+{
+    (void)context; // replace with macro
+    return PAL_SUCCESS;
+}
+
+PAL_PRIVATE int translateNSAPItoPALSocketOption(int option)
+{
+    int optionVal = PAL_SOCKET_OPTION_ERROR;
+    switch (option)
+    {
+    case PAL_SO_REUSEADDR:
+        optionVal = NSAPI_REUSEADDR;
+        break;
+#if PAL_NET_TCP_AND_TLS_SUPPORT // socket options below supported only if TCP is supported.
+    case PAL_SO_KEEPALIVE:
+        optionVal = NSAPI_KEEPALIVE;
+        break;
+    case PAL_SO_KEEPIDLE:
+        optionVal = NSAPI_KEEPIDLE;
+        break;
+    case PAL_SO_KEEPINTVL:
+        optionVal = NSAPI_KEEPINTVL;
+        break;
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+    case PAL_SO_SNDTIMEO:
+    case PAL_SO_RCVTIMEO:
+    default:
+        optionVal = PAL_SOCKET_OPTION_ERROR;
+    }
+    return optionVal;
+}
+
+
+PAL_PRIVATE palStatus_t palSockAddrToSocketAddress(const palSocketAddress_t* palAddr, int length, SocketAddress& output)
+{
+    palStatus_t result = PAL_SUCCESS;
+    uint16_t port = 0;
+    nsapi_version_t version = NSAPI_IPv4;
+
+    result = pal_getSockAddrPort(palAddr, &port);
+    if (result != PAL_SUCCESS)
+    {
+        return result;
+    }
+    output.set_port(port);
+
+#if PAL_SUPPORT_IP_V4
+    if (PAL_AF_INET == palAddr->addressType)
+    {
+        palIpV4Addr_t ipV4Addr;
+        version = NSAPI_IPv4;
+        result = pal_getSockAddrIPV4Addr(palAddr, ipV4Addr);
+        if (result == PAL_SUCCESS)
+        {
+            output.set_ip_bytes(&ipV4Addr, version);
+        }
+    }
+#endif
+#if PAL_SUPPORT_IP_V6
+    if (PAL_AF_INET6 == palAddr->addressType)
+    {
+        palIpV6Addr_t ipV6Addr;
+        version = NSAPI_IPv6;
+        result = pal_getSockAddrIPV6Addr(palAddr, ipV6Addr);
+        if (result == PAL_SUCCESS)
+        {
+            output.set_ip_bytes(&ipV6Addr, version);
+        }
+    }
+#endif
+
+    return result;
+}
+
+#ifndef PAL_DNS_API_V2
+PAL_PRIVATE palStatus_t socketAddressToPalSockAddr(SocketAddress& input, palSocketAddress_t* out, palSocketLength_t* length)
+#else
+PAL_PRIVATE palStatus_t socketAddressToPalSockAddr(SocketAddress& input, palSocketAddress_t* out)
+#endif
+{
+    palStatus_t result = PAL_SUCCESS;
+    int index = 0;
+    bool found = false;
+
+#if PAL_SUPPORT_IP_V4
+    if (input.get_ip_version() == NSAPI_IPv4)
+    {
+        palIpV4Addr_t addr;
+        found = true;
+        const void* tmp = input.get_ip_bytes();
+        for (index = 0; index < PAL_IPV4_ADDRESS_SIZE; index++)
+        {
+            addr[index] = ((const uint8_t*)tmp)[index];
+        }
+        result = pal_setSockAddrIPV4Addr(out, addr);
+#ifndef PAL_DNS_API_V2
+        *length = PAL_NET_MAX_ADDR_SIZE;  // TODO: check
+#endif
+
+    }
+#endif
+#if PAL_SUPPORT_IP_V6
+    if (input.get_ip_version() == NSAPI_IPv6)
+    {
+        palIpV6Addr_t addr;
+        found = true;
+        const void* tmp = input.get_ip_bytes();
+        for (index = 0; index < PAL_IPV6_ADDRESS_SIZE; index++)
+        {
+            addr[index] = ((const uint8_t*)tmp)[index];
+        }
+        result = pal_setSockAddrIPV6Addr(out, addr);
+#ifndef PAL_DNS_API_V2
+        *length = PAL_NET_MAX_ADDR_SIZE;  // TODO: check
+#endif
+    }
+#endif
+    if (false == found )
+    {
+        result = PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY;
+    }
+
+    if (result == PAL_SUCCESS)
+    {
+        result = pal_setSockAddrPort(out, input.get_port());
+    }
+    return result;
+}
+
+
+
+
+palStatus_t pal_plat_socket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palSocket_t* socket)
+{
+    int result = PAL_SUCCESS;
+    PALSocketWrapper* socketObj = NULL;
+    Socket* internalSocket = NULL;
+
+    PAL_VALIDATE_ARGUMENTS((NULL == socket))
+
+    if (PAL_NET_DEFAULT_INTERFACE == interfaceNum)
+    {
+        interfaceNum = 0;
+    }
+
+    if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_DGRAM == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6 == domain) || (PAL_AF_UNSPEC == domain))) // check correct parameters for UDP socket
+    {
+        internalSocket = new UDPSocket(s_pal_networkInterfacesSupported[interfaceNum]);
+    }
+#if PAL_NET_TCP_AND_TLS_SUPPORT // functionality below supported only in case TCP is supported.
+    else if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_STREAM == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6 == domain) || (PAL_AF_UNSPEC == domain))) // check correct parameters for TCP socket
+    {
+        internalSocket = new TCPSocket(s_pal_networkInterfacesSupported[interfaceNum]);
+    }
+    else if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_STREAM_SERVER == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6 == domain) || (PAL_AF_UNSPEC == domain))) // check correct parameters for TCP Server socket
+    {
+        internalSocket = new TCPServer(s_pal_networkInterfacesSupported[interfaceNum]);
+    }
+#endif
+    else
+    {
+        result =  PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    if ((PAL_SUCCESS == result ) && (NULL == internalSocket))
+    {
+        result = PAL_ERR_NO_MEMORY;
+    }
+
+    if (PAL_SUCCESS == result)
+    {
+
+        socketObj = new PALSocketWrapper();
+        if (NULL != socketObj)
+        {
+            if (0 == socketObj->initialize(internalSocket, type, nonBlockingSocket, NULL, NULL))
+            {
+                *socket = (palSocket_t)socketObj;
+            }
+            else
+            {
+                result = PAL_ERR_INVALID_ARGUMENT;
+            }
+
+        }
+        else
+        {
+            delete internalSocket;
+            result = PAL_ERR_NO_MEMORY;
+        }
+
+    }
+
+    if (PAL_SUCCESS != result) //cleanup
+    {
+        if (NULL != internalSocket)
+        {
+            delete internalSocket;
+        }
+        if (NULL != socketObj)
+        {
+            delete socketObj;
+        }
+    }
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+
+palStatus_t pal_plat_setSocketOptions(palSocket_t socket, int optionName, const void* optionValue, palSocketLength_t optionLength)
+{
+    int result = PAL_SUCCESS;
+    PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
+    int socketOption = PAL_SOCKET_OPTION_ERROR;
+
+    PAL_VALIDATE_ARGUMENTS(NULL == socket);
+
+    socketOption = translateNSAPItoPALSocketOption(optionName);
+    if (PAL_SOCKET_OPTION_ERROR != socketOption)
+    {
+        if (PAL_SO_REUSEADDR == optionName)
+        {
+            result = socketObj->setsockopt(NSAPI_SOCKET, socketOption, optionValue, optionLength);
+        }
+#if PAL_NET_TCP_AND_TLS_SUPPORT
+        else if (PAL_SO_KEEPIDLE == optionName ||
+                 PAL_SO_KEEPINTVL == optionName )
+        {
+                // Timeouts are in milliseconds
+                uint32_t timeout = (*(int *)optionValue) * 1000;
+                result = socketObj->setsockopt(NSAPI_SOCKET, socketOption, (void*)&timeout, sizeof(timeout));
+        }
+#endif
+        else
+        {
+            result = socketObj->setsockopt(NSAPI_SOCKET, socketOption, optionValue, optionLength);
+        }
+
+        if (result < 0)
+        {
+            result = translateErrorToPALError(result);
+        }
+    }
+    else
+    {
+        if ((PAL_SO_SNDTIMEO == optionName) || (PAL_SO_RCVTIMEO == optionName)) // timeouts in MBED API are not managed though socket options, bun instead via a different funciton call
+        {
+            int timeout = *((int*)optionValue);
+            // SO_xxxTIMEO should only affect blocking sockets - it only limits the block,
+            // whereas NSAPI's set_timeout is coupled with the blocking setting
+            if (!socketObj->isNonBlocking()) {
+                socketObj->set_timeout(timeout);
+            }
+        }
+        else
+        {
+            result = PAL_ERR_SOCKET_OPTION_NOT_SUPPORTED;
+        }
+    }
+
+
+    return result;
+}
+
+palStatus_t pal_plat_isNonBlocking(palSocket_t socket, bool* isNonBlocking)
+{
+    PALSocketWrapper* socketObj =  NULL;
+    PAL_VALIDATE_ARGUMENTS(NULL == socket);
+
+    socketObj =  (PALSocketWrapper*)socket;
+
+    *isNonBlocking = socketObj->isNonBlocking();
+
+    return PAL_SUCCESS;
+
+}
+
+palStatus_t pal_plat_bind(palSocket_t socket, palSocketAddress_t* myAddress, palSocketLength_t addressLength)
+{
+    int result = PAL_SUCCESS;
+    PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
+    SocketAddress internalAddr;
+
+    PAL_VALIDATE_ARGUMENTS ((NULL == socket));
+
+    result = palSockAddrToSocketAddress(myAddress, addressLength, internalAddr);
+    if (result == 0)
+    {
+        result = socketObj->bind(internalAddr);
+        if (result < 0)
+        {
+            result =  translateErrorToPALError(result);
+        }
+    }
+
+    return result;
+}
+
+
+palStatus_t pal_plat_receiveFrom(palSocket_t socket, void* buffer, size_t length, palSocketAddress_t* from, palSocketLength_t* fromLength, size_t* bytesReceived)
+{
+    int result = PAL_SUCCESS;
+    int status = 0;
+    *bytesReceived = 0;
+    SocketAddress sockAddr;
+    PALSocketWrapper* socketObj;
+    uint8_t* internalBufferPtr = (uint8_t*)buffer;
+    uint32_t bufferUsed = 0;
+
+    PAL_VALIDATE_ARGUMENTS((NULL == socket));
+
+    socketObj = (PALSocketWrapper*)socket;
+
+    if (true == socketObj->isRxBufferSet())
+    {
+        internalBufferPtr[0] = socketObj->getAndResetRxBuffer();
+        internalBufferPtr++;
+        length--;
+        bufferUsed += 1;
+    }
+
+    if (length > 0)
+    {
+        status = socketObj->recvfrom(&sockAddr, internalBufferPtr, length);
+        if (status < 0)
+        {
+            result = translateErrorToPALError(status);
+        }
+        else if (status == 0)
+        {
+            result = PAL_ERR_SOCKET_CONNECTION_CLOSED;
+        }
+        else // only return address / bytesReceived in case of success
+        {
+#ifndef PAL_DNS_API_V2
+            if ((NULL != from) && (NULL != fromLength))
+            {
+                result = socketAddressToPalSockAddr(sockAddr, from, fromLength);
+            }
+#else
+            if (NULL != from)
+            {
+                result = socketAddressToPalSockAddr(sockAddr, from);
+            }
+#endif
+            *bytesReceived = status + bufferUsed;
+        }
+    }
+    else
+    {
+        *bytesReceived = bufferUsed;
+    }
+
+    return result;
+
+}
+
+palStatus_t pal_plat_sendTo(palSocket_t socket, const void* buffer, size_t length, const palSocketAddress_t* to, palSocketLength_t toLength, size_t* bytesSent)
+{
+    int result = PAL_SUCCESS;
+    int status = 0;
+    SocketAddress sockAddr;
+
+    PAL_VALIDATE_ARGUMENTS((NULL == socket));
+
+    PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
+
+    *bytesSent = 0;
+    result = palSockAddrToSocketAddress(to, toLength, sockAddr);
+    if (result == 0)
+    {
+        status = socketObj->sendto(sockAddr, buffer, length);
+        if (status < 0)
+        {
+            result = translateErrorToPALError(status);
+        }
+        else
+        {
+            *bytesSent = status;
+        }
+    }
+
+    return result;
+}
+
+palStatus_t pal_plat_close(palSocket_t* socket)
+{
+    int result = PAL_SUCCESS;
+    if (NULL == *socket)
+    {
+        PAL_LOG(DBG, "socket close called on socket which was already closed");
+        return result; // socket already closed (or not opened) - no need to close.
+    }
+    PALSocketWrapper* socketObj = (PALSocketWrapper*)*socket;
+    result = socketObj->close();
+    if (result < 0)
+    {
+        result =  translateErrorToPALError(result);
+    }
+    delete socketObj;
+    *socket = NULL;
+    return result;
+}
+
+palStatus_t pal_plat_getNumberOfNetInterfaces( uint32_t* numInterfaces)
+{
+    *numInterfaces =  s_pal_numberOFInterfaces;
+    return PAL_SUCCESS;
+}
+
+palStatus_t pal_plat_getNetInterfaceInfo(uint32_t interfaceNum, palNetInterfaceInfo_t * interfaceInfo)
+{
+    palStatus_t result = PAL_SUCCESS;
+    const char* address = NULL;
+    SocketAddress addr;
+    PAL_VALIDATE_ARGUMENTS((interfaceNum >= s_pal_numberOFInterfaces));
+
+    address = s_pal_networkInterfacesSupported[interfaceNum]->get_ip_address(); // ip address returned is a null terminated string
+    if (NULL != address)
+    {
+        addr.set_ip_address(address);
+#ifndef PAL_DNS_API_V2
+        result = socketAddressToPalSockAddr(addr, &interfaceInfo->address, &interfaceInfo->addressSize);
+#else
+        result = socketAddressToPalSockAddr(addr, &interfaceInfo->address);
+#endif
+    }
+
+
+    return result;
+}
+
+typedef void(*palSelectCallbackFunction_t)();
+
+PAL_PRIVATE palSemaphoreID_t s_palSelectSemaphore = 0;
+
+uint32_t s_select_event_happened[PAL_NET_SOCKET_SELECT_MAX_SOCKETS];
+
+// select callbacks definition
+// TODO: nirson01 change to define these using a macro.
+void palSelectCallback0()
+{
+    s_select_event_happened[0]++;
+    pal_osSemaphoreRelease(s_palSelectSemaphore);
+}
+void palSelectCallback1()
+{
+    s_select_event_happened[1]++;
+    pal_osSemaphoreRelease(s_palSelectSemaphore);
+}
+void palSelectCallback2()
+{
+    s_select_event_happened[2]++;
+    pal_osSemaphoreRelease(s_palSelectSemaphore);
+}
+void palSelectCallback3()
+{
+    s_select_event_happened[3]++;
+    pal_osSemaphoreRelease(s_palSelectSemaphore);
+}
+void palSelectCallback4()
+{
+    s_select_event_happened[4]++;
+    pal_osSemaphoreRelease(s_palSelectSemaphore);
+}
+void palSelectCallback5()
+{
+    s_select_event_happened[5]++;
+    pal_osSemaphoreRelease(s_palSelectSemaphore);
+}
+void palSelectCallback6()
+{
+    s_select_event_happened[6]++;
+    pal_osSemaphoreRelease(s_palSelectSemaphore);
+}
+void palSelectCallback7()
+{
+    s_select_event_happened[7]++;
+    pal_osSemaphoreRelease(s_palSelectSemaphore);
+}
+
+palSelectCallbackFunction_t s_palSelectPalCallbackFunctions[PAL_NET_SOCKET_SELECT_MAX_SOCKETS] = { palSelectCallback0, palSelectCallback1, palSelectCallback2, palSelectCallback3, palSelectCallback4, palSelectCallback5, palSelectCallback6, palSelectCallback7 };
+
+
+#if PAL_NET_TCP_AND_TLS_SUPPORT // functionality below supported only in case TCP is supported.
+
+
+palStatus_t pal_plat_listen(palSocket_t socket, int backlog)
+{
+    int result = PAL_SUCCESS;
+    PAL_VALIDATE_ARGUMENTS(NULL == socket);
+
+    PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
+    result = socketObj->listen(backlog);
+    if (result < 0)
+    {
+        return translateErrorToPALError(result);
+    }
+    return PAL_SUCCESS;
+}
+
+
+palStatus_t pal_plat_accept(palSocket_t socket, palSocketAddress_t * address, palSocketLength_t* addressLen, palSocket_t* acceptedSocket)
+{
+    int result = PAL_SUCCESS;
+
+    SocketAddress incomingAddr;
+
+    PAL_VALIDATE_ARGUMENTS ((NULL == socket));
+
+    PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
+    result = socketObj->accept( (TCPSocket*)(*(PALSocketWrapper**)acceptedSocket)->getActiveSocket(), &incomingAddr);
+    if (result < 0)
+    {
+        result = translateErrorToPALError(result);
+    }
+    else
+    {
+#ifndef PAL_DNS_API_V2
+        result = socketAddressToPalSockAddr(incomingAddr, address, addressLen);
+#else
+        result = socketAddressToPalSockAddr(incomingAddr, address);
+#endif
+    }
+    return result;
+}
+
+
+palStatus_t pal_plat_connect(palSocket_t socket, const palSocketAddress_t* address, palSocketLength_t addressLen)
+{
+    int result = PAL_SUCCESS;
+    SocketAddress internalAddr;
+    PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
+    PAL_VALIDATE_ARGUMENTS ((NULL == socket));
+
+    result = palSockAddrToSocketAddress(address, addressLen,  internalAddr);
+    if (result == PAL_SUCCESS)
+    {
+        result = socketObj->connect(internalAddr);
+        if (result < 0)
+        {
+            result =  translateErrorToPALError(result);
+        }
+    }
+
+    return result;
+}
+
+palStatus_t pal_plat_recv(palSocket_t socket, void *buf, size_t len, size_t* recievedDataSize)
+{
+    int result = PAL_SUCCESS;
+    int status = 0;
+    uint8_t* internalBufferPtr = (uint8_t*)buf;
+    uint32_t bufferUsed = 0;
+
+    PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
+    PAL_VALIDATE_ARGUMENTS ((NULL == socket));
+
+    if (true == socketObj->isRxBufferSet())
+    {
+        internalBufferPtr[0] = socketObj->getAndResetRxBuffer();
+        internalBufferPtr++;
+        len--;
+        bufferUsed += 1;
+    }
+
+    if (len > 0)
+    {
+        status = socketObj->recv(internalBufferPtr, len);
+        if (status < 0)
+        {
+            result = translateErrorToPALError(status);
+        }
+        else if (status == 0) {
+            return PAL_ERR_SOCKET_CONNECTION_CLOSED;
+        }
+    }
+    *recievedDataSize = status + bufferUsed;
+    return result;
+}
+
+palStatus_t pal_plat_send(palSocket_t socket, const void *buf, size_t len, size_t* sentDataSize)
+{
+    palStatus_t result = PAL_SUCCESS;
+    int status = 0;
+
+    PALSocketWrapper* socketObj = (PALSocketWrapper*)socket;
+    PAL_VALIDATE_ARGUMENTS ((NULL == socket));
+
+    status = socketObj->send(buf, len);
+    if (status < 0)
+    {
+        result = translateErrorToPALError(status);
+    }
+    else
+    {
+        *sentDataSize = status;
+    }
+    return result;
+}
+
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+
+
+palStatus_t pal_plat_asynchronousSocket(palSocketDomain_t domain, palSocketType_t type, bool nonBlockingSocket, uint32_t interfaceNum, palAsyncSocketCallback_t callback, void* arg,  palSocket_t* socket)
+{
+    int result = PAL_SUCCESS;
+    PALSocketWrapper * socketObj = NULL;
+    Socket* internalSocket = NULL;
+
+    PAL_VALIDATE_ARGUMENTS((NULL == socket));
+
+    if (PAL_NET_DEFAULT_INTERFACE == interfaceNum)
+    {
+        interfaceNum = 0;
+    }
+
+    if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_DGRAM == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6 == domain) || (PAL_AF_UNSPEC == domain))) //check that we got correct parameters for UDP socket
+    {
+        internalSocket = new UDPSocket(s_pal_networkInterfacesSupported[interfaceNum]);
+    }
+#if PAL_NET_TCP_AND_TLS_SUPPORT // functionality below supported only in case TCP is supported.
+    else if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_STREAM == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6 == domain) || (PAL_AF_UNSPEC == domain))) //check that we got correct parameters for TCP socket
+    {
+        internalSocket = new TCPSocket(s_pal_networkInterfacesSupported[interfaceNum]);
+    }
+    else if ((s_pal_numberOFInterfaces > interfaceNum) && (PAL_SOCK_STREAM_SERVER == type) && ((PAL_AF_INET == domain) || (PAL_AF_INET6 == domain) || (PAL_AF_UNSPEC == domain))) //check that we got correct parameters for TCP Server socket
+    {
+        internalSocket = new TCPServer(s_pal_networkInterfacesSupported[interfaceNum]);
+    }
+#endif
+    else
+    {
+        result = PAL_ERR_INVALID_ARGUMENT;
+    }
+
+    if ((PAL_SUCCESS == result) && (NULL == internalSocket))
+    {
+        result = PAL_ERR_NO_MEMORY;
+    }
+
+    if (PAL_SUCCESS == result)
+    {
+        socketObj = new PALSocketWrapper();
+        if (NULL != socketObj)
+        {
+            if (0 == socketObj->initialize(internalSocket, type, nonBlockingSocket, callback, arg))
+            {
+                *socket = (palSocket_t)socketObj;
+            }
+            else
+            {
+                result = PAL_ERR_INVALID_ARGUMENT;
+            }
+        }
+        else
+        {
+            delete internalSocket;
+            result = PAL_ERR_NO_MEMORY;
+        }
+    }
+
+    if (PAL_SUCCESS != result) //cleanup
+    {
+        if (NULL != internalSocket)
+        {
+            delete internalSocket;
+        }
+        if (NULL != socketObj)
+        {
+            delete socketObj;
+        }
+    }
+    return result; // TODO(nirson01) ADD debug print for error propagation(once debug print infrastructure is finalized)
+}
+
+#endif
+
+#if PAL_NET_DNS_SUPPORT
+
+palStatus_t pal_plat_getAddressInfo(const char *url, palSocketAddress_t *address, palSocketLength_t* length)
+{
+    palStatus_t result = PAL_SUCCESS;
+    SocketAddress translatedAddress; // by default use the fist supported net interface - TODO: do we need to select a different interface?
+
+#if PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_ANY
+    result = s_pal_networkInterfacesSupported[0]->gethostbyname(url, &translatedAddress);
+#elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV4_ONLY
+    result = s_pal_networkInterfacesSupported[0]->gethostbyname(url, &translatedAddress, NSAPI_IPv4);
+#elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV6_ONLY
+    result = s_pal_networkInterfacesSupported[0]->gethostbyname(url, &translatedAddress, NSAPI_IPv6);
+#else
+#error PAL_NET_DNS_IP_SUPPORT is not defined to a valid value.
+#endif
+
+    if (result == 0) {
+#ifndef PAL_DNS_API_V2
+        result = socketAddressToPalSockAddr(translatedAddress, address, length);
+#else
+        result = socketAddressToPalSockAddr(translatedAddress, address);
+#endif
+    }
+    else { // error happened
+        result = translateErrorToPALError(result);
+    }
+    return result;
+}
+
+#ifdef PAL_DNS_API_V2
+void pal_plat_getAddressInfoAsync_callback(void *data, nsapi_error_t result, SocketAddress *address)
+{
+    PAL_LOG(DBG, "pal_plat_getAddressInfoAsync_callback(0x%X,%d, %s)",data, result, address->get_ip_address());
+    palStatus_t status = PAL_SUCCESS;
+    pal_asyncAddressInfo_t* info = (pal_asyncAddressInfo_t*)(data);
+
+    if (result == NSAPI_ERROR_OK) {
+        status = socketAddressToPalSockAddr(*address, info->address);
+    }
+    else { // error happened
+        status = translateErrorToPALError(result);
+    }
+
+    info->callback(info->url, info->address, status, info->callbackArgument); // invoke callback
+    free(info);
+}
+
+palStatus_t pal_plat_getAddressInfoAsync(pal_asyncAddressInfo* info)
+{
+    PAL_LOG(DBG, "pal_plat_getAddressInfoAsync");
+    palStatus_t result;
+#if PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_ANY
+    const nsapi_version_t version = NSAPI_UNSPEC;
+#elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV4_ONLY
+    const nsapi_version_t version = NSAPI_IPv4;
+#elif PAL_NET_DNS_IP_SUPPORT == PAL_NET_DNS_IPV6_ONLY
+    const nsapi_version_t version = NSAPI_IPv6;
+#else
+#error PAL_NET_DNS_IP_SUPPORT is not defined to a valid value.
+#endif
+
+    result = s_pal_networkInterfacesSupported[0]->gethostbyname_async(info->url, mbed::Callback<void(nsapi_error_t, SocketAddress *)>(pal_plat_getAddressInfoAsync_callback,(void*)info), version);
+    PAL_LOG(DBG, "pal_plat_getAddressInfoAsync result %d", result);
+    if (result < 0) {
+        result = translateErrorToPALError(result);
+    }
+    else {
+        /* Skip over setting queryHandle when:
+         * 1. info->queryHandle not allocated  
+         * 2. if result is zero then callback pal_plat_getAddressInfoAsync_callback will be called immediately and address info has been deallocated. */
+        if ( (info->queryHandle != NULL) && result) {
+            *(info->queryHandle) = result;
+        }
+        result = PAL_SUCCESS;
+    }
+    return result;
+}
+
+palStatus_t pal_plat_cancelAddressInfoAsync(palDNSQuery_t queryHandle)
+{
+    palStatus_t status = s_pal_networkInterfacesSupported[0]->gethostbyname_async_cancel(queryHandle);
+    if (PAL_SUCCESS != status) {
+        PAL_LOG(ERR, "pal_cancelAddressInfoAsync failed with %ld", status);
+    }
+    return status;
+}
+#endif
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/RTOS/pal_plat_rtos.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,798 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#include "pal.h"
+#include <stdlib.h>
+#include <string.h>
+#include "pal_plat_rtos.h"
+#include "mbed.h"
+#include "entropy_poll.h"
+
+/*
+    mbedOS latest version RTOS support
+*/
+#if defined(osRtxVersionAPI) && (osRtxVersionAPI >= 20000000)
+
+#include "cmsis_os2.h" // Revision:    V2.1
+#include <time.h>
+
+#define PAL_RTOS_TRANSLATE_CMSIS_ERROR_CODE(cmsisCode)\
+    ((int32_t)((int32_t)cmsisCode + PAL_ERR_RTOS_ERROR_BASE))
+
+#define PAL_THREAD_NAME_MAX_LEN 20 // max len for thread name which holds the pointer (as string) to dynamically allocated thread data
+#define PAL_THREAD_STACK_ALIGN(x) ((x % sizeof(uint64_t)) ? (x + ((sizeof(uint64_t)) - (x % sizeof(uint64_t)))) : x)
+
+typedef struct palThreadData 
+{
+    osThreadId_t threadID;
+    osThreadAttr_t threadAttr;
+    mbed_rtos_storage_thread_t threadStore;
+    palThreadFuncPtr userFunction;
+    void* userFunctionArgument;
+} palThreadData_t;
+
+typedef struct palThreadCleanupData
+{
+    palTimerID_t timerID;
+    palThreadData_t* threadData;
+} palThreadCleanupData_t;
+
+PAL_PRIVATE palMutexID_t g_threadsMutex = NULLPTR;
+
+//! Timer structure
+typedef struct palTimer{
+    palTimerID_t              timerID;
+    osTimerAttr_t             osTimer;
+    mbed_rtos_storage_timer_t osTimerStorage;
+} palTimer_t;
+
+//! Mutex structure
+typedef struct palMutex{
+    palMutexID_t              mutexID;
+    osMutexAttr_t             osMutex;
+    mbed_rtos_storage_mutex_t osMutexStorage;
+}palMutex_t;
+
+//! Semaphore structure
+typedef struct palSemaphore{
+    palSemaphoreID_t              semaphoreID;
+    osSemaphoreAttr_t             osSemaphore;
+    mbed_rtos_storage_semaphore_t osSemaphoreStorage;
+}palSemaphore_t;
+
+void pal_plat_osReboot()
+{
+    NVIC_SystemReset();
+}
+
+palStatus_t pal_plat_RTOSInitialize(void* opaqueContext)
+{
+    palStatus_t status = pal_osMutexCreate(&g_threadsMutex);
+    return status;
+}
+
+palStatus_t pal_plat_RTOSDestroy(void)
+{
+    palStatus_t status = PAL_SUCCESS; 
+    if (NULLPTR != g_threadsMutex)
+    {
+        status = pal_osMutexDelete(&g_threadsMutex);
+        g_threadsMutex = NULLPTR;
+    }
+    return status;
+}
+
+palStatus_t pal_plat_osDelay(uint32_t milliseconds)
+{
+    palStatus_t status;
+    osStatus_t platStatus = osDelay(milliseconds);
+    if (osOK == platStatus)
+    {
+        status = PAL_SUCCESS;
+    }
+    else
+    {
+        status = PAL_RTOS_TRANSLATE_CMSIS_ERROR_CODE(platStatus); //TODO(nirson01): error propagation MACRO??
+    }
+    return status;
+}
+
+uint64_t pal_plat_osKernelSysTick(void)
+{
+    uint64_t result;
+    result = osKernelGetTickCount();
+    return result;
+}
+
+uint64_t pal_plat_osKernelSysTickMicroSec(uint64_t microseconds)
+{
+    uint64_t result;
+    result =  (((uint64_t)microseconds * (osKernelGetTickFreq())) / 1000000);
+
+    return result;
+}
+
+uint64_t pal_plat_osKernelSysTickFrequency()
+{
+    return osKernelGetTickFreq();
+}
+
+PAL_PRIVATE void timerFunctionThreadCleanup(const void* arg)
+{
+    palStatus_t status;
+    palThreadCleanupData_t* cleanupData = (palThreadCleanupData_t*)arg;
+    palTimerID_t timerID = cleanupData->timerID;
+    osThreadState_t threadState = osThreadGetState(cleanupData->threadData->threadID);
+    if ((osThreadTerminated == threadState) || (osThreadInactive == threadState)) // thread has transitioned into its final state so clean up
+    {
+        free(cleanupData->threadData->threadAttr.stack_mem);
+        free((void*)cleanupData->threadData->threadAttr.name);
+        free(cleanupData->threadData);
+        free(cleanupData);
+        status = pal_osTimerDelete(&timerID);
+        if (PAL_SUCCESS != status)
+        {
+            PAL_LOG(ERR, "timerFunctionThreadCleanup timer delete failed\n");
+        }
+        goto end;
+    }
+
+    if (osThreadError == threadState)
+    {
+        PAL_LOG(ERR, "timerFunctionThreadCleanup threadState is osThreadError\n");
+        goto end;
+    }
+
+    status = pal_osTimerStart(timerID, PAL_RTOS_THREAD_CLEANUP_TIMER_MILISEC); // thread has not transitioned into its final so start the timer again
+    if (PAL_SUCCESS != status)
+    {
+        PAL_LOG(ERR, "timerFunctionThreadCleanup timer start failed\n");
+    }
+end:
+    return;
+}
+
+PAL_PRIVATE void threadFunction(void* arg)
+{
+    palThreadData_t* threadData;
+    palThreadFuncPtr userFunction;
+    void* userFunctionArgument;
+    palThreadCleanupData_t* cleanupData;
+    palTimerID_t timerID;
+    bool isMutexTaken = false;
+    palStatus_t status = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); // avoid race condition with thread terminate
+    if (PAL_SUCCESS != status)
+    {
+        PAL_LOG(ERR, "threadFunction mutex wait failed (pre)\n");
+        goto end;
+    }
+
+    isMutexTaken = true;
+    threadData = (palThreadData_t*)arg;
+    userFunction = threadData->userFunction;
+    userFunctionArgument = threadData->userFunctionArgument;
+    status = pal_osMutexRelease(g_threadsMutex);
+    if (PAL_SUCCESS != status)
+    {
+        PAL_LOG(ERR, "threadFunction mutex release failed (pre)\n");
+        goto end;
+    }
+
+    isMutexTaken = false;
+    userFunction(userFunctionArgument); // invoke user function with user argument (use local vars)
+    status = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); // avoid race condition with thread terminate
+    if (PAL_SUCCESS != status)
+    {
+        PAL_LOG(ERR, "threadFunction mutex wait failed (post)\n");
+        goto end;
+    }
+
+    isMutexTaken = true;
+    cleanupData = (palThreadCleanupData_t*)malloc(sizeof(palThreadCleanupData_t));
+    if (NULL == cleanupData)
+    {
+        PAL_LOG(ERR, "threadFunction malloc palThreadCleanupData_t failed\n");
+        goto end;
+    }
+
+    status = pal_osTimerCreate(timerFunctionThreadCleanup, cleanupData, palOsTimerOnce, &timerID);
+    if (PAL_SUCCESS != status)
+    {
+        free(cleanupData);
+        PAL_LOG(ERR, "threadFunction create timer failed\n");
+        goto end;
+    }
+
+    memset((void*)threadData->threadAttr.name, 0, PAL_THREAD_NAME_MAX_LEN); // clear the thread name which holds the address (as string) of the dynamically allocated palThreadData_t (rechecked in thread terminate)
+    threadData->threadID = osThreadGetId();
+    cleanupData->timerID = timerID;
+    cleanupData->threadData = threadData;
+    status = pal_osTimerStart(timerID, PAL_RTOS_THREAD_CLEANUP_TIMER_MILISEC);
+    if (PAL_SUCCESS != status)
+    {
+        free(cleanupData); // timer failed to start so cleanup dynamically allocated palThreadCleanupData_t
+        PAL_LOG(ERR, "threadFunction timer start failed\n");
+        status = pal_osTimerDelete(&timerID);
+        if (PAL_SUCCESS != status)
+        {
+            PAL_LOG(ERR, "threadFunction timer delete failed\n");
+        }
+    }
+end:
+    if (isMutexTaken)
+    {
+        status = pal_osMutexRelease(g_threadsMutex);
+        if (PAL_SUCCESS != status)
+        {
+            PAL_LOG(ERR, "threadFunction mutex release failed (post)\n");
+        }
+    }
+}
+
+PAL_PRIVATE osPriority_t translatePriority(palThreadPriority_t priority)
+{
+    osPriority_t translatedPriority;
+    switch (priority)
+    {
+        case PAL_osPriorityIdle:
+            translatedPriority = osPriorityIdle;
+            break;
+        case PAL_osPriorityLow:
+            translatedPriority = osPriorityLow;
+            break;
+        case PAL_osPriorityReservedTRNG:
+            translatedPriority = osPriorityLow1;
+            break;
+        case PAL_osPriorityBelowNormal:
+            translatedPriority = osPriorityBelowNormal;
+            break;
+        case PAL_osPriorityNormal:
+            translatedPriority = osPriorityNormal;
+            break;
+        case PAL_osPriorityAboveNormal:
+            translatedPriority = osPriorityAboveNormal;
+            break;
+        case PAL_osPriorityReservedDNS:
+            translatedPriority = osPriorityAboveNormal1;
+            break;
+        case PAL_osPriorityReservedSockets:
+            translatedPriority = osPriorityAboveNormal2;
+            break;
+        case PAL_osPriorityHigh:
+            translatedPriority = osPriorityHigh;
+            break;
+        case PAL_osPriorityReservedHighResTimer:
+            translatedPriority = osPriorityRealtime;
+            break;
+        case PAL_osPriorityRealtime:
+            translatedPriority = osPriorityRealtime1;
+            break;
+        case PAL_osPriorityError:
+        default:
+            translatedPriority = osPriorityError;
+            break;
+    }
+    return translatedPriority;
+}
+
+palStatus_t pal_plat_osThreadCreate(palThreadFuncPtr function, void* funcArgument, palThreadPriority_t priority, uint32_t stackSize, palThreadID_t* threadID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    void* threadStack = NULL;
+    char* threadName = NULL;
+    palThreadData_t* threadData = NULL;
+    int bytesWritten;
+    osThreadId_t sysThreadID;
+    osPriority_t threadPriority = translatePriority(priority);
+    if (osPriorityError == threadPriority)
+    {
+        status = PAL_ERR_RTOS_PRIORITY;
+        goto end;
+    }
+
+    stackSize = PAL_THREAD_STACK_ALIGN(stackSize);
+    threadStack = malloc(stackSize);
+    threadName = (char*)calloc((PAL_THREAD_NAME_MAX_LEN + 1), sizeof(char)); // name will hold the address of the dynamically allocated palThreadData_t (as string)
+    threadData = (palThreadData_t*)malloc(sizeof(palThreadData_t));
+    if ((NULL == threadData) || (NULL == threadStack) || (NULL == threadName))
+    {
+        status = PAL_ERR_RTOS_RESOURCE;
+        goto clean;
+    }
+
+    bytesWritten = snprintf(threadName, (PAL_THREAD_NAME_MAX_LEN + 1), "%p", threadData);
+    if ((bytesWritten <= 0) || ((PAL_THREAD_NAME_MAX_LEN + 1) <= bytesWritten))
+    {
+        status = PAL_ERR_RTOS_RESOURCE;
+        goto clean;
+    }
+
+    memset(&(threadData->threadStore), 0, sizeof(threadData->threadStore));
+    threadData->threadAttr.priority = threadPriority;
+    threadData->threadAttr.stack_size = stackSize;
+    threadData->threadAttr.stack_mem = threadStack;
+    threadData->threadAttr.name = threadName;
+    threadData->threadAttr.cb_mem= &(threadData->threadStore);
+    threadData->threadAttr.cb_size = sizeof(threadData->threadStore);
+    threadData->userFunction = function;
+    threadData->userFunctionArgument = funcArgument;
+
+    sysThreadID = osThreadNew(threadFunction, threadData, &(threadData->threadAttr));
+    if (NULL == sysThreadID)
+    {
+        status = PAL_ERR_GENERIC_FAILURE;
+        goto clean;
+    }
+
+    *threadID = (palThreadID_t)sysThreadID;
+    goto end;
+clean:
+    free(threadStack);
+    free(threadName);
+    free(threadData);
+end:
+    return status;
+}
+
+palThreadID_t pal_plat_osThreadGetId(void)
+{
+    palThreadID_t threadID = (palThreadID_t)osThreadGetId();
+    return threadID;
+}
+
+palStatus_t pal_plat_osThreadTerminate(palThreadID_t* threadID)
+{
+    palStatus_t status;
+    palThreadData_t* threadData = NULL;
+    osThreadId_t sysThreadID = (osThreadId_t)*threadID;
+    osStatus_t sysStatus;
+    osThreadState_t threadState;
+    const char* threadName;
+    bool isMutexTaken = false;
+    if (osThreadGetId() == sysThreadID) // self termination not allowed
+    {
+        status = PAL_ERR_RTOS_TASK;
+        goto end;   
+    }
+
+    status = pal_osMutexWait(g_threadsMutex, PAL_RTOS_WAIT_FOREVER); // avoid race condition with thread function
+    if (PAL_SUCCESS != status)
+    {
+        PAL_LOG(ERR, "thread terminate mutex wait failed\n");
+        goto end;
+    }
+
+    isMutexTaken = true;
+    threadState = osThreadGetState(sysThreadID);
+    if ((osThreadTerminated == threadState) || (osThreadInactive == threadState) || (osThreadError == threadState)) // thread has already transitioned into its final state
+    {
+        goto end;
+    }
+
+    threadName = osThreadGetName(sysThreadID);
+    if ((NULL == threadName) || (1 != sscanf(threadName, "%p", &threadData))) // this may happen if the thread has not tranistioned into its final state yet (altered in thread function)
+    {
+        goto end;
+    }
+
+    sysStatus = osThreadTerminate(sysThreadID);
+    if (osErrorISR == sysStatus)
+    {
+        status = PAL_ERR_RTOS_ISR;
+        goto end;
+    }
+
+    free(threadData->threadAttr.stack_mem);
+    free((void*)threadData->threadAttr.name);
+    free(threadData);
+end:
+    if (isMutexTaken)
+    {
+        if (PAL_SUCCESS != pal_osMutexRelease(g_threadsMutex))
+        {
+            PAL_LOG(ERR, "thread terminate mutex release failed\n");
+        }
+    }
+    return status;
+}
+
+palStatus_t pal_plat_osTimerCreate(palTimerFuncPtr function, void* funcArgument, palTimerType_t timerType, palTimerID_t* timerID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palTimer_t* timer = NULL;
+   
+    timer = (palTimer_t*)malloc(sizeof(palTimer_t));
+    if (NULL == timer)
+    {
+        status = PAL_ERR_NO_MEMORY;
+    }
+
+    if (PAL_SUCCESS == status)
+    {
+        timer->osTimer.name = NULL;
+        timer->osTimer.attr_bits = 0;
+        timer->osTimer.cb_mem = &timer->osTimerStorage;
+        timer->osTimer.cb_size = sizeof(timer->osTimerStorage);
+        memset(&timer->osTimerStorage, 0, sizeof(timer->osTimerStorage));
+    
+        timer->timerID = (uintptr_t)osTimerNew((osTimerFunc_t)function, (osTimerType_t)timerType, funcArgument, &timer->osTimer);
+        if (NULLPTR == timer->timerID)
+        {
+            free(timer);
+            timer = NULL;
+            status = PAL_ERR_GENERIC_FAILURE;
+        }
+        else
+        {
+            *timerID = (palTimerID_t)timer;
+        }
+    }
+    return status;
+}
+
+palStatus_t pal_plat_osTimerStart(palTimerID_t timerID, uint32_t millisec)
+{
+    palStatus_t status = PAL_SUCCESS;
+    osStatus_t platStatus = osOK;
+    palTimer_t* timer = NULL;
+    
+    timer = (palTimer_t*)timerID;
+    platStatus = osTimerStart((osTimerId_t)timer->timerID, millisec);
+    if (osOK == (osStatus_t)platStatus)
+    {
+        status = PAL_SUCCESS;
+    }
+    else
+    {
+        status = PAL_RTOS_TRANSLATE_CMSIS_ERROR_CODE(platStatus);
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_osTimerStop(palTimerID_t timerID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    osStatus_t platStatus = osOK;
+    palTimer_t* timer = NULL;
+    
+    timer = (palTimer_t*)timerID;
+    platStatus = osTimerStop((osTimerId_t)timer->timerID);
+    if (osOK == platStatus)
+    {
+        status = PAL_SUCCESS;
+    }
+    else
+    {
+        status = PAL_RTOS_TRANSLATE_CMSIS_ERROR_CODE(platStatus);
+    }
+
+    return status;  
+}
+
+palStatus_t pal_plat_osTimerDelete(palTimerID_t* timerID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    osStatus_t platStatus = osOK;
+    palTimer_t* timer = NULL;
+    
+    timer = (palTimer_t*)*timerID;
+    platStatus = osTimerDelete((osTimerId_t)timer->timerID);
+    if (osOK == platStatus)
+    {
+        free(timer);
+        *timerID = NULLPTR;
+        status = PAL_SUCCESS;
+    }
+    else
+    {
+        status = PAL_RTOS_TRANSLATE_CMSIS_ERROR_CODE(platStatus);
+    }
+
+    return status;
+}
+
+
+palStatus_t pal_plat_osMutexCreate(palMutexID_t* mutexID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palMutex_t* mutex = NULL;
+
+    mutex = (palMutex_t*)malloc(sizeof(palMutex_t));
+    if (NULL == mutex)
+    {
+        status = PAL_ERR_NO_MEMORY;
+    }
+
+    if (PAL_SUCCESS == status)
+    {
+        mutex->osMutex.name = NULL;
+        mutex->osMutex.attr_bits = osMutexRecursive | osMutexRobust;
+        mutex->osMutex.cb_mem = &mutex->osMutexStorage;
+        mutex->osMutex.cb_size = sizeof(mutex->osMutexStorage);
+        memset(&mutex->osMutexStorage, 0, sizeof(mutex->osMutexStorage));
+
+        mutex->mutexID = (uintptr_t)osMutexNew(&mutex->osMutex);
+        if (NULLPTR == mutex->mutexID)
+        {
+            free(mutex);
+            mutex = NULL;
+            status = PAL_ERR_GENERIC_FAILURE;
+        }
+        else
+        {
+            *mutexID = (palMutexID_t)mutex;
+        }
+    }
+    return status;
+}
+
+
+palStatus_t pal_plat_osMutexWait(palMutexID_t mutexID, uint32_t millisec)
+{
+    palStatus_t status = PAL_SUCCESS;
+    osStatus_t platStatus = osOK;
+    palMutex_t* mutex = NULL;
+    
+    mutex = (palMutex_t*)mutexID;
+    platStatus = osMutexAcquire((osMutexId_t)mutex->mutexID, millisec);
+    if (osOK == platStatus)
+    {
+        status = PAL_SUCCESS;
+    }
+    else
+    {
+        status = PAL_RTOS_TRANSLATE_CMSIS_ERROR_CODE(platStatus);
+    }
+
+    return status;
+}
+
+
+palStatus_t pal_plat_osMutexRelease(palMutexID_t mutexID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    osStatus_t platStatus = osOK;
+    palMutex_t* mutex = NULL;
+    
+    mutex = (palMutex_t*)mutexID;
+    platStatus = osMutexRelease((osMutexId_t)mutex->mutexID);
+    if (osOK == platStatus)
+    {
+        status = PAL_SUCCESS;
+    }
+    else
+    {
+        status = PAL_RTOS_TRANSLATE_CMSIS_ERROR_CODE(platStatus);
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_osMutexDelete(palMutexID_t* mutexID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    osStatus_t platStatus = osOK;
+    palMutex_t* mutex = NULL;
+    
+    mutex = (palMutex_t*)*mutexID;
+    platStatus = osMutexDelete((osMutexId_t)mutex->mutexID);
+    if (osOK == platStatus)
+    {
+        free(mutex);
+        *mutexID = NULLPTR;
+        status = PAL_SUCCESS;
+    }
+    else
+    {
+        status = PAL_RTOS_TRANSLATE_CMSIS_ERROR_CODE(platStatus);
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_osSemaphoreCreate(uint32_t count, palSemaphoreID_t* semaphoreID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palSemaphore_t* semaphore = NULL;
+    
+    semaphore = (palSemaphore_t*)malloc(sizeof(palSemaphore_t));
+    if (NULL == semaphore)
+    {
+        status = PAL_ERR_NO_MEMORY;
+    }
+
+    if(PAL_SUCCESS == status)
+    {
+        semaphore->osSemaphore.cb_mem = &semaphore->osSemaphoreStorage;
+        semaphore->osSemaphore.cb_size = sizeof(semaphore->osSemaphoreStorage);
+        memset(&semaphore->osSemaphoreStorage, 0, sizeof(semaphore->osSemaphoreStorage));
+
+        semaphore->semaphoreID = (uintptr_t)osSemaphoreNew(PAL_MAX_SEMAPHORE_COUNT, count, &semaphore->osSemaphore);
+        if (NULLPTR == semaphore->semaphoreID)
+        {
+            free(semaphore);
+            semaphore = NULL;
+            status = PAL_ERR_GENERIC_FAILURE;
+        }
+        else
+        {
+            *semaphoreID = (palSemaphoreID_t)semaphore;
+        }
+    }
+    return status;  
+}
+
+palStatus_t pal_plat_osSemaphoreWait(palSemaphoreID_t semaphoreID, uint32_t millisec, int32_t* countersAvailable)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palSemaphore_t* semaphore = NULL;
+    osStatus_t platStatus;
+    
+    semaphore = (palSemaphore_t*)semaphoreID;
+    platStatus = osSemaphoreAcquire((osSemaphoreId_t)semaphore->semaphoreID, millisec);
+
+    if (osErrorTimeout == platStatus)
+    {
+        status = PAL_ERR_RTOS_TIMEOUT;
+    }
+    else if (platStatus != osOK)
+    {
+        status = PAL_ERR_RTOS_PARAMETER;
+    }
+
+    if (NULL != countersAvailable)
+    {
+        *countersAvailable = osSemaphoreGetCount((osSemaphoreId_t)semaphore->semaphoreID);
+    }
+    return status;
+}
+
+palStatus_t pal_plat_osSemaphoreRelease(palSemaphoreID_t semaphoreID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    osStatus_t platStatus = osOK;
+    palSemaphore_t* semaphore = NULL;
+
+    semaphore = (palSemaphore_t*)semaphoreID;
+    platStatus = osSemaphoreRelease((osSemaphoreId_t)semaphore->semaphoreID);
+    if (osOK == platStatus)
+    {
+        status = PAL_SUCCESS;
+    }
+    else
+    {
+        status = PAL_RTOS_TRANSLATE_CMSIS_ERROR_CODE(platStatus);
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_osSemaphoreDelete(palSemaphoreID_t* semaphoreID)
+{
+    palStatus_t status = PAL_SUCCESS;
+    osStatus_t platStatus = osOK;
+    palSemaphore_t* semaphore = NULL;
+    
+    semaphore = (palSemaphore_t*)*semaphoreID;
+    platStatus = osSemaphoreDelete((osSemaphoreId_t)semaphore->semaphoreID);
+    if (osOK == platStatus)
+    {
+        free(semaphore);
+        *semaphoreID = NULLPTR;
+        status = PAL_SUCCESS;
+    }
+    else
+    {
+        status = PAL_RTOS_TRANSLATE_CMSIS_ERROR_CODE(platStatus);
+    }
+
+    return status;  
+}
+
+int32_t pal_plat_osAtomicIncrement(int32_t* valuePtr, int32_t increment)
+{
+    if (increment >= 0)
+    {
+        return core_util_atomic_incr_u32((uint32_t*)valuePtr, increment);
+    }
+    else
+    {
+        return core_util_atomic_decr_u32((uint32_t*)valuePtr, 0 - increment);
+    }
+}
+
+
+ void *pal_plat_malloc(size_t len)
+{
+	return malloc(len);
+}
+
+
+ void pal_plat_free(void * buffer)
+{
+	return free(buffer);
+}
+
+#if PAL_USE_HW_TRNG
+palStatus_t pal_plat_osRandomBuffer(uint8_t *randomBuf, size_t bufSizeBytes, size_t* actualRandomSizeBytes)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t platStatus = 0;
+    size_t actualOutputLen = 0;
+    platStatus = mbedtls_hardware_poll(NULL /*Not used by the function*/, randomBuf, bufSizeBytes, &actualOutputLen);
+    if ((0 != platStatus) || (0 == actualOutputLen))
+    {
+        status = PAL_ERR_RTOS_TRNG_FAILED;
+    }
+    else if (actualOutputLen != bufSizeBytes)
+    {
+        status = PAL_ERR_RTOS_TRNG_PARTIAL_DATA;
+    }
+
+    if (NULL != actualRandomSizeBytes)
+    {
+        *actualRandomSizeBytes = actualOutputLen;
+    }
+    return status;
+}
+#endif
+
+#if (PAL_USE_HW_RTC)
+palStatus_t pal_plat_osGetRtcTime(uint64_t *rtcGetTime)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if(rtcGetTime != NULL)
+    {
+        *rtcGetTime = (uint64_t)time(NULL);
+    }
+    else
+    {
+        ret = PAL_ERR_NULL_POINTER;
+    }
+    return ret;
+}
+
+palStatus_t pal_plat_osSetRtcTime(uint64_t rtcSetTime)
+{
+    palStatus_t status = PAL_SUCCESS;
+    if (rtcSetTime < (uint64_t)PAL_MIN_RTC_SET_TIME)
+    {
+        status = PAL_ERR_INVALID_TIME;
+    }
+    else
+    {
+        set_time(rtcSetTime);
+    }
+
+    return status;
+}
+
+palStatus_t pal_plat_rtcInit(void)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    return ret;
+}
+
+palStatus_t pal_plat_rtcDeInit(void)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    return ret;
+}
+#endif //#if (PAL_USE_HW_RTC)
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Storage/FileSystem/pal_plat_fileSystem.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,613 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#include <errno.h> //This should be added before mbed.h otherwise ARMCC compilation fails with conflicting error codes.
+#include "mbed.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "FileSystemLike.h"
+#include "FilePath.h"
+
+
+//PAL Includes
+#include "pal.h"
+#include "pal_plat_fileSystem.h"
+
+#ifndef EEXIST
+#define EEXIST 17
+#endif
+#ifndef EACCES
+#define EACCES 13
+#endif
+#ifndef EFAULT
+#define EFAULT 14
+#endif
+#ifndef EROFS
+#define EROFS 30
+#endif
+#ifndef EBUSY
+#define EBUSY 16
+#endif
+#ifndef ENAMETOOLONG
+#define ENAMETOOLONG 36
+#endif
+#ifndef EBADF
+#define EBADF 9
+#endif
+#ifndef EISDIR
+#define EISDIR 21
+#endif
+#ifndef ENOTEMPTY
+#define ENOTEMPTY 39
+#endif
+#ifndef ENOENT
+#define ENOENT 2
+#endif
+
+
+
+#define PAL_FS_COPY_BUFFER_SIZE 256                                                            //!< Size of the chunk to copy files
+PAL_PRIVATE const char *g_platOpenModeConvert[] = {"0", "r", "r+", "w+x", "w+"};                    //!< platform convert table for \b fopen() modes
+PAL_PRIVATE const int g_platSeekWhenceConvert[] = {0, SEEK_SET, SEEK_CUR, SEEK_END};                //!< platform convert table for \b fseek() relative position modes
+
+
+/*! \brief This function find the next file in a directory
+ *
+ * @param[in]    *dh - Directory handler to an open DIR
+ * @param[out]    CurrentEntry - entry for the file found in Directory (pre allocated)
+ *
+ * \return true - upon successful operation.\n
+ *
+ */
+PAL_PRIVATE bool pal_plat_findNextFile(DIR *dh, struct dirent ** CurrentEntry);
+
+/*! \brief This function translate the platform errors opcode to pal error codes
+ *
+ * @param[in]    errorOpCode - platform opcode to be translated
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+ */
+PAL_PRIVATE palStatus_t pal_plat_errorTranslation (int errorOpCode);
+
+
+/*! \brief This function build the full path name by adding the filename to the working path given in pathName arg
+ *
+ * @param[in]    *pathName - pointer to the null-terminated string that specifies the directory name.
+ * @param[in]   *fileName - pointer to the file name
+ * @param[out]    *fullPath - pointer to the full path including the filename (pre allocated)
+ *
+ * \return PAL_SUCCESS upon successful operation.\n
+ *         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t
+ *
+ */
+PAL_PRIVATE palStatus_t pal_plat_addFileNameToPath(const char *pathName, const char * fileName, char * fullPath);
+
+/*! \brief This function copy one file from source folder to destination folder
+*
+* @param[in]  pathNameSrc - Pointer to a null-terminated string that specifies the source dir.
+* @param[in]  pathNameDest - Pointer to a null-terminated string that specifies the destination dir
+* @param[in] fileName - pointer the the file name
+*
+* \return PAL_SUCCESS upon successful operation.\n
+*         PAL_FILE_SYSTEM_ERROR - see error code description \c palError_t
+*
+* \note File should not be open.\n
+*         If the Destination file exist then it shall be truncated
+*
+*/
+PAL_PRIVATE palStatus_t pal_plat_fsCpFile(const char *pathNameSrc,  char *pathNameDest, char * fileName);
+
+palStatus_t pal_plat_fsMkdir(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if(mkdir(pathName, 0600))
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsRmdir(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+	if (remove(pathName))
+	{
+		if((EINVAL == errno) || (EACCES == errno) || (ENOTEMPTY == errno)) // EINVAL LittleFS error code, EACCES FatFS error code
+		{
+			ret = PAL_ERR_FS_DIR_NOT_EMPTY;
+		}
+		else if(errno == ENOENT)
+		{
+			ret    = PAL_ERR_FS_NO_PATH;
+		}
+		else
+		{
+			ret = pal_plat_errorTranslation(errno);
+		}
+	}
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFopen(const char *pathName, pal_fsFileMode_t mode, palFileDescriptor_t *fd)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    if (mode == PAL_FS_FLAG_READWRITEEXCLUSIVE)
+    {
+        *fd = (palFileDescriptor_t)fopen(pathName, "r");
+        if (*fd)
+        {
+            ret = PAL_ERR_FS_NAME_ALREADY_EXIST;
+            fclose((FILE *)*fd);
+        }
+    }
+
+    if(ret == PAL_SUCCESS)
+    {
+        *fd = (palFileDescriptor_t)fopen(pathName, g_platOpenModeConvert[mode]);
+        if (!(*fd))
+        {
+            ret = pal_plat_errorTranslation(errno);
+        }
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFclose(palFileDescriptor_t *fd)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if (fclose((FILE *)*fd))
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFread(palFileDescriptor_t *fd, void * buffer, size_t numOfBytes, size_t *numberOfBytesRead)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    clearerr((FILE *)*fd);
+    *numberOfBytesRead = fread(buffer, 1, numOfBytes, (FILE *)*fd);
+    if (*numberOfBytesRead != numOfBytes)
+    {
+        if (ferror((FILE *)*fd))
+        {
+            ret = PAL_ERR_FS_ERROR;
+        }
+        clearerr((FILE *)*fd);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFwrite(palFileDescriptor_t *fd, const void *buffer, size_t numOfBytes, size_t *numberOfBytesWritten)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    errno = 0;
+    *numberOfBytesWritten = fwrite(buffer, 1, numOfBytes, (FILE *)*fd);
+    if (*numberOfBytesWritten != numOfBytes)
+    {
+        if(errno == EBADF)
+        {
+            ret = PAL_ERR_FS_ACCESS_DENIED;
+        }
+        else
+        {
+            ret = pal_plat_errorTranslation(errno);
+        }
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFseek(palFileDescriptor_t *fd, int32_t offset, pal_fsOffset_t whence)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if (fseek((FILE *)*fd, offset, g_platSeekWhenceConvert[whence]))
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsFtell(palFileDescriptor_t *fd, int32_t * pos)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    long retPos = 0;
+    *pos = 0;
+    retPos = ftell((FILE *)*fd);
+    if (retPos < 0)
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+    else
+    {
+        *pos = retPos;
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsUnlink(const char *pathName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    if (remove(pathName))
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsRmFiles(const char *pathName)
+{
+    DIR *dh = NULL; //Directory handler
+    palStatus_t ret = PAL_SUCCESS;
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; //Buffer for coping the name and folder
+    struct dirent * currentEntry = NULL; //file Entry
+
+    dh = opendir(pathName);
+    if (dh)
+    {
+        while(true)
+        {
+            if (!pal_plat_findNextFile(dh, &currentEntry))
+            {
+                break;
+            }
+
+            if (currentEntry)
+            {
+                pal_plat_addFileNameToPath(pathName, currentEntry->d_name, buffer);
+                if (currentEntry->d_type == DT_DIR)
+                {
+                    pal_plat_fsRmFiles(buffer);
+                }
+                if (remove(buffer))
+                {
+                    ret = pal_plat_errorTranslation(errno);
+                    break;
+                }
+            }
+            else
+            {//End of directory reached  without errors break, close directory and exit
+                break;
+            }
+        }//while()
+    }
+    else//if (dh)
+    {
+        ret = PAL_ERR_FS_NO_PATH;
+    }
+
+    if (dh)
+    {
+        closedir(dh); //Close DIR handler
+    }
+    return ret;
+}
+
+
+palStatus_t pal_plat_fsCpFolder(const char *pathNameSrc,  char *pathNameDest)
+{
+    DIR *src_dh = NULL; //Directory for the source Directory handler
+    palStatus_t ret = PAL_SUCCESS;
+    struct dirent * currentEntry = NULL; //file Entry
+
+    src_dh = opendir(pathNameSrc);
+    if (src_dh == NULL)
+    {
+        ret = PAL_ERR_FS_NO_PATH;
+    }
+
+    if (ret == PAL_SUCCESS)
+    {
+        while(true)
+        {
+        	currentEntry = NULL;
+            if (!pal_plat_findNextFile(src_dh, &currentEntry))
+            {
+                break;
+            }
+
+            if (currentEntry)
+            {
+                if (currentEntry->d_type == DT_DIR)
+                {
+                    continue;
+                }
+                //copy the file to the destination
+                ret = pal_plat_fsCpFile(pathNameSrc, pathNameDest, currentEntry->d_name);
+                if (ret != PAL_SUCCESS)
+                {
+                    break;
+                }
+            }
+            else
+            {//End of directory reached  without errors break and close directory and exit
+                break;
+            }
+        }//while()
+    }
+
+    if (src_dh)
+    {
+        closedir(src_dh);
+    }
+    return ret;
+}
+
+
+PAL_PRIVATE palStatus_t pal_plat_fsCpFile(const char *pathNameSrc,  char *pathNameDest, char * fileName)
+{
+    palStatus_t ret = PAL_SUCCESS;
+    palFileDescriptor_t src_fd = 0;
+    palFileDescriptor_t dst_fd = 0;
+    char buffer_name[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0}; //Buffer for coping the name and folder
+    char * buffer = NULL;
+    size_t bytesCount = 0;
+
+    //Add file name to path
+    pal_plat_addFileNameToPath(pathNameSrc, fileName, buffer_name);
+    src_fd = (palFileDescriptor_t)fopen(buffer_name, g_platOpenModeConvert[PAL_FS_FLAG_READONLY]);
+    if (src_fd == 0)
+    {
+        ret = pal_plat_errorTranslation(errno);
+    }
+    else
+    {
+        //Add file name to path
+        pal_plat_addFileNameToPath(pathNameDest, fileName, buffer_name);
+        dst_fd = (palFileDescriptor_t)fopen(buffer_name, g_platOpenModeConvert[PAL_FS_FLAG_READWRITETRUNC]);
+        if (dst_fd == 0)
+        {
+            ret = pal_plat_errorTranslation(errno);
+        }
+        else
+        {
+            buffer = (char*)malloc(PAL_FS_COPY_BUFFER_SIZE);
+            if (!buffer)
+            {
+                ret = PAL_ERR_RTOS_RESOURCE;
+            }
+        }
+    }
+
+    if (ret == PAL_SUCCESS)
+    {
+        while (1)
+        {
+            ret = pal_fsFread(&src_fd, buffer, PAL_FS_COPY_BUFFER_SIZE, &bytesCount);
+            if (ret != PAL_SUCCESS)
+            {
+                break;
+            }
+
+            //Check if end of file reached
+            if (bytesCount == 0)
+            {
+                break;
+            }
+
+            ret = pal_fsFwrite(&dst_fd, buffer, bytesCount, &bytesCount);
+            if (ret != PAL_SUCCESS)
+            {
+                break;
+            }
+        }
+    }
+
+    if (src_fd != 0)
+    {
+        pal_fsFclose(&src_fd);
+    }
+    if (dst_fd != 0)
+    {
+        pal_fsFclose(&dst_fd);
+    }
+    if (buffer)
+    {
+        free(buffer);
+    }
+    return ret;
+}
+
+
+const char* pal_plat_fsGetDefaultRootFolder(pal_fsStorageID_t dataID)
+{
+    const char* returnedRoot = NULL;
+    if (PAL_FS_PARTITION_PRIMARY == dataID)
+    {
+        returnedRoot = PAL_FS_MOUNT_POINT_PRIMARY;
+    }
+    else if (PAL_FS_PARTITION_SECONDARY == dataID)
+    {
+        returnedRoot = PAL_FS_MOUNT_POINT_SECONDARY;
+    }
+
+    return returnedRoot;
+}
+
+
+PAL_PRIVATE bool pal_plat_findNextFile(DIR *dh, struct dirent ** CurrentEntry)
+{
+    bool ret = true;
+    bool skip = false;
+    bool foundFile = false;
+
+    do
+    {
+        errno = 0;
+        *CurrentEntry = readdir(dh);
+        if (*CurrentEntry)
+        {
+            /* Skip the names "." and ".." as we don't want to remove them. also make sure that the current entry point to REGULER file*/
+        	skip = ((!strcmp((*CurrentEntry)->d_name, ".")) || (!strcmp((*CurrentEntry)->d_name, "..")));
+        	if (skip)
+            {
+                continue;
+            }
+            else
+            {
+                foundFile = true;
+            }
+        }
+        else
+        {
+            ret = false;
+            break; //Break from while
+        }
+    }
+    while((!foundFile) && (ret)); //While file has been found or ret is set to false
+
+    return ret;
+}
+
+PAL_PRIVATE palStatus_t pal_plat_addFileNameToPath(const char *pathName, const char * fileName, char * fullPath)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    if ((strlen(pathName) >= PAL_MAX_FOLDER_DEPTH_CHAR)  || (strlen(fileName) >= PAL_MAX_FULL_FILE_NAME))
+    {
+        ret = PAL_ERR_FS_FILENAME_LENGTH;
+    }
+    else if (fullPath)
+    {
+        strcpy(fullPath, pathName);
+        strcat(fullPath, "/");
+        strcat(fullPath, fileName);
+    }
+    else
+    {
+        ret = PAL_ERR_RTOS_RESOURCE;
+    }
+    return ret;
+}
+
+
+
+
+PAL_PRIVATE palStatus_t pal_plat_errorTranslation (int errorOpCode)
+{
+    palStatus_t ret = PAL_SUCCESS;
+
+    switch(errorOpCode)
+    {
+    case 0:
+        break;
+
+    case EACCES:
+    case EFAULT:
+    case EROFS:
+        ret = PAL_ERR_FS_ACCESS_DENIED;
+        break;
+
+    case EBUSY:
+        ret = PAL_ERR_FS_BUSY;
+        break;
+
+    case EEXIST:
+        ret = PAL_ERR_FS_NAME_ALREADY_EXIST;
+        break;
+
+    case ENAMETOOLONG:
+        ret = PAL_ERR_FS_FILENAME_LENGTH;
+        break;
+
+    case -1: // This makes it compatible with mbedOS 5.8 , check https://github.com/ARMmbed/mbed-os/pull/6120
+    case ETIMEDOUT: // This makes it compatible with mbedOS 5.8, check https://github.com/ARMmbed/mbed-os/pull/6120
+    case EBADF:
+        ret = PAL_ERR_FS_BAD_FD;
+        break;
+
+    case ENOEXEC: // This makes it compatible with mbedOS 5.8, check https://github.com/ARMmbed/mbed-os/pull/6120
+    case EINVAL:
+        ret = PAL_ERR_FS_INVALID_ARGUMENT;
+        break;
+
+    case EISDIR:
+        ret = PAL_ERR_FS_FILE_IS_DIR;
+        break;
+
+    case ENOTEMPTY:
+        ret = PAL_ERR_FS_DIR_NOT_EMPTY;
+        break;
+
+    case ENOTDIR: // This makes it compatible with mbedOS 5.8, check https://github.com/ARMmbed/mbed-os/pull/6120
+    case ENODEV: // This makes it compatible with mbedOS 5.8, check https://github.com/ARMmbed/mbed-os/pull/6120
+    case ENXIO: // This makes it compatible with mbedOS 5.8, check https://github.com/ARMmbed/mbed-os/pull/6120
+    case ENOENT:
+        ret = PAL_ERR_FS_NO_FILE;
+        break;
+
+    case EIO: // This makes it compatible with mbedOS 5.8, check https://github.com/ARMmbed/mbed-os/pull/6120
+        ret = PAL_ERR_FS_DISK_ERR;
+        break;
+
+    default:
+        ret = PAL_ERR_FS_ERROR;
+        break;
+    }
+    return ret;
+}
+
+
+size_t pal_plat_fsSizeCheck(const char *stringToChk)
+{
+    size_t length = 0;
+    length = strlen(stringToChk);
+    return length;
+}
+
+
+
+
+
+palStatus_t pal_plat_fsFormat(pal_fsStorageID_t dataID)
+{
+    const char* partitionTranslationArray[] =
+                                  {
+                                          PAL_FS_MOUNT_POINT_PRIMARY,
+                                          PAL_FS_MOUNT_POINT_SECONDARY
+                                  };//  "/sd\0"
+    FileSystem *myFs;
+    int err = 0;
+    palStatus_t status = PAL_SUCCESS;
+    FilePath myPath(partitionTranslationArray[dataID]);
+    myFs = (FileSystem*)myPath.fileSystem();
+    if (NULL != myFs) 
+    {
+        err = myFs->reformat(NULL);
+        if (err < 0)
+        {
+            status = PAL_ERR_FS_ERROR;
+        }
+    }
+    else //This should not happen
+    {
+        status = PAL_ERR_FS_ERROR;
+    }
+    return status;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Storage/Flash/pal_plat_internalFlash.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "mbed.h"
+#include "flash_api.h"
+#include "pal.h"
+#include "pal_plat_internalFlash.h"
+
+
+////////////////////////////PRIVATE///////////////////////////////////
+PAL_PRIVATE FlashIAP flash;
+PAL_PRIVATE palStatus_t pal_platFlashErrorTranslation(int32_t status);
+////////////////////////////END PRIVATE////////////////////////////////
+
+palStatus_t pal_plat_internalFlashInit(void)
+{
+	uint32_t status = 0;
+	palStatus_t ret = PAL_SUCCESS;
+	status = flash.init();
+	if (status != 0)
+	{
+		ret = pal_platFlashErrorTranslation(status);
+	}
+	return ret;
+}
+
+
+palStatus_t pal_plat_internalFlashDeInit(void)
+{
+	uint32_t status = 0;
+	palStatus_t ret = PAL_SUCCESS;
+	status = flash.deinit();
+	if (status != 0)
+	{
+		ret = pal_platFlashErrorTranslation(status);
+	}
+	return ret;
+}
+
+
+palStatus_t pal_plat_internalFlashWrite(const size_t size, const uint32_t address, const uint32_t * buffer)
+{
+	uint32_t status = 0;
+	palStatus_t ret = PAL_SUCCESS;
+
+	status = flash.program(buffer, address, size);
+	if (status != 0)
+	{
+		ret = pal_platFlashErrorTranslation(status);
+	}
+	return ret;
+}
+
+
+palStatus_t pal_plat_internalFlashRead(const size_t size, const uint32_t address, uint32_t * buffer)
+{
+	uint32_t status = 0;
+	palStatus_t ret = PAL_SUCCESS;
+	status = flash.read(buffer, address, size);
+	if (status != 0)
+	{
+		ret = pal_platFlashErrorTranslation(status);
+	}
+	return ret;
+}
+
+
+palStatus_t pal_plat_internalFlashErase(uint32_t address, size_t size)
+{
+	uint32_t status = 0;
+	palStatus_t ret = PAL_SUCCESS;
+
+	status = flash.erase(address, size);
+	if (status != 0)
+	{
+		ret = pal_platFlashErrorTranslation(status);
+	}
+	return ret;
+}
+
+
+size_t pal_plat_internalFlashGetPageSize(void)
+{
+	size_t ret = flash.get_page_size();
+	return ret;
+}
+
+
+size_t pal_plat_internalFlashGetSectorSize(uint32_t address)
+{
+	size_t ret = flash.get_sector_size(address);
+	return ret;
+}
+
+
+PAL_PRIVATE palStatus_t pal_platFlashErrorTranslation(int32_t status)
+{
+	return PAL_ERR_INTERNAL_FLASH_GENERIC_FAILURE;//ALL mbedOS error are -1
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Source/Port/Reference-Impl/OS_Specific/mbedOS/Update/pal_plat_update.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include <mbed.h>
+#include <pal.h>
+#include <pal_plat_update.h>
+
+
+#ifndef PAL_UPDATE_ACTIVE_METADATA_HEADER_OFFSET
+#ifdef MBED_CONF_MBED_CLIENT_PAL_UPDATE_ACTIVE_METADATA_HEADER_OFFSET
+#define PAL_UPDATE_ACTIVE_METADATA_HEADER_OFFSET MBED_CONF_MBED_CLIENT_PAL_UPDATE_ACTIVE_METADATA_HEADER_OFFSET
+#else  // MBED_CONF_MBED_CLIENT_PAL_UPDATE_ACTIVE_METADATA_HEADER_OFFSET
+#define PAL_UPDATE_ACTIVE_METADATA_HEADER_OFFSET 0
+#endif // MBED_CONF_MBED_CLIENT_PAL_UPDATE_ACTIVE_METADATA_HEADER_OFFSET
+#endif // PAL_UPDATE_ACTIVE_METADATA_HEADER_OFFSET
+
+palStatus_t pal_plat_imageInitAPI(palImageSignalEvent_t CBfunction)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageDeInit(void)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageGetMaxNumberOfImages(uint8_t *imageNumber)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageSetVersion(palImageId_t imageId, const palConstBuffer_t* version)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageGetDirectMemAccess(palImageId_t imageId, void** imagePtr, size_t *imageSizeInBytes)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageActivate(palImageId_t imageId)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageGetActiveHash(palBuffer_t *hash)
+{
+    palStatus_t ret = PAL_ERR_UPDATE_ERROR;
+    uint32_t read_offset = PAL_UPDATE_ACTIVE_METADATA_HEADER_OFFSET +
+                            offsetof(FirmwareHeader_t, firmwareSHA256);
+
+    FlashIAP flash;
+    int rc = -1;
+
+    rc = flash.init();
+    if (rc != 0)
+    {
+        DEBUG_PRINT("flash init failed\r\n");
+        goto exit;
+    }
+
+
+    rc = flash.read(hash->buffer, read_offset, SIZEOF_SHA256);
+    if (rc != 0)
+    {
+        DEBUG_PRINT("flash read failed\r\n");
+        goto exit;
+    }
+
+    hash->bufferLength = SIZEOF_SHA256;
+
+    rc = flash.deinit();
+    if (rc != 0)
+    {
+        DEBUG_PRINT("flash deinit failed\r\n");
+        goto exit;
+    }
+
+    ret = PAL_SUCCESS;
+
+exit:
+    return ret;
+}
+
+palStatus_t pal_plat_imageGetActiveVersion (palBuffer_t* version)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageWriteHashToMemory(const palConstBuffer_t* const hashValue)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageSetHeader(palImageId_t imageId, palImageHeaderDeails_t *details)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageReserveSpace(palImageId_t imageId, size_t imageSize)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageWrite(palImageId_t imageId, size_t offset, palConstBuffer_t *chunk)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageReadToBuffer(palImageId_t imageId, size_t offset, palBuffer_t *chunk)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
+
+palStatus_t pal_plat_imageFlush(palImageId_t package_id)
+{
+    return PAL_ERR_NOT_IMPLEMENTED;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,5 @@
+Unity/examples/*
+Unity/test/*
+Unity/extras/fixture/test/*
+Unity/
+PAL_Modules/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/CMakeLists.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,174 @@
+include_directories(../Source/PAL-Impl/Services-API) 
+include_directories(../Source/Port/Platform-API)
+option(SPLIT_BINARIES "Choose whether to split the tests into 2 binaries or not" OFF)
+
+
+
+
+
+if (${OS_BRAND} MATCHES FreeRTOS)
+	add_definitions(-DUNITY_OUTPUT_CHAR=unity_output_char)
+endif()
+
+add_definitions(-DSOTP_TESTING)
+
+#on Linux, we might find different names for the network interface
+#so we have to find it, and pass to the code.
+if (${OS_BRAND} MATCHES Linux)
+  add_definitions(-DPAL_NO_FATFS_SD_TEST=1)
+  if (NOT USE_ETH_INTERFACE)
+    execute_process(COMMAND ip -o -4 route show to default 
+	                  COMMAND awk "{print $5}" 
+			  COMMAND head -1 
+	                  OUTPUT_STRIP_TRAILING_WHITESPACE
+	                  OUTPUT_VARIABLE  ETHNAME)
+    set(TMPD \"${ETHNAME}\")
+    add_definitions(-DPAL_LINUX_ETH=${TMPD})
+    message( "ETHNAME = ${ETHNAME}")
+  else()
+    add_definitions(-DPAL_LINUX_ETH=${USE_ETH_INTERFACE})
+    message("Using ${USE_ETH_INTERFACE} for network")
+  endif()
+endif()
+
+if (CMAKE_BUILD_TYPE MATCHES Debug)
+	add_definitions(-DDEBUG)
+endif()
+
+include_directories(Unitest)
+include_directories(Common)  
+include_directories(Unity/src) 
+include_directories(Unity/extras/fixture/src)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/PAL_Modules/)
+
+
+set (PAL_TESTS_SOURCE_DIR   ${CMAKE_CURRENT_SOURCE_DIR}/PAL_Modules/)
+set (PAL_TESTS_RUNNER_DIR   ${CMAKE_CURRENT_SOURCE_DIR}/TESTS/Unitest/)
+set (PAL_TESTS_SOTP_DIR     ${CMAKE_CURRENT_SOURCE_DIR}/TESTS/Sotp/)
+set (PAL_UNITY_SOURCE_DIR   ${CMAKE_CURRENT_SOURCE_DIR}/Unity/src/)
+set (PAL_UNITY_FIXTURE_DIR  ${CMAKE_CURRENT_SOURCE_DIR}/Unity/extras/fixture/src)
+set (PAL_TEST_BSP_DIR       ${CMAKE_CURRENT_SOURCE_DIR}/../Examples/PlatformBSP)
+set (PAL_UTILS_DIR          ${CMAKE_CURRENT_SOURCE_DIR}/../Utils/memoryProfiler/Other)
+
+  
+file(GLOB PAL_TEST_RTOS_SRCS "${PAL_TESTS_SOURCE_DIR}/RTOS/*.c")
+
+file(GLOB PAL_TEST_SANITY_SRCS "${PAL_TESTS_SOURCE_DIR}/Sanity/*.c")
+
+file(GLOB PAL_TEST_NETWORK_SRCS "${PAL_TESTS_SOURCE_DIR}/Networking/*.c")
+
+file(GLOB PAL_TEST_FS_SRCS "${PAL_TESTS_SOURCE_DIR}/FileSystem/*.c")
+
+file(GLOB PAL_TEST_TLS_SRCS "${PAL_TESTS_SOURCE_DIR}/TLS/*.c")
+
+file(GLOB_RECURSE PAL_TEST_CRYPTO_SRCS "${PAL_TESTS_SOURCE_DIR}/Crypto/*.c")
+
+file(GLOB PAL_TEST_UPDATE_SRCS "${PAL_TESTS_SOURCE_DIR}/Update/*")
+
+file(GLOB PAL_TEST_FLASH_SRCS "${PAL_TESTS_SOURCE_DIR}/Storage/*.c")
+
+file(GLOB PAL_TEST_SOTP_SRCS "${PAL_TESTS_SOURCE_DIR}/SOTP/*.c")
+
+file(GLOB PAL_TEST_MAIN_SRCS "${PAL_TESTS_SOURCE_DIR}/*.c")
+
+
+file(GLOB PAL_TEST_RUNNER_SANITY_SRCS "${PAL_TESTS_RUNNER_DIR}/Sanity/*.c")
+
+file(GLOB PAL_TEST_RUNNER_RTOS_SRCS "${PAL_TESTS_RUNNER_DIR}/RTOS/*.c")
+
+file(GLOB PAL_TEST_RUNNER_NETWORK_SRCS "${PAL_TESTS_RUNNER_DIR}/Networking/*.c")
+
+file(GLOB PAL_TEST_RUNNER_FS_SRCS "${PAL_TESTS_RUNNER_DIR}/FileSystem/*.c")
+
+file(GLOB PAL_TEST_RUNNER_TLS_SRCS "${PAL_TESTS_RUNNER_DIR}/TLS/*.c")
+
+file(GLOB PAL_TEST_RUNNER_CRYPTO_SRCS "${PAL_TESTS_RUNNER_DIR}/Crypto/*.c")
+
+file(GLOB PAL_TEST_RUNNER_UPDATE_SRCS "${PAL_TESTS_RUNNER_DIR}/Update/*.c")
+
+file(GLOB PAL_TEST_RUNNER_FLASH_SRCS "${PAL_TESTS_RUNNER_DIR}/Storage/*.c")
+
+file(GLOB PAL_TEST_RUNNER_FULL_SRCS "${PAL_TESTS_RUNNER_DIR}/Full_pal/*.c")
+
+file(GLOB PAL_TEST_RUNNER_SOTP_SRCS "${PAL_TESTS_SOTP_DIR}/security/*.c")
+
+
+message(PAL_TESTS_RUNNER_DIR = ${PAL_TESTS_RUNNER_DIR})
+message(PAL_TEST_MAIN_SRCS = ${PAL_TEST_MAIN_SRCS})
+
+
+file(GLOB PAL_TEST_BSP_SRCS "${PAL_TEST_BSP_DIR}/${PAL_TARGET_DEVICE}_${OS_BRAND}/*")
+
+set(PAL_TEST_UNITY_SRC
+  	${PAL_UNITY_SOURCE_DIR}/unity.c
+  	${PAL_UNITY_FIXTURE_DIR}/unity_fixture.c
+)
+
+
+set(PAL_INSECURE_ROT_SRC
+	  ${PAL_TEST_BSP_DIR}/pal_insecure_ROT.c
+	  )
+
+if (PAL_MEMORY_STATISTICS) #currently working only in gcc based compilers
+    list (APPEND PAL_TEST_BSP_SRCS  ${PAL_UTILS_DIR}/pal_memory.c)
+    add_definitions(-DPAL_MEMORY_STATISTICS=1)
+endif() 
+
+ADD_GLOBALDIR(${PAL_TEST_BSP_DIR}/Include/)
+ADD_GLOBALDIR(${PAL_TESTS_SOURCE_DIR}/Includes/)
+
+set(test_src ${PAL_TEST_BSP_SRCS}; ${PAL_INSECURE_ROT_SRC}; ${PAL_TEST_SOTP_SRCS}; ${PAL_TEST_MAIN_SRCS}; ${PAL_TEST_NETWORK_SRCS}; ${PAL_TEST_TLS_SRCS}; ${PAL_TEST_CRYPTO_SRCS}; ${PAL_TEST_RTOS_SRCS}; ${PAL_TEST_FLASH_SRCS}; ${PAL_TEST_FS_SRCS}; ${PAL_TEST_UPDATE_SRCS}; ${PAL_TEST_SANITY_SRCS}; ${PAL_TEST_UNITY_SRC})
+set (PAL_TEST_FLAGS
+	-DPAL_TEST_RTOS
+	-DPAL_TEST_FS
+	-DPAL_TEST_UPDATE
+	-DPAL_TEST_NETWORK
+	-DPAL_TEST_TLS
+	-DPAL_TEST_CRYPTO
+	-DPAL_TEST_FLASH
+)
+	
+set(sanity_test_src ${test_src}; ${PAL_TEST_RUNNER_SANITY_SRCS}) 
+
+CREATE_TEST_LIBRARY(sanityTests "${sanity_test_src}" "${PAL_TEST_FLAGS}")	
+	
+set(rtos_test_src ${test_src}; ${PAL_TEST_RUNNER_RTOS_SRCS}) 
+
+CREATE_TEST_LIBRARY(RTOSTests "${rtos_test_src}" "${PAL_TEST_FLAGS}")
+
+set(network_test_src ${test_src}; ${PAL_TEST_RUNNER_NETWORK_SRCS}) 
+
+CREATE_TEST_LIBRARY(NetworkTests "${network_test_src}" "${PAL_TEST_FLAGS}")
+
+set(fs_test_src ${test_src}; ${PAL_TEST_RUNNER_FS_SRCS}) 
+
+CREATE_TEST_LIBRARY(FileSystemTests "${fs_test_src}" "${PAL_TEST_FLAGS}")
+
+set(tls_test_src ${test_src}; ${PAL_TEST_RUNNER_TLS_SRCS}) 
+
+CREATE_TEST_LIBRARY(TLSTests "${tls_test_src}" "${PAL_TEST_FLAGS}")
+
+set(crypto_test_src ${test_src}; ${PAL_TEST_RUNNER_CRYPTO_SRCS}) 
+
+CREATE_TEST_LIBRARY(CryptoTests "${crypto_test_src}" "${PAL_TEST_FLAGS}")
+
+set(update_test_src ${test_src}; ${PAL_TEST_RUNNER_UPDATE_SRCS}) 
+
+CREATE_TEST_LIBRARY(UpdateTests "${update_test_src}" "${PAL_TEST_FLAGS}")
+
+set(flash_test_src ${test_src}; ${PAL_TEST_RUNNER_FLASH_SRCS}) 
+
+CREATE_TEST_LIBRARY(FlashTests "${flash_test_src}" "${PAL_TEST_FLAGS}")
+
+set(sotp_test_src ${test_src}; ${PAL_TEST_RUNNER_SOTP_SRCS}) 
+
+CREATE_TEST_LIBRARY(SotpTests "${sotp_test_src}" "${PAL_TEST_FLAGS}")
+
+set(all_test_src ${test_src}; ${PAL_TEST_RUNNER_FULL_SRCS})
+
+CREATE_TEST_LIBRARY(palTests "${all_test_src}" "${PAL_TEST_FLAGS}")
+
+
+CREATE_LIBRARY(palBringup "${PAL_TEST_BSP_SRCS}" "")
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Crypto/pal_crypto_test.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1242 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal.h"
+#include "pal_Crypto.h"
+#include "unity.h"
+#include "unity_fixture.h"
+#include "pal_crypto_test_data.h"
+#include "string.h"
+#include "time.h"
+
+
+TEST_GROUP(pal_crypto);
+
+TEST_SETUP(pal_crypto)
+{
+    pal_init();
+    palStatus_t status = PAL_SUCCESS;
+    uint64_t currentTime = 1512572014; //GMT: Wed, 06 Dec 2017 14:53:33 GMT
+    status = pal_osSetTime(currentTime);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+}
+
+TEST_TEAR_DOWN(pal_crypto)
+{
+    pal_destroy();
+}
+
+/**
+ * @brief Testing AES encryption and decryption of buffers in CTR mode.
+ * 
+ * The test encrypts a buffer, compares it against a desired result and then decrypts it back and compares with the original buffer.
+ *
+ * Uses CtrVector.
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Initialize an AES context.                                                              | PAL_SUCCESS |
+ * | 2 | Set an AES 128bit key for encryption.                                                   | PAL_SUCCESS |
+ * | 3 | Perform AES CTR encryption on an input vector and check that the result is as expected. | PAL_SUCCESS |
+ * | 4 | Release AES context.                                                                    | PAL_SUCCESS |
+ * | 5 | Initialize an AES context.                                                              | PAL_SUCCESS |
+ * | 6 | Set an AES 128bit key for encryption (used for decryption, see AES CTR docs)            | PAL_SUCCESS |
+ * | 7 | Perform AES CTR decryption on an input vector and check that the result is as expected. | PAL_SUCCESS |
+ * | 8 | Release AES context.                                                                    | PAL_SUCCESS |
+ */
+TEST(pal_crypto, AES_CTR)
+{
+    palStatus_t result;
+    palAesHandle_t ctx_enc = NULLPTR, ctx_dec = NULLPTR;
+    unsigned char out[16] = {0};
+    unsigned char iv[16] = {0};
+
+    memcpy(iv, CtrVector.nonce, sizeof(CtrVector.nonce));
+
+    /*#1*/
+    result = pal_initAes(&ctx_enc);
+    TEST_ASSERT_NOT_EQUAL(ctx_enc, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#2*/
+    result = pal_setAesKey(ctx_enc, CtrVector.key, 128, PAL_KEY_TARGET_ENCRYPTION);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#3*/
+    result = pal_aesCTR(ctx_enc, CtrVector.input, out, sizeof(CtrVector.input), iv);
+    TEST_ASSERT_EQUAL_MEMORY(CtrVector.output, out, sizeof(CtrVector.output));
+
+    /*#4*/
+    result = pal_freeAes(&ctx_enc);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    memcpy(iv, CtrVector.nonce, sizeof(CtrVector.nonce));
+    memset(out, 0, sizeof(out));
+
+    /*#5*/
+    result = pal_initAes(&ctx_dec);
+    TEST_ASSERT_NOT_EQUAL(ctx_dec, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#6*/
+    result = pal_setAesKey(ctx_dec, CtrVector.key, 128, PAL_KEY_TARGET_ENCRYPTION);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#7*/
+    result = pal_aesCTR(ctx_dec, CtrVector.output, out, sizeof(CtrVector.output), iv);
+    TEST_ASSERT_EQUAL_MEMORY(CtrVector.input, out, sizeof(CtrVector.output));
+
+    /*#8*/
+    result = pal_freeAes(&ctx_dec);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+}
+
+/**
+ * @brief Testing AES encryption and decryption of buffers in CTR mode.
+ *
+ * The test encrypts a buffer, compares it against the desired result and then decrypts it back and compares with the original buffer.
+ *
+ * Uses CtrVector.
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Initialize an AES context.                                                             | PAL_SUCCESS |
+ * | 2 | Set an AES 128bit key for encryption.                                                  | PAL_SUCCESS |
+ * | 3 | Perform AES CTR encryption on input vector and check the encryption output.            | PAL_SUCCESS |
+ * | 4 | Release AES context.                                                                   | PAL_SUCCESS |
+ * | 5 | Initialize an AES context.                                                             | PAL_SUCCESS |
+ * | 6 | Set an AES 128bit key for encryption (used for decryption, see AES CTR docs).          | PAL_SUCCESS |
+ * | 7 | Perform AES CTR decryption on an input vector and check that the result is as expected.| PAL_SUCCESS |
+ * | 8 | Release AES context.                                                                   | PAL_SUCCESS |
+ */
+TEST(pal_crypto, AES_CTR_ZeroOffset)
+{
+    palStatus_t result;
+    palAesHandle_t ctx_enc = NULLPTR, ctx_dec = NULLPTR;
+    unsigned char out[16] = {0};
+    unsigned char iv[16] = {0};
+
+    memcpy(iv, CtrVector.nonce, sizeof(CtrVector.nonce));
+
+    /*#1*/
+    result = pal_initAes(&ctx_enc);
+    TEST_ASSERT_NOT_EQUAL(ctx_enc, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#2*/
+    result = pal_setAesKey(ctx_enc, CtrVector.key, 128, PAL_KEY_TARGET_ENCRYPTION);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#3*/
+    result = pal_aesCTRWithZeroOffset(ctx_enc, CtrVector.input, out, sizeof(CtrVector.input), iv);
+    TEST_ASSERT_EQUAL_MEMORY(CtrVector.output, out, sizeof(CtrVector.output));
+
+    /*#4*/
+    result = pal_freeAes(&ctx_enc);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    memcpy(iv, CtrVector.nonce, sizeof(CtrVector.nonce));
+    memset(out, 0, sizeof(out));
+
+    /*#5*/
+    result = pal_initAes(&ctx_dec);
+    TEST_ASSERT_NOT_EQUAL(ctx_dec, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#6*/
+    result = pal_setAesKey(ctx_dec, CtrVector.key, 128, PAL_KEY_TARGET_ENCRYPTION);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#7*/
+    result = pal_aesCTRWithZeroOffset(ctx_dec, CtrVector.output, out, sizeof(CtrVector.output), iv);
+    TEST_ASSERT_EQUAL_MEMORY(CtrVector.input, out, sizeof(CtrVector.output));
+
+    /*#8*/
+    result = pal_freeAes(&ctx_dec);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+}
+
+
+/**
+ * @brief Testing AES encryption and decryption of buffers in ECB mode.
+ *
+ * The test encrypts a buffer, compares it against the desired result and then decrypts it back and compares with the original buffer.
+ *
+ * Uses EcbVector.
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Initialize an AES context.                                                             | PAL_SUCCESS |
+ * | 2 | Set an AES 128bit key for encryption.                                                  | PAL_SUCCESS |
+ * | 3 | Perform AES ECB encryption on input vector and check the encryption output.            | PAL_SUCCESS |
+ * | 4 | Release AES context.                                                                   | PAL_SUCCESS |
+ * | 5 | Initialize an AES context.                                                             | PAL_SUCCESS |
+ * | 6 | Set an AES 128bit key for decryption.                                                  | PAL_SUCCESS |
+ * | 7 | Perform AES ECB decryption on an input vector and check that the result is as expected.| PAL_SUCCESS |
+ * | 8 | Release AES context.                                                                   | PAL_SUCCESS |
+ */
+TEST(pal_crypto, AES_ECB)
+{
+    palStatus_t result;
+    palAesHandle_t ctx_enc = NULLPTR, ctx_dec = NULLPTR;
+    unsigned char out[16] = {0};
+    unsigned char iv[16] = {0};
+
+    memcpy(iv, EcbVector.nonce, sizeof(EcbVector.nonce));
+
+    /*#1*/
+    result = pal_initAes(&ctx_enc);
+    TEST_ASSERT_NOT_EQUAL(ctx_enc, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#2*/
+    result = pal_setAesKey(ctx_enc, EcbVector.key, 128, PAL_KEY_TARGET_ENCRYPTION);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#3*/
+    result = pal_aesECB(ctx_enc, EcbVector.input, out, PAL_AES_ENCRYPT);
+    TEST_ASSERT_EQUAL_MEMORY(EcbVector.output, out, sizeof(EcbVector.output));
+
+    /*#4*/
+    result = pal_freeAes(&ctx_enc);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    memcpy(iv, EcbVector.nonce, sizeof(EcbVector.nonce));
+    memset(out, 0, sizeof(out));
+
+    /*#5*/
+    result = pal_initAes(&ctx_dec);
+    TEST_ASSERT_NOT_EQUAL(ctx_dec, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#6*/
+    result = pal_setAesKey(ctx_dec, EcbVector.key, 128, PAL_KEY_TARGET_DECRYPTION);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#7*/
+    result = pal_aesECB(ctx_dec, EcbVector.output, out, PAL_AES_DECRYPT);
+    TEST_ASSERT_EQUAL_MEMORY(EcbVector.input, out, sizeof(EcbVector.output));
+
+    /*#8*/
+    result = pal_freeAes(&ctx_dec);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+}
+
+
+/**
+ * @brief Testing AES encryption and decryption of buffers in CCM mode.
+ *
+ * The test encrypts a buffer, compares it against the desired result and then decrypts it back and compares with the original buffer.
+ *
+ * Uses aesCcmVectors.
+ *
+ * For each vector:
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Initialize an AES CCM context.                                                         | PAL_SUCCESS |
+ * | 2 | Set an AES 128bit key for this particular vector.                                      | PAL_SUCCESS |
+ * | 3 | Perform AES CCM encryption on input vector and check the encryption output.            | PAL_SUCCESS |
+ * | 4 | Perform AES CCM decryption on an input vector and check that the result is as expected.| PAL_SUCCESS |
+ * | 5 | Release AES CCM context.                                                               | PAL_SUCCESS |
+ */
+TEST(pal_crypto, AES_CCM)
+{
+    palStatus_t result;
+    palCCMHandle_t ctx = NULLPTR;
+
+    unsigned char iv[16] = {0};
+    unsigned char encryptBuffer[32] = {0};
+    unsigned char decryptBuffer[32] = {0};
+
+
+    for (size_t i = 0; i < sizeof(aesCcmVectors) / sizeof(palAesCcmVector_t); ++i)
+    {
+        memset(encryptBuffer, 0, sizeof(encryptBuffer));
+        memset(decryptBuffer, 0, sizeof(decryptBuffer));
+        memset(iv, 0, sizeof(iv));
+        memcpy(iv, aesCcmVectors[i].iv, aesCcmVectors[i].ivLen);
+
+        /*#1*/
+        result = pal_CCMInit(&ctx);
+        TEST_ASSERT_NOT_EQUAL(ctx, NULLPTR);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+        /*#2*/
+        result = pal_CCMSetKey(ctx, aesCcmVectors[i].key, 128, PAL_CIPHER_ID_AES);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+        /*#3*/
+        result = pal_CCMEncrypt(ctx, (unsigned char*)aesCcmVectors[i].in, aesCcmVectors[i].inLen,
+                iv, aesCcmVectors[i].ivLen, (unsigned char*)aesCcmVectors[i].ad, aesCcmVectors[i].adLen,
+                encryptBuffer, encryptBuffer + aesCcmVectors[i].inLen, aesCcmVectors[i].tagLen);
+
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        TEST_ASSERT_EQUAL_MEMORY(aesCcmVectors[i].out, encryptBuffer, aesCcmVectors[i].inLen + aesCcmVectors[i].tagLen);
+
+        /*#4*/
+        result = pal_CCMDecrypt(ctx, encryptBuffer, aesCcmVectors[i].inLen,
+                iv, aesCcmVectors[i].ivLen, (unsigned char*)aesCcmVectors[i].ad, aesCcmVectors[i].adLen,
+                encryptBuffer + aesCcmVectors[i].inLen,    aesCcmVectors[i].tagLen, decryptBuffer);
+
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        TEST_ASSERT_EQUAL_MEMORY(aesCcmVectors[i].in, decryptBuffer, aesCcmVectors[i].inLen);
+
+        /*#5*/
+        result = pal_CCMFree(&ctx);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    }
+}
+
+
+/**
+ * @brief Testing SHA256 hash algorithm.
+ *
+ * The test hashes a few buffers and compares them with a well known result using SHA256.
+ *
+ * Uses sha256Vectors.
+ *
+ * For each vector:
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Perform SHA256 hash on the input vector and check the resulting digest Small input Buffers.     | PAL_SUCCESS |
+ * | 2 | Perform SHA256 hash on the input vector and check the resulting digest BIG input buffer.     | PAL_SUCCESS |
+ */
+TEST(pal_crypto, SHA256)
+{
+    palStatus_t result;
+    unsigned char output[32];
+
+    for (size_t i = 0; i < sizeof(sha256Vectors) / sizeof(palSha256Vector_t); ++i)
+    {
+        memset(output, 0x0, sizeof(output));
+        /*#1*/
+        result = pal_sha256(sha256Vectors[i].input, sha256Vectors[i].inLenInBytes, output);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+        TEST_ASSERT_EQUAL_MEMORY(sha256Vectors[i].output, output, sizeof(sha256Vectors[i].output));
+    }
+
+    	memset(output, 0x0, sizeof(output));
+	/*#2*/
+	result = pal_sha256(sha256Vectors_2nd.input, sha256Vectors_2nd.inLenInBytes, output);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+	TEST_ASSERT_EQUAL_MEMORY(sha256Vectors_2nd.output, output, sizeof(sha256Vectors_2nd.output));
+
+}
+
+
+/**
+ * @brief Testing message digest using SHA256 hash algorithm.
+ *
+ * The test calculates a message digest of the buffers and compares them against the expected results.
+ *
+ * Uses sha256Vectors.
+ *
+ * For each vector:
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Initialize a message digest context.                                                       | PAL_SUCCESS |
+ * | 2 | Perform `pal_mdUpdate` on vector input data and check the status.                          | PAL_SUCCESS |
+ * | 3 | Get the output size using `pal_mdGetOutputSize` and check the result.                      | PAL_SUCCESS |
+ * | 4 | Get the digest result using `pal_mdFinal` and check its value.                             | PAL_SUCCESS |
+ * | 5 | Release message digest context.                                                            | PAL_SUCCESS |
+ * | 6 | Initialize a message digest context. with Big input buffer                                 | PAL_SUCCESS |
+ * | 7 | Perform `pal_mdUpdate` on vector input data and check the status.  with Big input buffer   | PAL_SUCCESS |
+ * | 8 | Get the output size using `pal_mdGetOutputSize` and check the result. with Big input buffer| PAL_SUCCESS |
+ * | 9 | Get the digest result using `pal_mdFinal` and check its value. with Big input buffer 		| PAL_SUCCESS |
+ * | 10 | Release message digest context. with Big input buffer                                     | PAL_SUCCESS |
+ */
+TEST(pal_crypto, md)
+{
+    palStatus_t result;
+    palMDHandle_t handle = NULLPTR;
+    size_t bufferSize = 0;
+    uint8_t output[32] = {0};
+
+    for (size_t i = 0; i < sizeof(sha256Vectors) / sizeof(palSha256Vector_t); ++i)
+    {
+    	memset(output, 0x0, sizeof(output));
+        /*#1*/
+        result = pal_mdInit(&handle, PAL_SHA256);
+        TEST_ASSERT_NOT_EQUAL(handle, NULLPTR);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+        /*#2*/
+        result = pal_mdUpdate(handle, sha256Vectors[i].input, sha256Vectors[i].inLenInBytes);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+        /*#3*/
+        result = pal_mdGetOutputSize(handle, &bufferSize);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        TEST_ASSERT_EQUAL_HEX(sha256Vectors[i].outLenInBytes, bufferSize);
+
+        /*#4*/
+        result = pal_mdFinal(handle, output);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        TEST_ASSERT_EQUAL_MEMORY(sha256Vectors[i].output, output, sizeof(sha256Vectors[i].output));
+
+        /*#5*/
+        result = pal_mdFree(&handle);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    }
+
+    memset(output, 0x0, sizeof(output));
+    /*#6*/
+    result = pal_mdInit(&handle, PAL_SHA256);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#7*/
+    result = pal_mdUpdate(handle, sha256Vectors_2nd.input, sha256Vectors_2nd.inLenInBytes);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#8*/
+    result = pal_mdGetOutputSize(handle, &bufferSize);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_HEX(sha256Vectors_2nd.outLenInBytes, bufferSize);
+
+    /*#9*/
+    result = pal_mdFinal(handle, output);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_MEMORY(sha256Vectors_2nd.output, output, sizeof(sha256Vectors_2nd.output));
+
+    /*#10*/
+    result = pal_mdFree(&handle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+}
+
+
+/**
+ * @brief Testing random number generation using deterministic random bit generators.
+ *
+ * The test generates a 128 bit number for 100 times and checks that there are no similar keys.
+ *
+ * Uses `ctr_drbg_buf` and `ctr_drbg_nonce_pers`.
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Initialize a CTR DRBG context.                                                          | PAL_SUCCESS |
+ * | 2 | Generate 100 128bit random values using `pal_CtrDRBGGenerate`.                          | PAL_SUCCESS |
+ * | 3 | Release message CTR DRBG context.                                                       | PAL_SUCCESS |
+ * | 4 | Check that all generated numbers are different.                                         | PAL_SUCCESS |
+ */
+TEST(pal_crypto, CTR_DRBG)
+{
+    palStatus_t result;
+    palCtrDrbgCtxHandle_t ctx = NULLPTR;
+
+    memset(ctr_drbg_buf, 0x0, sizeof(ctr_drbg_buf));
+
+    /*#1*/
+    result = pal_CtrDRBGInit(&ctx,ctr_drbg_nonce_pers, sizeof(ctr_drbg_nonce_pers));
+    TEST_ASSERT_NOT_EQUAL(ctx, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#2*/
+    for (int i = 0; i < 100; ++i) {
+        result = pal_CtrDRBGGenerate(ctx, ctr_drbg_buf[i], sizeof(ctr_drbg_buf[i]));
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    }
+
+    /*#3*/
+    result = pal_CtrDRBGFree(&ctx);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#4*/
+    for (int i = 0; i < 99; ++i) {
+        for (int j = i + 1; j < 100; ++j) {
+            TEST_ASSERT_NOT_EQUAL(0, memcmp(ctr_drbg_buf[i], ctr_drbg_buf[j], sizeof(ctr_drbg_buf[i])));
+        }
+    }
+}
+
+
+/**
+ * @brief Testing CMAC operation on a buffer with one operation.
+ *
+ * The test signs a buffer using CMAC and compares with the expected result buffer.
+ *
+ * Uses cmacSingleUseVector.
+ *
+ * For each vector:
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Perform CMAC using `pal_cipherCMAC` and check the result.                                    | PAL_SUCCESS |
+ * | 2 | Check the CMAC output against the test vector.                                               | PAL_SUCCESS |
+ */
+TEST(pal_crypto, CMAC_one_shot)
+{
+    palStatus_t result;
+    unsigned char output[16] = {0};
+
+    for (size_t i = 0; i < sizeof(cmacSingleUseVector) / sizeof(palAesCMACVector_t); ++i){
+        memset(output, 0x0, sizeof(output));
+        /*#1*/
+        result = pal_cipherCMAC(cmacSingleUseVector[i].key, 128, cmacSingleUseVector[i].in, cmacSingleUseVector[i].inLen, output);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#2*/
+        TEST_ASSERT_EQUAL_MEMORY(cmacSingleUseVector[i].out, output, sizeof(cmacSingleUseVector[i].out));
+    }
+}
+
+/**
+ * @brief Testing CMAC operation on a buffer with multiple operations and blocks.
+ *
+ * The test signs a buffer using CMAC multiple times and compares with the expected result buffer.
+ *
+ * Uses cmacIterativeUseVector.
+ *
+ * For each vector:
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Initialize CMAC context using `pal_CMACStart`.                                           | PAL_SUCCESS |
+ * | 2 | Add a block of data from test vector for CMAC processing using `pal_CMACFinish`.         | PAL_SUCCESS |
+ * | 3 | Add a block of data from test vector for CMAC processing using `pal_CMACFinish`.         | PAL_SUCCESS |
+ * | 4 | Add a block of data from test vector for CMAC processing using `pal_CMACFinish`.         | PAL_SUCCESS |
+ * | 5 | Add a block of data from test vector for CMAC processing using `pal_CMACFinish`.         | PAL_SUCCESS |
+ * | 6 | Get CMAC output using `pal_CMACFinish` and check the result.                             | PAL_SUCCESS |
+ */
+TEST(pal_crypto, CMAC_Iterative)
+{
+    palStatus_t result;
+    palCMACHandle_t ctx = NULLPTR;
+    unsigned char output[64] = {0};
+    size_t resultLen = 0;
+
+    for (size_t i = 0; i < sizeof(cmacIterativeUseVector) / sizeof(palCMACMultipleBlockVector_t); ++i)
+    {
+        memset(output, 0x0, sizeof(output));
+        /*#1*/
+        result = pal_CMACStart(&ctx,cmacIterativeUseVector[i].key_string, cmacIterativeUseVector[i].keybits, cmacIterativeUseVector[i].cipher_type);
+        TEST_ASSERT_NOT_EQUAL(ctx, NULLPTR);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#2*/
+        if (cmacIterativeUseVector[i].block1_len >= 0) {
+            result = pal_CMACUpdate(ctx, cmacIterativeUseVector[i].block1_string, cmacIterativeUseVector[i].block1_len);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        }
+        /*#3*/
+        if (cmacIterativeUseVector[i].block2_len >= 0) {
+            result = pal_CMACUpdate(ctx, cmacIterativeUseVector[i].block2_string, cmacIterativeUseVector[i].block2_len);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        }
+        /*#4*/
+        if (cmacIterativeUseVector[i].block3_len >= 0) {
+            result = pal_CMACUpdate(ctx, cmacIterativeUseVector[i].block3_string, cmacIterativeUseVector[i].block3_len);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        }
+        /*#5*/
+        if (cmacIterativeUseVector[i].block4_len >= 0) {
+            result = pal_CMACUpdate(ctx, cmacIterativeUseVector[i].block4_string, cmacIterativeUseVector[i].block4_len);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        }
+        /*#6*/
+        result = pal_CMACFinish(&ctx, output, &resultLen);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        TEST_ASSERT_EQUAL_HEX(cmacIterativeUseVector[i].block_size, resultLen);
+        TEST_ASSERT_EQUAL_MEMORY(cmacIterativeUseVector[i].expected_result_string, output, cmacIterativeUseVector[i].block_size);
+    } // for ends
+}
+
+/**
+ * @brief Testing HMAC operation on a buffer with one operation.
+ *
+ * The test signs a buffer using HMAC and compares with the expected result buffer.
+ *
+ * Uses mdHMACVector.
+ *
+ * For each vector:
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Perform one shot SHA256 HMAC on input vector using `pal_mdHmacSha256` and check the result. | PAL_SUCCESS |
+ */
+TEST(pal_crypto, HMAC_SHA256_one_shot)
+{
+    palStatus_t result;
+    unsigned char output[32] = {0};
+
+    for (size_t i = 0; i < sizeof(mdHMACVector) / sizeof(palMdHMACTestVector_t); ++i){
+        memset(output, 0x0, sizeof(output));
+        /*#1*/
+        result = pal_mdHmacSha256(mdHMACVector[i].key, mdHMACVector[i].keyLen, mdHMACVector[i].input,    mdHMACVector[i].inputLen, output, NULL);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        TEST_ASSERT_EQUAL_MEMORY(mdHMACVector[i].output, output, mdHMACVector[i].outputLen);
+    }
+}
+
+/**
+ * @brief Searching for ASN1 patterns in a DER certificate.
+ *
+ * The test extracts ASN1 tags from an existing DER format certificate and validates their types.
+ *
+ * Uses ASN1TestVector for coordinates and `asn1_data` as the dummy certificate buffer.
+ *
+ * For each vector:
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Get data for an ASN tag using `pal_ASN1GetTag`.                                              | PAL_SUCCESS |
+ * | 2 | Check if the result is success and the size tag size is correct.                             | PAL_SUCCESS |
+ */
+TEST(pal_crypto, ASN1)
+{
+    palStatus_t result;
+    size_t s = 0;
+    unsigned char* start = NULL;
+    const unsigned char* end = NULL;
+
+    for (size_t i = 0; i < sizeof(ASN1TestVector) / sizeof(palASN1TestVector_t); ++i) {
+        start = (unsigned char*)(asn1_data + ASN1TestVector[i].start);
+        end = asn1_data + ASN1TestVector[i].end;
+        /*#1*/
+        result = pal_ASN1GetTag(&start, end, &s, ASN1TestVector[i].type);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#2*/
+        TEST_ASSERT_EQUAL(ASN1TestVector[i].dataLen, s);
+    }
+}
+
+/**
+ * @brief Test the parsing of a dummy X509 certificate.
+ *
+ * uses x509_cert
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Initialize the X509 ceritifcate context using `pal_x509Initiate`.                            | PAL_SUCCESS |
+ * | 2 | Parse a valid x509 certificate using `pal_x509CertParse`.                                    | PAL_SUCCESS |
+ * | 3 | Parse an invalid x509 certificate using `pal_x509CertParse`.                                 | PAL_ERR_CERT_PARSING_FAILED |
+ * | 4 | Parse an invalid x509 certificate using `pal_x509CertParse`.                                 | PAL_ERR_INVALID_MD_TYPE |
+ * | 5 | Parse an invalid x509 certificate using `pal_x509CertParse`.                                 | PAL_ERR_NOT_SUPPORTED_CURVE |
+ * | 6 | Release x509 certificate context.                                                            | PAL_SUCCESS |
+ */
+TEST(pal_crypto, X509_Parse)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t result;
+    palX509Handle_t ctx = NULLPTR;
+    /*#1*/
+    result = pal_x509Initiate(&ctx);
+    TEST_ASSERT_NOT_EQUAL(ctx, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    /*#2*/
+    result = pal_x509CertParse(ctx, x509_TI, sizeof(x509_TI));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    /*#3*/
+    result = pal_x509CertParse(ctx, x509_TI_PEM, sizeof(x509_TI_PEM));
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_CERT_PARSING_FAILED, result);
+    /*#4*/
+    result = pal_x509CertParse(ctx, (unsigned char*)testdata_x509_Sha512, sizeof(testdata_x509_Sha512));
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_MD_TYPE, result);
+    /*#5*/
+    result = pal_x509CertParse(ctx, (unsigned char*)testdata_x509_Curve512r1, sizeof(testdata_x509_Curve512r1));
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_NOT_SUPPORTED_CURVE, result);
+    /*#6*/
+    result = pal_x509Free(&ctx);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+#endif
+}
+
+/**
+ * @brief Test the reading of specific attributes in an X509 certificate.
+ *
+ * The test parses a X509 certificate and extracts specific attributes and compare them against the expected result.
+ *
+ * Uses `x509_cert` and `cert_not_self_signed`.
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Initialize the X509 ceritifcate context using `pal_x509Initiate`.                            | PAL_SUCCESS |
+ * | 2 | Parse a valid x509 certificate using `pal_x509CertParse`.                                    | PAL_SUCCESS |
+ * | 3 | Get the certificate attribute value using `pal_x509CertGetAttribute` and check it.           | PAL_SUCCESS |
+ * | 4 | Get the certificate attribute value using `pal_x509CertGetAttribute` and check it.           | PAL_SUCCESS |
+ * | 5 | Get the certificate attribute value using `pal_x509CertGetAttribute` and check it.           | PAL_SUCCESS |
+ * | 6 | Get the certificate attribute value using `pal_x509CertGetAttribute` and check it.           | PAL_SUCCESS |
+ * | 7 | Get the certificate attribute value using `pal_x509CertGetAttribute` and check it.           | PAL_SUCCESS |
+ * | 8 | Get the certificate attribute value using `pal_x509CertGetAttribute` and check it.           | PAL_SUCCESS |
+ * | 9 | Get the certificate attribute value using `pal_x509CertGetAttribute` and check it.           | PAL_SUCCESS |
+ * | 10 | Release x509 certificate context using `pal_x509Free`.                                       | PAL_SUCCESS |
+ * | 11 | Initialize X509 ceritifcate context using `pal_x509Initiate`.                                | PAL_SUCCESS |
+ * | 12 | Parse a valid x509 certificate using `pal_x509CertParse`.                                   | PAL_SUCCESS |
+ * | 13 | Get the certificate attribute value using `pal_x509CertGetAttribute` and check it.          | PAL_SUCCESS |
+ * | 14 | Get the certificate attribute value using `pal_x509CertGetAttribute` and check it.          | PAL_SUCCESS |
+ * | 15 | Get the certificate attribute value using `pal_x509CertGetAttribute `and check it.          | PAL_SUCCESS |
+ * | 16 | Get the certificate attribute value using `pal_x509CertGetAttribute` and check it.          | PAL_SUCCESS |
+ * | 17 | Get the certificate attribute value using `pal_x509CertGetAttribute` and check it.          | PAL_SUCCESS |
+ * | 18 | Get the certificate attribute value with a too small buffer.                                | PAL_ERR_BUFFER_TOO_SMALL |
+ * | 19 | Get the certificate attribute value using `pal_x509CertGetAttribute` and check it.          | PAL_SUCCESS |
+ * | 20 | Release x509 certificate context using `pal_x509Free`.                                      | PAL_SUCCESS |
+ */
+TEST(pal_crypto, X509_ReadAttributes)
+{
+
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t result;
+    palX509Handle_t ctx = NULLPTR;
+    char buffer1[512] = {0};
+    char validationBuf[12] = {0};
+    uint8_t certID1[PAL_CERT_ID_SIZE] = {0};
+    uint8_t certID2[PAL_CERT_ID_SIZE] = {0};
+    time_t validFrom = 0;
+    time_t validTo = 0;
+    time_t tmpTime;
+    size_t actualOutLen = 0;
+
+    /*#1*/
+    result = pal_x509Initiate(&ctx);
+    TEST_ASSERT_NOT_EQUAL(ctx, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    /*#2*/
+    result = pal_x509CertParse(ctx, x509_TI, sizeof(x509_TI));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    /*#3*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_ISSUER_ATTR, buffer1, sizeof(buffer1), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    memset(buffer1, 0, sizeof(buffer1));
+    /*#4*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_SUBJECT_ATTR, buffer1, sizeof(buffer1), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    memset(buffer1, 0, sizeof(buffer1));
+    /*#5*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_VALID_FROM, validationBuf, sizeof(validationBuf), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    memcpy(&tmpTime, validationBuf, sizeof(tmpTime));
+    memset(validationBuf, 0, sizeof(validationBuf));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    /*#6*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_CN_ATTR, buffer1, sizeof(buffer1), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_STRING("IOT_PAL", buffer1);
+    memset(buffer1, 0, sizeof(buffer1));
+    /*#7*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_L_ATTR, buffer1, sizeof(buffer1), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    memset(buffer1, 0, sizeof(buffer1));
+    /*#8*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_OU_ATTR, buffer1, sizeof(buffer1), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_STRING("IOTBU", buffer1);
+    memset(buffer1, 0, sizeof(buffer1));
+    /*#9*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_CERT_ID_ATTR, certID1, sizeof(certID1), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_CERT_ID_ATTR, certID2, sizeof(certID2), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_MEMORY(certID1, certID2, sizeof(certID1));
+    memset(certID1, 0, sizeof(certID1));
+    memset(certID2, 0, sizeof(certID2));
+    /*#10*/
+    result = pal_x509Free(&ctx);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#11*/
+    result = pal_x509Initiate(&ctx);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    /*#12*/
+    result = pal_x509CertParse(ctx, cert_not_self_signed, sizeof(cert_not_self_signed));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    /*#13*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_ISSUER_ATTR, buffer1, sizeof(buffer1), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    memset(buffer1, 0, sizeof(buffer1));
+    /*#14*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_SUBJECT_ATTR, buffer1, sizeof(buffer1), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    memset(buffer1, 0, sizeof(buffer1));
+    /*#15*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_CN_ATTR, buffer1, sizeof(buffer1), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_STRING("IOT_TEST", buffer1);
+    memset(buffer1, 0, sizeof(buffer1));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    /*#16*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_VALID_FROM, validationBuf, sizeof(validationBuf), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    memcpy(&validFrom, validationBuf, sizeof(tmpTime));
+    memset(validationBuf, 0, sizeof(validationBuf));
+    /*#17*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_VALID_TO, validationBuf, sizeof(validationBuf), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    memcpy(&validTo, validationBuf, sizeof(tmpTime));
+    memset(validationBuf, 0, sizeof(validationBuf));
+    
+    //Check exact time period
+    TEST_ASSERT_EQUAL_HEX(0x05a39a7f, validTo - validFrom);
+    /*#18*/
+    //! sending small buffer size to check error value scenario
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_VALID_TO, validationBuf, 1, &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_BUFFER_TOO_SMALL, result);
+    TEST_ASSERT_EQUAL(sizeof(uint64_t), actualOutLen);
+    /*#19*/
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_CERT_ID_ATTR, certID1, sizeof(certID1), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    result = pal_x509CertGetAttribute(ctx, PAL_X509_CERT_ID_ATTR, certID2, sizeof(certID2), &actualOutLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_MEMORY(certID1, certID2, sizeof(certID1));
+    memset(certID1, 0, sizeof(certID1));
+    memset(certID2, 0, sizeof(certID2));
+
+    /*#20*/
+    result = pal_x509Free(&ctx);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+#endif
+}
+    
+/**
+ * @brief Test the validity of a X509 certificate.
+ *
+ * Reads a X509 certificate, specific attributes such as `PAL_X509_VALID_FROM` and `PAL_X509_VALID_TO`
+ * and validates with `pal_x509CertVerify`.
+ *
+ * Uses `x509_verify_data`.
+ *
+ For each test vector:
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | If the CA cert is part of vector, initialize X509 certificate context using `pal_x509Initiate`. | PAL_SUCCESS |
+ * | 2 | If the CA cert is part of vector, parse a valid x509 certificate using `pal_x509CertParse`.     | PAL_SUCCESS |
+ * | 3 | Initialize X509 certificate context using `pal_x509Initiate`.                                   | PAL_SUCCESS |
+ * | 4 | Parse a valid x509 certificate using `pal_x509CertParse`.                                       | PAL_SUCCESS |
+ * | 5 | Verify the certificate using `pal_x509CertVerify`.                                              | PAL_SUCCESS |
+ * | 6 | Release X509 certificate context.                                                               | PAL_SUCCESS |
+ * | 7 | If the CA cert is part of vector, release X509 certificate context.                             | PAL_SUCCESS |
+ */
+TEST(pal_crypto, X509_Verify)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t result = PAL_SUCCESS;
+    palX509Handle_t cert = NULLPTR;
+    palX509Handle_t caCert = NULLPTR;
+    int32_t verifyResult = 0;
+
+    for (size_t i = 0; i < sizeof(x509_verify_data) / sizeof(palX509VertifyTestVector_t); ++i) 
+    {
+        if (x509_verify_data[i].ca != NULL)
+        {
+            /*#1*/
+            result = pal_x509Initiate(&caCert);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+            TEST_ASSERT_NOT_EQUAL(caCert, NULLPTR);
+            /*#2*/
+            result = pal_x509CertParse(caCert, x509_verify_data[i].ca, x509_verify_data[i].ca_size);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        }
+
+        /*#3*/
+        result = pal_x509Initiate(&cert);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#4*/
+        result = pal_x509CertParse(cert, x509_verify_data[i].crt, x509_verify_data[i].crt_size);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#5*/
+        result = pal_x509CertVerifyExtended(cert, caCert, &verifyResult);
+        if (PAL_ERR_X509_CERT_VERIFY_FAILED == result)
+        {
+            TEST_ASSERT_TRUE((x509_verify_data[i].result & verifyResult));
+        }
+        else
+        {
+            TEST_ASSERT_EQUAL_HEX(x509_verify_data[i].result, result);   
+        }
+        /*#6*/
+        result = pal_x509Free(&cert);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        if (x509_verify_data[i].ca != NULL)
+        {
+            /*#7*/
+            result = pal_x509Free(&caCert);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        }
+    }
+#endif
+}
+
+/**
+ * @brief Test the parsing of elliptic-curves keys (public and private).
+ *
+ * Uses `parse_ec_key_data`.
+ *
+ * For each test vector:
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Initialize a new ECC key using `pal_ECKeyNew`.                                                                      | PAL_SUCCESS |
+ * | 2 | If private key, parse using `pal_parseECPrivateKeyFromDER`, otherwise parse using `pal_parseECPublicKeyFromDER`.    | PAL_SUCCESS |
+ * | 3 | Check the parsing status according to the test vector.                                                              | PAL_SUCCESS |
+ * | 4 | Release the ECC key using `pal_ECKeyFree`.                                                                          | PAL_SUCCESS |
+ */
+TEST(pal_crypto, ECKey_parseKey)
+{
+    palStatus_t result;
+    palECKeyHandle_t handle = NULLPTR;
+
+    for (uint32_t i = 0; i < sizeof(parse_ec_key_data) / sizeof(palParseECKeyTestVector_t) ; ++i) {
+        /*#1*/
+        result = pal_ECKeyNew(&handle);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#2*/
+        switch (parse_ec_key_data[i].type) {
+            case PAL_CHECK_PRIVATE_KEY:
+                result = pal_parseECPrivateKeyFromDER(parse_ec_key_data[i].key, parse_ec_key_data[i].len, handle);
+                break;
+            case PAL_CHECK_PUBLIC_KEY:
+                result = pal_parseECPublicKeyFromDER(parse_ec_key_data[i].key, parse_ec_key_data[i].len, handle);
+                break;
+            default:
+                TEST_FAIL();
+        }
+        /*#3*/
+        if (parse_ec_key_data[i].shouldSucceed)
+        {
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        }
+        else
+        {
+            TEST_ASSERT_NOT_EQUAL(PAL_SUCCESS, result);
+        }
+        /*#4*/
+        result = pal_ECKeyFree(&handle);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    }
+}
+
+/**
+ * @brief Test the validity of elliptic-curves keys (public and private).
+ *
+ * Uses `check_ec_key_data`.
+ *
+ * For each test vector:
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Initialize and load EC curve using `pal_ECGroupInitAndLoad`.                                                         | PAL_SUCCESS |
+ * | 2 | Initialize a new ECC key using `pal_ECKeyNew`.                                                                       | PAL_SUCCESS |
+ * | 3 | If private key, parse using `pal_parseECPrivateKeyFromDER` and check the parsing status according to the test vector.| PAL_SUCCESS |
+ * | 4 | If successfully parsed, check the key using `pal_ECCheckKey`.                                                        | PAL_SUCCESS |
+ * | 5 | Release the ECC key using `pal_ECKeyFree`.                                                                           | PAL_SUCCESS |
+ * | 6 | Initialize a new ECC key using `pal_ECKeyNew`.                                                                       | PAL_SUCCESS |
+ * | 7 | If public key, parse using `pal_parseECPublicKeyFromDER` and check the parsing status according to test the vector.  | PAL_SUCCESS |
+ * | 8 | If successfully parsed, check the key using `pal_ECCheckKey`.                                                        | PAL_SUCCESS |
+ * | 9 | Release the ECC key using `pal_ECKeyFree`.                                                                           | PAL_SUCCESS |
+ * | 10 | Release the EC curve using `pal_ECGroupFree`.                                                                       | PAL_SUCCESS |
+ */
+TEST(pal_crypto, ECKey_checkKey)
+{
+    palStatus_t result;
+    palCurveHandle_t grp = NULLPTR;
+    bool verified = false;
+    palECKeyHandle_t key = NULLPTR;
+
+    for (uint32_t i = 0; i < sizeof(check_ec_key_data) / sizeof(palCheckEcKeyTestVector_t); ++i)
+    {
+        /*#1*/
+        result = pal_ECGroupInitAndLoad(&grp, check_ec_key_data[i].index);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#2*/
+        result = pal_ECKeyNew(&key);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#3*/
+        result = pal_parseECPrivateKeyFromDER(check_ec_key_data[i].key, check_ec_key_data[i].keyLen, key);
+        TEST_ASSERT_EQUAL_HEX(check_ec_key_data[i].parsePrvRes, result);
+        if (PAL_SUCCESS == result)
+        {
+            /*#4*/
+            result = pal_ECCheckKey(grp, key, PAL_CHECK_PRIVATE_KEY, &verified);
+            TEST_ASSERT_EQUAL(check_ec_key_data[i].checkPrvRes, result);
+            TEST_ASSERT_EQUAL(check_ec_key_data[i].verifed, verified);
+        }
+
+        /*#5*/
+        result = pal_ECKeyFree(&key);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#6*/
+        result = pal_ECKeyNew(&key);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#7*/
+        result = pal_parseECPublicKeyFromDER(check_ec_key_data[i].key, check_ec_key_data[i].keyLen, key);
+        TEST_ASSERT_EQUAL_HEX(check_ec_key_data[i].parsePubRes, result);
+        if (PAL_SUCCESS == result)
+        {
+            /*#8*/
+            result = pal_ECCheckKey(grp, key, PAL_CHECK_PUBLIC_KEY, &verified);
+            TEST_ASSERT_EQUAL(check_ec_key_data[i].checkPubRes, result);
+            TEST_ASSERT_EQUAL(check_ec_key_data[i].verifed, verified);
+        }
+        /*#9*/
+        result = pal_ECKeyFree(&key);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#10*/
+        result = pal_ECGroupFree(&grp);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    }
+}
+
+/**
+ * @brief Create a CSR from an elliptic-curve key and assure its validity.
+ *
+ * Uses CsrTests.
+ *
+ * For each test vector (steps 1A-1O are run for each tect vector):
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Initialize and load the EC curve using `pal_ECGroupInitAndLoad`.                                                     | PAL_SUCCESS |
+ * | 1A | Initialize a new ECC key using `pal_ECKeyNew`.                                                                      | PAL_SUCCESS |
+ * | 1B | Parse using `pal_parseECPrivateKeyFromDER` and check the parsing status according to the test vector.               | PAL_SUCCESS |
+ * | 1C | Check the key using `pal_ECCheckKey`.                                                                               | PAL_SUCCESS |
+ * | 1D | Initialize a new ECC key using `pal_ECKeyNew`.                                                                      | PAL_SUCCESS |
+ * | 1E | Parse using `pal_parseECPublicKeyFromDER` and check the parsing status according to the test vector.                | PAL_SUCCESS |
+ * | 1F | Check the key using `pal_ECCheckKey`.                                                                               | PAL_SUCCESS |
+ * | 1G | Initialize the x509 certificate context using `pal_x509CSRInit`.                                                    | PAL_SUCCESS |
+ * | 1H  | Set the cert subject using `pal_x509CSRSetSubject`.                                                                | PAL_SUCCESS |
+ * | 1I  | Set the cert MD using `pal_x509CSRSetMD`.                                                                          | PAL_SUCCESS |
+ * | 1J  | Set the cert keys using `pal_x509CSRSetKey`.                                                                       | PAL_SUCCESS |
+ * | 1K  | Set the cert key usage using `pal_x509CSRSetKey`.                                                                  | PAL_SUCCESS |
+ * | 1L  | Write the certificate to DER file using `pal_x509CSRWriteDER`.                                                     | PAL_SUCCESS |
+ * | 1M  | Release the x509 ceritifcate context using `pal_x509CSRFree`.                                                      | PAL_SUCCESS |
+ * | 1N  | Release the ECC key using `pal_ECKeyFree`.                                                                         | PAL_SUCCESS |
+ * | 1O  | Release the ECC key using `pal_ECKeyFree`.                                                                         | PAL_SUCCESS |
+ * | 2 | Release the EC curve using `pal_ECGroupFree`.                                                                        | PAL_SUCCESS |
+ */
+TEST(pal_crypto, CSR)
+{
+
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t result;
+    palECKeyHandle_t prvKeyHandle = NULLPTR, pubKeyHandle = NULLPTR;
+    unsigned char outDer[1000] = {0};
+    size_t reqLen;
+    palx509CSRHandle_t CSRHandle = NULLPTR;
+
+    bool goodKey = false;
+    palCurveHandle_t grp = NULLPTR;
+    palGroupIndex_t index = PAL_ECP_DP_SECP256R1;
+    /*#1*/
+    result = pal_ECGroupInitAndLoad(&grp, index);
+    TEST_ASSERT_NOT_EQUAL(grp, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    for (uint32_t i = 0; i < sizeof(CsrTests) / sizeof(palX509CSRTestVector_t); ++i)
+    {
+        memset(outDer,0, sizeof(outDer));
+
+        goodKey = false;
+        /*#1A*/
+        result = pal_ECKeyNew(&prvKeyHandle);
+        TEST_ASSERT_NOT_EQUAL(prvKeyHandle, NULLPTR);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#1B*/
+        result = pal_parseECPrivateKeyFromDER(CsrTests[i].prvkey, CsrTests[i].prvkeyLen, prvKeyHandle);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#1C*/
+        result = pal_ECCheckKey(grp, prvKeyHandle, PAL_CHECK_PRIVATE_KEY, &goodKey);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        TEST_ASSERT_EQUAL(true, goodKey);
+
+        goodKey = false;
+        /*#1D*/
+        result = pal_ECKeyNew(&pubKeyHandle);
+        TEST_ASSERT_NOT_EQUAL(pubKeyHandle, NULLPTR);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#1E*/
+        result = pal_parseECPublicKeyFromDER(CsrTests[i].pubkey, CsrTests[i].pubkeyLen, pubKeyHandle);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#1F*/
+        result = pal_ECCheckKey(grp, pubKeyHandle, PAL_CHECK_PUBLIC_KEY, &goodKey);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        TEST_ASSERT_EQUAL(true, goodKey);
+        /*#1G*/
+        result = pal_x509CSRInit(&CSRHandle);
+        TEST_ASSERT_NOT_EQUAL(CSRHandle, NULLPTR);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#1H*/
+        result = pal_x509CSRSetSubject(CSRHandle, CsrTests[i].subject_name);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#1I*/
+        result = pal_x509CSRSetMD(CSRHandle, CsrTests[i].mdType);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#1J*/
+        result = pal_x509CSRSetKey(CSRHandle, pubKeyHandle, prvKeyHandle);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#1K*/
+        result = pal_x509CSRSetKeyUsage(CSRHandle, CsrTests[i].keyUsage);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#1L*/
+        //pal_x509CSRSetExtension - need input from provisioning
+        reqLen = 0;
+        result = pal_x509CSRWriteDER(CSRHandle, outDer, sizeof(outDer), &reqLen);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+        TEST_ASSERT_EQUAL(CsrTests[i].derOutLen, reqLen);
+        TEST_ASSERT_EQUAL_MEMORY(CsrTests[i].derOut, outDer, reqLen);
+        /*#1M*/
+        result = pal_x509CSRFree(&CSRHandle);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#1N*/
+        result = pal_ECKeyFree(&prvKeyHandle);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#1O*/
+        result = pal_ECKeyFree(&pubKeyHandle);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    }
+    /*#2*/
+    result = pal_ECGroupFree(&grp);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+#endif
+}
+
+#define PAL_CRYPTO_TEST_MAX_ECDSA_LEN 74
+
+/**
+* @brief Test hash function of the TBS of an X509 and its verification
+*
+* Uses `x509_verify_ca` and `x509_verify_cert`.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Instantiate X509 handles using `pal_x509Initiate`.                                                                   | PAL_SUCCESS |
+* | 2 | Parse signer and signee X509 certificates into handles using `pal_x509CertParse`.                                    | PAL_SUCCESS |
+* | 3 | Hash the TBS of the signee using `pal_x509CertGetHTBS`.                                                              | PAL_SUCCESS |
+* | 4 | Acquire the signature from the signee using `pal_x509CertGetAttribute` with PAL_X509_SIGNATUR_ATTR flag.             | PAL_SUCCESS |
+* | 5 | Verify the hash signed by the CA in the signature of signee equals the hash of the TBS using `pal_verifySignature`.  | PAL_SUCCESS |
+* | 6 | Verify the signature with the public key of the signee instead of the signer, using `pal_verifySignature` and fail.  | PAL_ERR_PK_SIG_VERIFY_FAILED |
+* | 7 | Release the two X509 handles using `pal_x509Free`.                                                                   | PAL_SUCCESS |
+*/
+TEST(pal_crypto, X509_tbs_hash)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status;
+    unsigned char digest[PAL_SHA256_SIZE] = { 0 };
+    unsigned char sig[PAL_CRYPTO_TEST_MAX_ECDSA_LEN] = { 0 };
+    size_t sig_len;
+    size_t digest_len;
+    palX509Handle_t signee = NULLPTR;
+    palX509Handle_t signer = NULLPTR;
+
+    /*#1*/
+    status = pal_x509Initiate(&signee);
+    TEST_ASSERT_NOT_EQUAL(signee, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    status = pal_x509Initiate(&signer);
+    TEST_ASSERT_NOT_EQUAL(signer, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#2*/
+    status = pal_x509CertParse(signee, x509_verify_cert, sizeof(x509_verify_cert));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    status = pal_x509CertParse(signer, x509_verify_ca, sizeof(x509_verify_ca));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#3*/
+#ifdef DEBUG
+    // Check invalid arguments
+    status = pal_x509CertGetHTBS(NULLPTR, PAL_SHA256, digest, sizeof(digest), &digest_len);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_x509CertGetHTBS(signee, PAL_SHA256, NULL, sizeof(digest), &digest_len);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_x509CertGetHTBS(signee, PAL_SHA256, digest, sizeof(digest), NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+#endif
+    // Check with small buffer
+    status = pal_x509CertGetHTBS(signee, PAL_SHA256, digest, sizeof(digest) - 1, &digest_len);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_BUFFER_TOO_SMALL, status);
+
+    status = pal_x509CertGetHTBS(signee, PAL_SHA256, digest, sizeof(digest), &digest_len);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL_HEX(PAL_SHA256_SIZE, digest_len);
+    
+    /*#4*/
+    status = pal_x509CertGetAttribute(signee, PAL_X509_SIGNATUR_ATTR, sig, sizeof(sig), &sig_len);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#5*/
+    status = pal_verifySignature(signer, PAL_SHA256, digest, digest_len, sig, sig_len);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#6*/
+    status = pal_verifySignature(signee, PAL_SHA256, digest, PAL_SHA256_SIZE, sig, sig_len);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_PK_SIG_VERIFY_FAILED, status);
+
+    /*#7*/
+    status = pal_x509Free(&signee);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_x509Free(&signer);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+#endif
+}
+
+/**
+* @brief Test the generation of elliptic-curves keys (public and private).
+*
+* Uses `pal_ECKeyGenerateKey`.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize a new EC key using `pal_ECKeyNew`.                                                                      | PAL_SUCCESS |
+* | 2 | Generate EC keys using `pal_ECKeyGenerateKey`.                                                                     | PAL_SUCCESS |
+* | 3 | Initialize and load EC group using `pal_ECGroupInitAndLoad`.                                                       | PAL_SUCCESS |
+* | 4 | Check both generated keys using `pal_ECCheckKey`.                                                                  | PAL_SUCCESS |
+* | 5 | Compute signature for digest with private key using `pal_ECDSASign`.                                               | PAL_SUCCESS |
+* | 6 | Verify signature with public key using `pal_ECDSAVerify`.                                                          | PAL_SUCCESS |
+* | 7 | Release the EC group using `pal_ECGroupFree`.                                                                      | PAL_SUCCESS |
+* | 8 | Release the EC key using `pal_ECKeyFree`.                                                                          | PAL_SUCCESS |
+*/
+TEST(pal_crypto, ECKey_GenerateKeys)
+{
+    palStatus_t result;
+    palECKeyHandle_t key_handle = NULLPTR;
+    palGroupIndex_t grpID = PAL_ECP_DP_SECP256R1;
+    palCurveHandle_t grp_handle = NULLPTR;
+    bool verified = false;
+    unsigned char hash_digest[] =
+    { 0x34, 0x70, 0xCD, 0x54, 0x7B, 0x0A, 0x11, 0x5F, 0xE0, 0x5C, 0xEB, 0xBC, 0x07, 0xBA, 0x91, 0x88,
+        0x27, 0x20, 0x25, 0x6B, 0xB2, 0x7A, 0x66, 0x89, 0x1A, 0x4B, 0xB7, 0x17, 0x11, 0x04, 0x86, 0x6F };
+    unsigned char signature[74] = { 0 };
+    size_t act_size_of_sign = sizeof(signature);
+
+    /*#1*/
+    result = pal_ECKeyNew(&key_handle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#2*/
+    result = pal_ECKeyGenerateKey(grpID, key_handle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#3*/
+    result = pal_ECGroupInitAndLoad(&grp_handle, grpID);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#4*/
+    result = pal_ECCheckKey(grp_handle,key_handle, PAL_CHECK_BOTH_KEYS,&verified);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_HEX(true, verified);
+
+    /*#5*/
+    result = pal_ECDSASign(grp_handle, PAL_SHA256, key_handle, hash_digest, sizeof(hash_digest), signature, &act_size_of_sign);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#6*/
+    verified = false;
+    result = pal_ECDSAVerify(key_handle, hash_digest, sizeof(hash_digest), signature, act_size_of_sign, &verified);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_HEX(true, verified);
+
+    /*#7*/
+    result = pal_ECGroupFree(&grp_handle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#8*/
+    result = pal_ECKeyFree(&key_handle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Crypto/pal_crypto_test_data.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1308 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal.h"
+
+
+typedef struct palAesTestVector{
+	unsigned char key[16];
+	unsigned char nonce[16];
+	unsigned char input[16];
+	unsigned char output[16];
+} palAesTestVector_t;
+
+const palAesTestVector_t CtrVector =
+{
+		{
+				0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+				0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E
+		},
+		{
+				0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+		},
+		{
+				0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+				0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67
+		},
+		{
+				0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,
+				0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8
+		}
+};
+
+const palAesTestVector_t EcbVector =
+{
+		{
+				0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
+				0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E
+		},
+		{
+				0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
+		},
+		{
+				0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
+				0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67
+		},
+		{
+				0x61, 0x5f, 0x09, 0xfb, 0x35, 0x3f, 0x61, 0x3b,
+				0xa2, 0x8f, 0xf3, 0xa3, 0x0c, 0x64, 0x75, 0x2d
+		}
+};
+
+
+
+typedef struct palSha256Vector_2nd{
+	size_t inLenInBytes;
+	size_t outLenInBytes;
+	unsigned char output[32];
+	unsigned char input[1000];
+} palSha256Vector_2nd_t;
+
+palSha256Vector_2nd_t sha256Vectors_2nd ={
+		955,
+		32,
+		{
+				0x41, 0x09, 0xcd, 0xbe, 0xc3, 0x24, 0x0a, 0xd7, 0x4c, 0xc6,0xc3, 0x7f, 0x39, 0x30, 0x0f, 0x70,
+				0xfe, 0xde, 0x16, 0xe2, 0x1e, 0xfc, 0x77, 0xf7, 0x86, 0x59,0x98, 0x71, 0x4a, 0xad, 0x0b, 0x5e
+		},
+		{
+				0x83, 0x90, 0xcf, 0x0b, 0xe0, 0x76, 0x61, 0xcc, 0x76, 0x69, 0xaa, 0xc5, 0x4c, 0xe0, 0x9a, 0x37,
+				0x73, 0x3a, 0x62, 0x9d, 0x45, 0xf5, 0xd9, 0x83, 0xef, 0x20, 0x1f, 0x9b, 0x2d, 0x13, 0x80, 0x0e,
+				0x55, 0x5d, 0x9b, 0x10, 0x97, 0xfe, 0xc3, 0xb7, 0x83, 0xd7, 0xa5, 0x0d, 0xcb, 0x5e, 0x2b, 0x64,
+				0x4b, 0x96, 0xa1, 0xe9, 0x46, 0x3f, 0x17, 0x7c, 0xf3, 0x49, 0x06, 0xbf, 0x38, 0x8f, 0x36, 0x6d,
+				0xb5, 0xc2, 0xde, 0xee, 0x04, 0xa3, 0x0e, 0x28, 0x3f, 0x76, 0x4a, 0x97, 0xc3, 0xb3, 0x77, 0xa0,
+				0x34, 0xfe, 0xfc, 0x22, 0xc2, 0x59, 0x21, 0x4f, 0xaa, 0x99, 0xba, 0xba, 0xff, 0x16, 0x0a, 0xb0,
+				0xaa, 0xa7, 0xe2, 0xcc, 0xb0, 0xce, 0x09, 0xc6, 0xb3, 0x2f, 0xe0, 0x8c, 0xbc, 0x47, 0x46, 0x94,
+				0x37, 0x5a, 0xba, 0x70, 0x3f, 0xad, 0xbf, 0xa3, 0x1c, 0xf6, 0x85, 0xb3, 0x0a, 0x11, 0xc5, 0x7f,
+				0x3c, 0xf4, 0xed, 0xd3, 0x21, 0xe5, 0x7d, 0x3a, 0xe6, 0xeb, 0xb1, 0x13, 0x3c, 0x82, 0x60, 0xe7,
+				0x5b, 0x92, 0x24, 0xfa, 0x47, 0xa2, 0xbb, 0x20, 0x52, 0x49, 0xad, 0xd2, 0xe2, 0xe6, 0x2f, 0x81,
+				0x74, 0x91, 0x48, 0x2a, 0xe1, 0x52, 0x32, 0x2b, 0xe0, 0x90, 0x03, 0x55, 0xcd, 0xcc, 0x8d, 0x42,
+				0xa9, 0x8f, 0x82, 0xe9, 0x61, 0xa0, 0xdc, 0x6f, 0x53, 0x7b, 0x7b, 0x41, 0x0e, 0xff, 0x10, 0x5f,
+				0x59, 0x67, 0x3b, 0xfb, 0x78, 0x7b, 0xf0, 0x42, 0xaa, 0x07, 0x1f, 0x7a, 0xf6, 0x8d, 0x94, 0x4d,
+				0x27, 0x37, 0x1c, 0x64, 0x16, 0x0f, 0xe9, 0x38, 0x27, 0x72, 0x37, 0x25, 0x16, 0xc2, 0x30, 0xc1,
+				0xf4, 0x5c, 0x0d, 0x6b, 0x6c, 0xca, 0x7f, 0x27, 0x4b, 0x39, 0x4d, 0xa9, 0x40, 0x2d, 0x3e, 0xaf,
+				0xdf, 0x73, 0x39, 0x94, 0xec, 0x58, 0xab, 0x22, 0xd7, 0x18, 0x29, 0xa9, 0x83, 0x99, 0x57, 0x4d,
+				0x4b, 0x59, 0x08, 0xa4, 0x47, 0xa5, 0xa6, 0x81, 0xcb, 0x0d, 0xd5, 0x0a, 0x31, 0x14, 0x53, 0x11,
+				0xd9, 0x2c, 0x22, 0xa1, 0x6d, 0xe1, 0xea, 0xd6, 0x6a, 0x54, 0x99, 0xf2, 0xdc, 0xeb, 0x4c, 0xae,
+				0x69, 0x47, 0x72, 0xce, 0x90, 0x76, 0x2e, 0xf8, 0x33, 0x6a, 0xfe, 0xc6, 0x53, 0xaa, 0x9b, 0x1a,
+				0x1c, 0x48, 0x20, 0xb2, 0x21, 0x13, 0x6d, 0xfc, 0xe8, 0x0d, 0xce, 0x2b, 0xa9, 0x20, 0xd8, 0x8a,
+				0x53, 0x0c, 0x94, 0x10, 0xd0, 0xa4, 0xe0, 0x35, 0x8a, 0x3a, 0x11, 0x05, 0x2e, 0x58, 0xdd, 0x73,
+				0xb0, 0xb1, 0x79, 0xef, 0x8f, 0x56, 0xfe, 0x3b, 0x5a, 0x2d, 0x11, 0x7a, 0x73, 0xa0, 0xc3, 0x8a,
+				0x13, 0x92, 0xb6, 0x93, 0x8e, 0x97, 0x82, 0xe0, 0xd8, 0x64, 0x56, 0xee, 0x48, 0x84, 0xe3, 0xc3,
+				0x9d, 0x4d, 0x75, 0x81, 0x3f, 0x13, 0x63, 0x3b, 0xc7, 0x9b, 0xaa, 0x07, 0xc0, 0xd2, 0xd5, 0x55,
+				0xaf, 0xbf, 0x20, 0x7f, 0x52, 0xb7, 0xdc, 0xa1, 0x26, 0xd0, 0x15, 0xaa, 0x2b, 0x98, 0x73, 0xb3,
+				0xeb, 0x06, 0x5e, 0x90, 0xb9, 0xb0, 0x65, 0xa5, 0x37, 0x3f, 0xe1, 0xfb, 0x1b, 0x20, 0xd5, 0x94,
+				0x32, 0x7d, 0x19, 0xfb, 0xa5, 0x6c, 0xb8, 0x1e, 0x7b, 0x66, 0x96, 0x60, 0x5f, 0xfa, 0x56, 0xeb,
+				0xa3, 0xc2, 0x7a, 0x43, 0x86, 0x97, 0xcc, 0x21, 0xb2, 0x01, 0xfd, 0x7e, 0x09, 0xf1, 0x8d, 0xee,
+				0xa1, 0xb3, 0xea, 0x2f, 0x0d, 0x1e, 0xdc, 0x02, 0xdf, 0x0e, 0x20, 0x39, 0x6a, 0x14, 0x54, 0x12,
+				0xcd, 0x6b, 0x13, 0xc3, 0x2d, 0x2e, 0x60, 0x56, 0x41, 0xc9, 0x48, 0xb7, 0x14, 0xae, 0xc3, 0x0c,
+				0x06, 0x49, 0xdc, 0x44, 0x14, 0x35, 0x11, 0xf3, 0x5a, 0xb0, 0xfd, 0x5d, 0xd6, 0x4c, 0x34, 0xd0,
+				0x6f, 0xe8, 0x6f, 0x38, 0x36, 0xdf, 0xe9, 0xed, 0xeb, 0x7f, 0x08, 0xcf, 0xc3, 0xbd, 0x40, 0x95,
+				0x68, 0x26, 0x35, 0x62, 0x42, 0x19, 0x1f, 0x99, 0xf5, 0x34, 0x73, 0xf3, 0x2b, 0x0c, 0xc0, 0xcf,
+				0x93, 0x21, 0xd6, 0xc9, 0x2a, 0x11, 0x2e, 0x8d, 0xb9, 0x0b, 0x86, 0xee, 0x9e, 0x87, 0xcc, 0x32,
+				0xd0, 0x34, 0x3d, 0xb0, 0x1e, 0x32, 0xce, 0x9e, 0xb7, 0x82, 0xcb, 0x24, 0xef, 0xbb, 0xbe, 0xb4,
+				0x40, 0xfe, 0x92, 0x9e, 0x8f, 0x2b, 0xf8, 0xdf, 0xb1, 0x55, 0x0a, 0x3a, 0x2e, 0x74, 0x2e, 0x8b,
+				0x45, 0x5a, 0x3e, 0x57, 0x30, 0xe9, 0xe6, 0xa7, 0xa9, 0x82, 0x4d, 0x17, 0xac, 0xc0, 0xf7, 0x2a,
+				0x7f, 0x67, 0xea, 0xe0, 0xf0, 0x97, 0x0f, 0x8b, 0xde, 0x46, 0xdc, 0xde, 0xfa, 0xed, 0x30, 0x47,
+				0xcf, 0x80, 0x7e, 0x7f, 0x00, 0xa4, 0x2e, 0x5f, 0xd1, 0x1d, 0x40, 0xf5, 0xe9, 0x85, 0x33, 0xd7,
+				0x57, 0x44, 0x25, 0xb7, 0xd2, 0xbc, 0x3b, 0x38, 0x45, 0xc4, 0x43, 0x00, 0x8b, 0x58, 0x98, 0x0e,
+				0x76, 0x8e, 0x46, 0x4e, 0x17, 0xcc, 0x6f, 0x6b, 0x39, 0x39, 0xee, 0xe5, 0x2f, 0x71, 0x39, 0x63,
+				0xd0, 0x7d, 0x8c, 0x4a, 0xbf, 0x02, 0x44, 0x8e, 0xf0, 0xb8, 0x89, 0xc9, 0x67, 0x1e, 0x2f, 0x8a,
+				0x43, 0x6d, 0xde, 0xef, 0xfc, 0xca, 0x71, 0x76, 0xe9, 0xbf, 0x9d, 0x10, 0x05, 0xec, 0xd3, 0x77,
+				0xf2, 0xfa, 0x67, 0xc2, 0x3e, 0xd1, 0xf1, 0x37, 0xe6, 0x0b, 0xf4, 0x60, 0x18, 0xa8, 0xbd, 0x61,
+				0x3d, 0x03, 0x8e, 0x88, 0x37, 0x04, 0xfc, 0x26, 0xe7, 0x98, 0x96, 0x9d, 0xf3, 0x5e, 0xc7, 0xbb,
+				0xc6, 0xa4, 0xfe, 0x46, 0xd8, 0x91, 0x0b, 0xd8, 0x2f, 0xa3, 0xcd, 0xed, 0x26, 0x5d, 0x0a, 0x3b,
+				0x6d, 0x39, 0x9e, 0x42, 0x51, 0xe4, 0xd8, 0x23, 0x3d, 0xaa, 0x21, 0xb5, 0x81, 0x2f, 0xde, 0xd6,
+				0x53, 0x61, 0x98, 0xff, 0x13, 0xaa, 0x5a, 0x1c, 0xd4, 0x6a, 0x5b, 0x9a, 0x17, 0xa4, 0xdd, 0xc1,
+				0xd9, 0xf8, 0x55, 0x44, 0xd1, 0xd1, 0xcc, 0x16, 0xf3, 0xdf, 0x85, 0x80, 0x38, 0xc8, 0xe0, 0x71,
+				0xa1, 0x1a, 0x7e, 0x15, 0x7a, 0x85, 0xa6, 0xa8, 0xdc, 0x47, 0xe8, 0x8d, 0x75, 0xe7, 0x00, 0x9a,
+				0x8b, 0x26, 0xfd, 0xb7, 0x3f, 0x33, 0xa2, 0xa7, 0x0f, 0x1e, 0x0c, 0x25, 0x9f, 0x8f, 0x95, 0x33,
+				0xb9, 0xb8, 0xf9, 0xaf, 0x92, 0x88, 0xb7, 0x27, 0x4f, 0x21, 0xba, 0xee, 0xc7, 0x8d, 0x39, 0x6f,
+				0x8b, 0xac, 0xdc, 0xc2, 0x24, 0x71, 0x20, 0x7d, 0x9b, 0x4e, 0xfc, 0xcd, 0x3f, 0xed, 0xc5, 0xc5,
+				0xa2, 0x21, 0x4f, 0xf5, 0xe5, 0x1c, 0x55, 0x3f, 0x35, 0xe2, 0x1a, 0xe6, 0x96, 0xfe, 0x51, 0xe8,
+				0xdf, 0x73, 0x3a, 0x8e, 0x06, 0xf5, 0x0f, 0x41, 0x9e, 0x59, 0x9e, 0x9f, 0x9e, 0x4b, 0x37, 0xce,
+				0x64, 0x3f, 0xc8, 0x10, 0xfa, 0xaa, 0x47, 0x98, 0x97, 0x71, 0x50, 0x9d, 0x69, 0xa1, 0x10, 0xac,
+				0x91, 0x62, 0x61, 0x42, 0x70, 0x26, 0x36, 0x9a, 0x21, 0x26, 0x3a, 0xc4, 0x46, 0x0f, 0xb4, 0xf7,
+				0x08, 0xf8, 0xae, 0x28, 0x59, 0x98, 0x56, 0xdb, 0x7c, 0xb6, 0xa4, 0x3a, 0xc8, 0xe0, 0x3d, 0x64,
+				0xa9, 0x60, 0x98, 0x07, 0xe7, 0x6c, 0x5f, 0x31, 0x2b, 0x9d, 0x18, 0x63, 0xbf, 0xa3, 0x04, 0xe8,
+				0x95, 0x36, 0x47, 0x64, 0x8b, 0x4f, 0x4a, 0xb0, 0xed, 0x99, 0x5e
+		}
+};
+
+typedef struct palSha256Vector{
+	size_t inLenInBytes;
+	size_t outLenInBytes;
+	unsigned char output[32];
+	unsigned char input[5];
+} palSha256Vector_t;
+
+palSha256Vector_t sha256Vectors[6] =
+{
+		{
+				0,
+				32,
+				{
+						0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
+						0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
+				},
+				{0x00}
+		},
+		{
+				1,
+				32,
+				{
+						0x68, 0x32, 0x57, 0x20, 0xaa, 0xbd, 0x7c, 0x82, 0xf3, 0x0f, 0x55, 0x4b, 0x31, 0x3d, 0x05, 0x70,
+						0xc9, 0x5a, 0xcc, 0xbb, 0x7d, 0xc4, 0xb5, 0xaa, 0xe1, 0x12, 0x04, 0xc0, 0x8f, 0xfe, 0x73, 0x2b
+				},
+				{0xbd}
+		},
+		{
+				2,
+				32,
+				{
+						0x7c, 0x4f, 0xbf, 0x48, 0x44, 0x98, 0xd2, 0x1b, 0x48, 0x7b, 0x9d, 0x61, 0xde, 0x89,0x14, 0xb2,
+						0xea, 0xda, 0xf2, 0x69, 0x87, 0x12, 0x93, 0x6d, 0x47, 0xc3, 0xad, 0xa2, 0x55, 0x8f,0x67, 0x88
+				},
+				{0x5f, 0xd4}
+		},
+		{
+				3,
+				32,
+				{
+						0x40, 0x96, 0x80, 0x42, 0x21, 0x09, 0x3d, 0xdc, 0xcf, 0xbf, 0x46, 0x83, 0x14, 0x90, 0xea, 0x63,
+						0xe9, 0xe9, 0x94, 0x14, 0x85, 0x8f, 0x8d, 0x75, 0xff, 0x7f, 0x64, 0x2c, 0x7c, 0xa6, 0x18, 0x03
+				},
+				{0xb0, 0xbd, 0x69}
+		},
+		{
+				4,
+				32,
+				{
+						0x7a, 0xbc, 0x22, 0xc0, 0xae, 0x5a, 0xf2, 0x6c, 0xe9, 0x3d, 0xbb, 0x94, 0x43, 0x3a, 0x0e, 0x0b,
+						0x2e, 0x11, 0x9d, 0x01, 0x4f, 0x8e, 0x7f, 0x65, 0xbd, 0x56, 0xc6, 0x1c,0xcc, 0xcd, 0x95, 0x04
+				},
+				{0xc9, 0x8c, 0x8e, 0x55	}
+		},
+		{
+				5,
+				32,
+				{
+						0x75, 0x16, 0xfb, 0x8b, 0xb1, 0x13, 0x50, 0xdf, 0x2b, 0xf3, 0x86, 0xbc, 0x3c, 0x33, 0xbd, 0x0f,
+						0x52, 0xcb, 0x4c, 0x67, 0xc6, 0xe4, 0x74, 0x5e, 0x04, 0x88, 0xe6, 0x2c, 0x2a, 0xea, 0x26, 0x05
+				},
+				{0x81, 0xa7, 0x23, 0xd9, 0x66}
+		}
+};
+
+typedef struct palAesCcmVector{
+	const unsigned char key[16];
+	const unsigned char iv[16];
+	const unsigned char ad[20];
+	const unsigned char in[24];
+	const unsigned char out[32];
+	size_t ivLen;
+	size_t adLen;
+	size_t inLen;
+	size_t tagLen;
+	//	size_t outLen;
+
+}palAesCcmVector_t;
+
+static const palAesCcmVector_t aesCcmVectors[3] =
+{
+		{
+				{
+						0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+						0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
+				},
+				{ 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 },
+				{	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
+				{	0x20, 0x21, 0x22, 0x23 },
+				{   0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
+				7, 8, 4, 4
+		},
+		{
+				{
+						0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+						0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
+				},
+				{ 	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
+				{
+						0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+						0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+				},
+				{
+						0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+						0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
+				},
+				{
+						0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
+						0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
+						0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd
+				},
+				8, 16, 16, 6
+		},
+		{
+				{
+						0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+						0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
+				},
+				{
+						0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+						0x18, 0x19, 0x1a, 0x1b
+				},
+				{
+						0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+						0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+						0x10, 0x11, 0x12, 0x13
+				},
+				{
+						0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+						0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+						0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+				},
+				{
+						0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
+						0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
+						0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
+						0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51
+				},
+				12, 20, 24, 8
+		}
+};
+
+static const unsigned char ctr_drbg_nonce_pers[16] =
+{
+		0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
+		0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f
+};
+
+unsigned char ctr_drbg_buf[100][16];
+
+typedef struct palAesCMACVector{
+	const unsigned char key[16];
+	const unsigned char in[64];
+	const unsigned char out[16];
+	size_t inLen;
+}palAesCMACVector_t;
+
+static const palAesCMACVector_t cmacSingleUseVector[4] =
+{
+		{
+				{
+						0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+						0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+				},
+				{
+						0x00
+				},
+				{
+						0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
+						0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
+				},
+				0
+		},
+		{
+				{
+						0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+						0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+				},
+				{
+						0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+						0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
+				},
+				{
+						0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
+						0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
+				},
+				16
+		},
+		{
+				{
+						0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+						0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+				},
+				{
+						0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+						0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+						0xae, 0x2d, 0x8a, 0x57
+				},
+				{
+						0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8,
+						0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde
+				},
+				20
+		},
+		{
+				{
+						0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+						0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+				},
+				{
+						0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+						0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+						0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
+						0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+						0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+						0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+						0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
+						0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
+				},
+				{
+						0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
+						0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
+				},
+				64
+		}
+};
+
+typedef struct palCMACMultipleBlockVector{
+	palCipherID_t cipher_type;
+	unsigned char key_string[64];
+	unsigned char block1_string[64];
+	unsigned char block2_string[64];
+	unsigned char block3_string[64];
+	unsigned char block4_string[64];
+	unsigned char expected_result_string[64];
+	uint32_t keybits;
+	uint32_t block_size;
+	int32_t block1_len;
+	int32_t block2_len;
+	int32_t block3_len;
+	int32_t block4_len;
+}palCMACMultipleBlockVector_t;
+
+static const palCMACMultipleBlockVector_t cmacIterativeUseVector[] =
+{
+		{
+				PAL_CIPHER_ID_AES,
+				{
+						0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+				},
+				{	0x00	},
+				{	0x00	},
+				{	0x00	},
+				{	0x00	},
+				{
+						0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46
+				}, 128, 16,	-1,	-1,	-1,	-1
+		},
+		{
+				PAL_CIPHER_ID_AES,
+				{
+						0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+				},
+				{
+						0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
+				},
+				{	0x00	},
+				{	0x00	},
+				{	0x00	},
+				{
+						0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
+				}, 128,	16,	16,	-1,	-1,	-1
+		},
+		{
+				PAL_CIPHER_ID_AES,
+				{
+						0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+				},
+				{
+						0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+						0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+						0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+						0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
+				},
+				{	0x00	},
+				{	0x00	},
+				{	0x00	},
+				{
+						0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
+				},	128, 16, 64, -1, -1, -1
+		},
+		{
+				PAL_CIPHER_ID_AES,
+				{
+						0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+				},
+				{
+						0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96
+				},
+				{
+						0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
+				},
+				{	0x00	},
+				{	0x00 	},
+				{
+						0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
+				}, 128,	16,	8, 8, -1, -1
+		},
+		{
+				PAL_CIPHER_ID_AES,
+				{
+						0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+				},
+				{
+						0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
+				},
+				{
+						0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51
+				},
+				{
+						0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef
+				},
+				{
+						0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
+				},
+				{
+						0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
+				}, 128,	16,	16,	16,	16,	16
+		},
+		{
+				PAL_CIPHER_ID_AES,
+				{
+						0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+				},
+				{
+						0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96
+				},
+				{
+						0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c
+				},
+				{
+						0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+						0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef
+				},
+				{
+						0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10
+				},
+				{
+						0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe
+				},128, 16, 8, 16, 24, 16
+		},
+		{
+				PAL_CIPHER_ID_AES,
+				{
+						0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c
+				},
+				{	0x00	},
+				{
+						0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96
+				},
+				{	0x00	},
+				{
+						0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a
+				},
+				{
+						0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c
+				}, 128,	16, 0, 8, 0, 8
+		}
+};
+
+typedef struct palASN1TestVector{
+	size_t start;
+	size_t end;
+	size_t dataLen;
+	uint8_t type;
+}palASN1TestVector_t;
+
+static const palASN1TestVector_t ASN1TestVector[11] = {
+		{ 0, 879, 875, PAL_ASN1_SEQUENCE | PAL_ASN1_CONSTRUCTED },
+		{ 10, 13, 1, PAL_ASN1_INTEGER },
+		{ 26, 37, 9, PAL_ASN1_OID },
+		{ 37, 39, 0, PAL_ASN1_NULL },
+		{ 41, 54, 11, PAL_ASN1_SET | PAL_ASN1_CONSTRUCTED },
+		{ 50, 54, 2, PAL_ASN1_PRINTABLE_STRING },
+		{ 63, 75, 10, PAL_ASN1_UTF8_STRING },
+		{ 119, 134, 13, PAL_ASN1_UTC_TIME },
+		{ 532, 556, 22, PAL_ASN1_OCTET_STRING },
+		{ 600, 603, 1, PAL_ASN1_BOOLEAN },
+		{ 618, 879, 257, PAL_ASN1_BIT_STRING }
+};
+
+
+static const unsigned char asn1_data[879] =
+{
+		0x30, 0x82, 0x03, 0x6B, 0x30, 0x82, 0x02, 0x53, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
+		0xAA, 0xF6, 0x26, 0x55, 0x10, 0xA4, 0x58, 0x1E, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+		0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x4C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
+		0x04, 0x06, 0x13, 0x02, 0x49, 0x4C, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C,
+		0x0A, 0x53, 0x6F, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x0C, 0x30, 0x0A, 0x06,
+		0x03, 0x55, 0x04, 0x07, 0x0C, 0x03, 0x4E, 0x65, 0x74, 0x31, 0x0C, 0x30, 0x0A, 0x06, 0x03, 0x55,
+		0x04, 0x0A, 0x0C, 0x03, 0x41, 0x52, 0x4D, 0x31, 0x0C, 0x30, 0x0A, 0x06, 0x03, 0x55, 0x04, 0x0B,
+		0x0C, 0x03, 0x50, 0x41, 0x4C, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x36, 0x31, 0x31, 0x32, 0x33, 0x31,
+		0x33, 0x35, 0x30, 0x31, 0x39, 0x5A, 0x17, 0x0D, 0x31, 0x37, 0x31, 0x31, 0x32, 0x33, 0x31, 0x33,
+		0x35, 0x30, 0x31, 0x39, 0x5A, 0x30, 0x4C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+		0x13, 0x02, 0x49, 0x4C, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x53,
+		0x6F, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x0C, 0x30, 0x0A, 0x06, 0x03, 0x55,
+		0x04, 0x07, 0x0C, 0x03, 0x4E, 0x65, 0x74, 0x31, 0x0C, 0x30, 0x0A, 0x06, 0x03, 0x55, 0x04, 0x0A,
+		0x0C, 0x03, 0x41, 0x52, 0x4D, 0x31, 0x0C, 0x30, 0x0A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x03,
+		0x50, 0x41, 0x4C, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
+		0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02,
+		0x82, 0x01, 0x01, 0x00, 0xCE, 0xD5, 0x2F, 0x89, 0x97, 0xD5, 0xC1, 0xDF, 0x2D, 0xDB, 0x1B, 0xF5,
+		0x4B, 0x0F, 0xAF, 0xD0, 0xF1, 0xC5, 0xD4, 0x45, 0xD4, 0x6D, 0x55, 0x73, 0x73, 0xD5, 0xBB, 0x7D,
+		0x2E, 0x56, 0x8E, 0xF4, 0xCB, 0xAC, 0x0A, 0x78, 0x91, 0x9E, 0x6C, 0x72, 0xA6, 0x0F, 0x65, 0xFE,
+		0x86, 0x91, 0x2D, 0x96, 0xE0, 0x40, 0xF4, 0x3A, 0xBB, 0x82, 0x29, 0x69, 0x23, 0x92, 0x93, 0xC8,
+		0x20, 0x83, 0xD3, 0x7A, 0xFF, 0x71, 0xB4, 0x11, 0x43, 0xF0, 0x30, 0xE8, 0x32, 0xF8, 0x4C, 0xCB,
+		0xE6, 0xF1, 0xE2, 0xBC, 0x01, 0xE6, 0xB8, 0x17, 0xBF, 0x82, 0xA2, 0xBF, 0x75, 0xFF, 0x88, 0x44,
+		0x15, 0x86, 0x88, 0x4A, 0xDF, 0xEF, 0x48, 0x46, 0xD8, 0xFA, 0x81, 0xBB, 0xAA, 0xED, 0x16, 0xC7,
+		0x7C, 0xE8, 0xCE, 0x1E, 0x79, 0x6C, 0x2D, 0x66, 0x88, 0x4C, 0xB7, 0x88, 0xA5, 0x35, 0xD7, 0x4A,
+		0xE8, 0x6D, 0x89, 0xD1, 0x84, 0xBF, 0x23, 0x9B, 0xA2, 0xF4, 0xF3, 0x0D, 0x3E, 0xB8, 0x12, 0x48,
+		0x38, 0xC6, 0x76, 0xD3, 0xEF, 0xAE, 0xA1, 0xD9, 0xC9, 0xA8, 0x32, 0xE7, 0x5E, 0xD5, 0x7C, 0x2A,
+		0x26, 0xAD, 0x94, 0x60, 0xF6, 0x73, 0x73, 0xD1, 0x8B, 0xA3, 0x2A, 0x42, 0xA6, 0x86, 0x47, 0x0F,
+		0x61, 0x59, 0xCD, 0x13, 0x87, 0xFB, 0x14, 0x16, 0x0E, 0x22, 0xBA, 0x7E, 0xC4, 0xF9, 0xC5, 0x59,
+		0x31, 0xDF, 0xDA, 0x6A, 0xBB, 0x3F, 0x8B, 0xE7, 0xF7, 0x22, 0x7E, 0x35, 0xF2, 0xE3, 0x8A, 0xAC,
+		0xFA, 0xCF, 0x49, 0xE0, 0x64, 0xC0, 0xC8, 0x24, 0x96, 0x69, 0x23, 0x3A, 0xC7, 0x04, 0x0A, 0x99,
+		0xA7, 0x21, 0x87, 0x87, 0x9A, 0x01, 0x7B, 0x50, 0xCF, 0xE1, 0x7B, 0x0E, 0x8A, 0x4A, 0x25, 0xCF,
+		0x88, 0xE4, 0x47, 0xAD, 0x85, 0x47, 0x8A, 0xE7, 0x35, 0xD9, 0x6B, 0x13, 0xA4, 0x77, 0x3F, 0x58,
+		0x8F, 0x55, 0x65, 0xFF, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x50, 0x30, 0x4E, 0x30, 0x1D, 0x06,
+		0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x53, 0x43, 0x7D, 0x59, 0x2A, 0xF5, 0x93, 0xA5,
+		0xA5, 0x02, 0x43, 0xD9, 0x7B, 0xC4, 0x2C, 0xCA, 0xBD, 0xDE, 0x96, 0x0D, 0x30, 0x1F, 0x06, 0x03,
+		0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x53, 0x43, 0x7D, 0x59, 0x2A, 0xF5, 0x93,
+		0xA5, 0xA5, 0x02, 0x43, 0xD9, 0x7B, 0xC4, 0x2C, 0xCA, 0xBD, 0xDE, 0x96, 0x0D, 0x30, 0x0C, 0x06,
+		0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A,
+		0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x15,
+		0x9A, 0xFC, 0xBF, 0x26, 0x7A, 0x6A, 0xF9, 0x3F, 0xD4, 0x88, 0xF9, 0x83, 0x6C, 0xF6, 0x68, 0xC6,
+		0x99, 0xDD, 0x55, 0x62, 0x89, 0xFB, 0x80, 0x74, 0x5B, 0x14, 0x1A, 0x82, 0x4F, 0xFF, 0x5E, 0xCC,
+		0x20, 0x97, 0x68, 0x8C, 0x7B, 0x85, 0x02, 0xDE, 0x5A, 0x02, 0x4C, 0x72, 0x57, 0xE8, 0x01, 0x0A,
+		0x08, 0x0F, 0xA2, 0xAB, 0xA4, 0x57, 0xC8, 0x4C, 0x8A, 0x3D, 0xCF, 0x23, 0xA6, 0xE4, 0x8D, 0xE3,
+		0x1E, 0x9F, 0x50, 0xB3, 0x2C, 0xDD, 0xC6, 0x11, 0x98, 0xAA, 0x71, 0xA9, 0xF3, 0x02, 0x5C, 0x16,
+		0xDB, 0xC2, 0x28, 0xA3, 0x9E, 0x51, 0xB1, 0xE7, 0xEC, 0x60, 0xE4, 0x59, 0x62, 0x1B, 0xC0, 0x4F,
+		0xE4, 0xF3, 0xD7, 0x10, 0x12, 0x38, 0x6D, 0x2A, 0xF8, 0x96, 0x4E, 0x25, 0xE5, 0x05, 0xE1, 0x77,
+		0x1F, 0xC7, 0xAB, 0x54, 0xDA, 0x0D, 0x09, 0xE5, 0xC3, 0xB0, 0x61, 0x50, 0x11, 0xC8, 0x5C, 0x7B,
+		0x6B, 0x96, 0x71, 0x2E, 0xC9, 0x7C, 0x8E, 0x34, 0xA9, 0xB9, 0x25, 0x0A, 0x35, 0x0F, 0xA1, 0x77,
+		0x6C, 0xC3, 0x30, 0x96, 0x7C, 0x40, 0x12, 0x9D, 0xBB, 0x62, 0xA7, 0xD6, 0xE6, 0x07, 0xCB, 0xAB,
+		0xC6, 0xD7, 0xD1, 0x3C, 0x4D, 0x7F, 0xAE, 0x62, 0x22, 0xBD, 0x88, 0x33, 0x43, 0x15, 0xFF, 0x63,
+		0x80, 0x95, 0x29, 0xCD, 0x00, 0x76, 0x53, 0xF6, 0xA6, 0xA1, 0xD0, 0x07, 0xE4, 0xF0, 0xC2, 0x03,
+		0xBA, 0x7B, 0x25, 0x9B, 0x75, 0xA1, 0xB6, 0xA8, 0x4C, 0x44, 0x72, 0x14, 0x48, 0x29, 0x75, 0x76,
+		0x66, 0xB1, 0xBB, 0x5A, 0x2D, 0x7C, 0x21, 0xBB, 0xEA, 0x70, 0x45, 0x8E, 0x6E, 0xFA, 0xCE, 0xCE,
+		0x26, 0xDE, 0xF7, 0x36, 0xB7, 0x52, 0xBC, 0x9F, 0x21, 0x35, 0x2F, 0x5B, 0xAF, 0x0A, 0xAE, 0xD8,
+		0xE1, 0x0C, 0x69, 0x27, 0x30, 0xFF, 0xCF, 0x13, 0xE8, 0x57, 0x1F, 0x5B, 0x38, 0x13, 0x02
+};
+
+
+typedef struct palCheckEcKeyTestVector
+{
+	const unsigned char key[200];
+	size_t keyLen;
+	palGroupIndex_t index;
+	uint32_t keyType;
+	palStatus_t parsePrvRes;
+	palStatus_t checkPrvRes;
+	bool verifed;
+	palStatus_t parsePubRes;
+	palStatus_t checkPubRes;
+}palCheckEcKeyTestVector_t;
+
+
+
+static const palCheckEcKeyTestVector_t check_ec_key_data[3] =
+{
+		{
+				{ 0x00 }, 0, PAL_ECP_DP_SECP256R1, PAL_CHECK_PRIVATE_KEY, PAL_ERR_PK_KEY_INVALID_FORMAT, PAL_ERR_PARSING_PRIVATE_KEY, false, PAL_ERR_PARSING_PUBLIC_KEY, PAL_ERR_PARSING_PUBLIC_KEY
+		},
+		{
+				{
+						0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x07, 0xED, 0xF8, 0x74, 0xA2, 0x0A, 0x3D, 0xA2, 0xC5,
+						0x89, 0x99, 0x8A, 0x28, 0xC5, 0x00, 0x8C, 0x12, 0xD8, 0x9B, 0xC9, 0x74, 0x2F, 0x94, 0x53, 0x40,
+						0x82, 0x36, 0x96, 0x04, 0x15, 0x2A, 0xB6, 0xA0, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+						0x03, 0x01, 0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xE5, 0xD8, 0x40, 0xEF, 0xE8, 0x3B, 0x0D,
+						0xC5, 0x7E, 0x72, 0x21, 0x65, 0xF6, 0x96, 0xF0, 0xC8, 0x16, 0xCC, 0xC5, 0x9D, 0x88, 0x24, 0x41,
+						0xF3, 0xB3, 0x39, 0x34, 0xD2, 0xA1, 0x5B, 0xF9, 0xC7, 0xAF, 0xF6, 0x8F, 0x4E, 0x78, 0x01, 0xDB,
+						0xB2, 0xAA, 0x7E, 0x7E, 0xC7, 0x41, 0x31, 0xF4, 0x8D, 0xD4, 0x8E, 0x98, 0x7B, 0x16, 0x4E, 0x96,
+						0x26, 0x71, 0x9D, 0x1F, 0x84, 0xEC, 0x68, 0x9A, 0x31
+				}, 121, PAL_ECP_DP_SECP256R1, PAL_CHECK_PRIVATE_KEY, PAL_SUCCESS, PAL_SUCCESS, true, PAL_ERR_PARSING_PUBLIC_KEY, PAL_ERR_PARSING_PUBLIC_KEY
+		},
+		{
+				{
+						0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A,
+						0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xE5, 0xD8, 0x40, 0xEF, 0xE8,
+						0x3B, 0x0D, 0xC5, 0x7E, 0x72, 0x21, 0x65, 0xF6, 0x96, 0xF0, 0xC8, 0x16, 0xCC, 0xC5, 0x9D, 0x88,
+						0x24, 0x41, 0xF3, 0xB3, 0x39, 0x34, 0xD2, 0xA1, 0x5B, 0xF9, 0xC7, 0xAF, 0xF6, 0x8F, 0x4E, 0x78,
+						0x01, 0xDB, 0xB2, 0xAA, 0x7E, 0x7E, 0xC7, 0x41, 0x31, 0xF4, 0x8D, 0xD4, 0x8E, 0x98, 0x7B, 0x16,
+						0x4E, 0x96, 0x26, 0x71, 0x9D, 0x1F, 0x84, 0xEC, 0x68, 0x9A, 0x31
+				}, 91, PAL_ECP_DP_SECP256R1, PAL_CHECK_PUBLIC_KEY, PAL_ERR_PK_KEY_INVALID_FORMAT, PAL_ERR_PARSING_PRIVATE_KEY, true, PAL_SUCCESS, PAL_SUCCESS
+		}
+};
+
+typedef struct palParseECKeyTestVector{
+	const unsigned char key[250];
+	size_t len;
+	uint32_t type;
+	bool isDER;
+	bool shouldSucceed;
+
+}palParseECKeyTestVector_t;
+
+static const palParseECKeyTestVector_t parse_ec_key_data[8] =
+{
+		{
+				{0x00, 0x00}, 0, PAL_CHECK_PRIVATE_KEY, true, false
+		},
+		{
+				{0x00, 0x00}, 0, PAL_CHECK_PUBLIC_KEY, true, false
+		},
+		{
+				{
+						0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xBD, 0x42, 0xD6, 0x36, 0x31, 0x2D, 0xF3, 0x2B, 0x31,
+						0xEB, 0xE6, 0xE3, 0xC8, 0x63, 0x61, 0xA8, 0x45, 0x92, 0x2C, 0x70, 0xAB, 0x02, 0xC7, 0x45, 0xA7,
+						0xBA, 0x7F, 0x39, 0xD3, 0xFD, 0xF0, 0x07, 0xA0, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+						0x03, 0x01, 0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x7A, 0xDC, 0x03, 0xFE, 0xEF, 0x2B, 0x2B,
+						0xF4, 0xE4, 0x6B, 0xAB, 0xA4, 0xD8, 0xEE, 0x2D, 0xAE, 0xA5, 0xD2, 0x28, 0xC5, 0xC1, 0xB2, 0x3C,
+						0x7A, 0xAA, 0x5D, 0xE7, 0x81, 0x09, 0x1F, 0xE5, 0x9D, 0x80, 0xD4, 0xE9, 0xC5, 0x99, 0xF8, 0xBB,
+						0xB1, 0x7B, 0xCB, 0x9A, 0x48, 0x2E, 0xF9, 0xEB, 0x01, 0xA3, 0xA4, 0x81, 0x70, 0x29, 0x34, 0xDB,
+						0xE0, 0x65, 0x68, 0x48, 0x62, 0x99, 0x6D, 0xEC, 0x2E
+				},121, PAL_CHECK_PRIVATE_KEY, true, true
+		},
+		{
+				{
+						0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A,
+						0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x7A, 0xDC, 0x03, 0xFE, 0xEF,
+						0x2B, 0x2B, 0xF4, 0xE4, 0x6B, 0xAB, 0xA4, 0xD8, 0xEE, 0x2D, 0xAE, 0xA5, 0xD2, 0x28, 0xC5, 0xC1,
+						0xB2, 0x3C, 0x7A, 0xAA, 0x5D, 0xE7, 0x81, 0x09, 0x1F, 0xE5, 0x9D, 0x80, 0xD4, 0xE9, 0xC5, 0x99,
+						0xF8, 0xBB, 0xB1, 0x7B, 0xCB, 0x9A, 0x48, 0x2E, 0xF9, 0xEB, 0x01, 0xA3, 0xA4, 0x81, 0x70, 0x29,
+						0x34, 0xDB, 0xE0, 0x65, 0x68, 0x48, 0x62, 0x99, 0x6D, 0xEC, 0x2E
+				}, 91, PAL_CHECK_PUBLIC_KEY, true, true
+		},
+		{
+				{
+						0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xBD, 0x42, 0xD6, 0x36, 0x31, 0x2D, 0xF3, 0x2B, 0x31,
+						0xEB, 0xE6, 0xE3, 0xC8, 0x63, 0x61, 0xA8, 0x45, 0x92, 0x2C, 0x70, 0xAB, 0x02, 0xC7, 0x45, 0xA7,
+						0xBA, 0x7F, 0x39, 0xD3, 0xFD, 0xF0, 0x07, 0xA0, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+						0x03, 0x01, 0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x7A, 0xDC, 0x03, 0xFE, 0xEF, 0x2B, 0x2B,
+						0xF4, 0xE4, 0x6B, 0xAB, 0xA4, 0xD8, 0xEE, 0x2D, 0xAE, 0xA5, 0xD2, 0x28, 0xC5, 0xC1, 0xB2, 0x3C,
+						0x7A, 0xAA, 0x5D, 0xE7, 0x81, 0x09, 0x1F, 0xE5, 0x9D, 0x80, 0xD4, 0xE9, 0xC5, 0x99, 0xF8, 0xBB,
+						0xB1, 0x7B, 0xCB, 0x9A, 0x48, 0x2E, 0xF9, 0xEB, 0x01, 0xA3, 0xA4, 0x81, 0x70, 0x29, 0x34, 0xDB,
+						0xE0, 0x65, 0x68, 0x48, 0x62, 0x99, 0x6D, 0xEC, 0x2E
+				}, 121,	PAL_CHECK_PUBLIC_KEY, true, false
+		},
+		{
+				{
+						0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A,
+						0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x7A, 0xDC, 0x03, 0xFE, 0xEF,
+						0x2B, 0x2B, 0xF4, 0xE4, 0x6B, 0xAB, 0xA4, 0xD8, 0xEE, 0x2D, 0xAE, 0xA5, 0xD2, 0x28, 0xC5, 0xC1,
+						0xB2, 0x3C, 0x7A, 0xAA, 0x5D, 0xE7, 0x81, 0x09, 0x1F, 0xE5, 0x9D, 0x80, 0xD4, 0xE9, 0xC5, 0x99,
+						0xF8, 0xBB, 0xB1, 0x7B, 0xCB, 0x9A, 0x48, 0x2E, 0xF9, 0xEB, 0x01, 0xA3, 0xA4, 0x81, 0x70, 0x29,
+						0x34, 0xDB, 0xE0, 0x65, 0x68, 0x48, 0x62, 0x99, 0x6D, 0xEC, 0x2E
+				},91, PAL_CHECK_PRIVATE_KEY, true, false
+		},
+		{
+				"-----BEGIN EC PRIVATE KEY-----\r\n"
+				"MHcCAQEEIBnI7FMl8SVLh8u3jUyGtJRxtyzf8WhZ6zVlR+uezRi/oAoGCCqGSM49\r\n"
+				"AwEHoUQDQgAE7XbxNHg17rUMJ8nwTSTwSRrskUVWVkrnB7HARGN8eX4vL6v75D/3\r\n"
+				"WsseEnEVMAhsbPs7rDx7xaKStJQKKSX84w==\r\n"
+				"-----END EC PRIVATE KEY-----\r\n",
+				236, PAL_CHECK_PRIVATE_KEY, false, false
+		},
+		{
+				"-----BEGIN PUBLIC KEY-----\r\n"
+				"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7XbxNHg17rUMJ8nwTSTwSRrskUVW\r\n"
+				"VkrnB7HARGN8eX4vL6v75D/3WsseEnEVMAhsbPs7rDx7xaKStJQKKSX84w==\r\n"
+				"-----END PUBLIC KEY-----\r\n",
+				185, PAL_CHECK_PUBLIC_KEY, false, false
+		}
+};
+
+
+typedef struct palX509CSRTestVector{
+	unsigned char prvkey[300];
+	size_t prvkeyLen;
+	unsigned char pubkey[300];
+	size_t pubkeyLen;
+	palMDType_t mdType;
+	const char subject_name[50];
+	uint32_t keyUsage;
+	unsigned char derOut[300];
+	size_t derOutLen;
+}palX509CSRTestVector_t;
+
+static const palX509CSRTestVector_t CsrTests[2] =
+{
+		{
+				{
+						0x30, 0x78, 0x02, 0x01, 0x01, 0x04, 0x21, 0x00, 0xAE, 0xD9, 0xBE, 0xEA, 0x76, 0x78, 0xF2, 0xD9,
+						0xEC, 0x11, 0xC5, 0x49, 0x00, 0xDC, 0xB7, 0xB1, 0x06, 0xBD, 0xA5, 0xF6, 0xF7, 0x06, 0xBB, 0xC2,
+						0x8A, 0x8D, 0x46, 0xCB, 0xCF, 0xAE, 0x1F, 0x22, 0xA0, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+						0x3D, 0x03, 0x01, 0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xC9, 0xEB, 0xAC, 0x6F, 0x9C, 0x39,
+						0x1D, 0xFC, 0xFE, 0xBD, 0x25, 0x69, 0x51, 0x56, 0x80, 0xAC, 0xBF, 0x1A, 0x6F, 0xD4, 0xD7, 0x2E,
+						0x02, 0x07, 0xBF, 0xF8, 0x4C, 0xEF, 0xEC, 0x60, 0x41, 0xAC, 0xDC, 0x7D, 0xD6, 0xDE, 0xD9, 0xF4,
+						0xAA, 0xB8, 0x81, 0x0F, 0x96, 0xB6, 0xB3, 0x4A, 0x47, 0xD3, 0x98, 0x3F, 0x52, 0x87, 0x62, 0x0D,
+						0xC7, 0xA0, 0x40, 0xCD, 0x23, 0x03, 0xBD, 0x17, 0x1E, 0xDE
+				},122,
+				{
+						0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A,
+						0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xC9, 0xEB, 0xAC, 0x6F, 0x9C,
+						0x39, 0x1D, 0xFC, 0xFE, 0xBD, 0x25, 0x69, 0x51, 0x56, 0x80, 0xAC, 0xBF, 0x1A, 0x6F, 0xD4, 0xD7,
+						0x2E, 0x02, 0x07, 0xBF, 0xF8, 0x4C, 0xEF, 0xEC, 0x60, 0x41, 0xAC, 0xDC, 0x7D, 0xD6, 0xDE, 0xD9,
+						0xF4, 0xAA, 0xB8, 0x81, 0x0F, 0x96, 0xB6, 0xB3, 0x4A, 0x47, 0xD3, 0x98, 0x3F, 0x52, 0x87, 0x62,
+						0x0D, 0xC7, 0xA0, 0x40, 0xCD, 0x23, 0x03, 0xBD, 0x17, 0x1E, 0xDE
+				}, 91, PAL_SHA256, "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd", PAL_X509_KU_DIGITAL_SIGNATURE,
+				{
+						0x30, 0x82, 0x01, 0x20, 0x30, 0x81, 0xC5, 0x02, 0x01, 0x00, 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09,
+						0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+						0x04, 0x08, 0x13, 0x0A, 0x53, 0x6F, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+						0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x18, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65,
+						0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4C, 0x74,
+						0x64, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08,
+						0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xC9, 0xEB, 0xAC, 0x6F,
+						0x9C, 0x39, 0x1D, 0xFC, 0xFE, 0xBD, 0x25, 0x69, 0x51, 0x56, 0x80, 0xAC, 0xBF, 0x1A, 0x6F, 0xD4,
+						0xD7, 0x2E, 0x02, 0x07, 0xBF, 0xF8, 0x4C, 0xEF, 0xEC, 0x60, 0x41, 0xAC, 0xDC, 0x7D, 0xD6, 0xDE,
+						0xD9, 0xF4, 0xAA, 0xB8, 0x81, 0x0F, 0x96, 0xB6, 0xB3, 0x4A, 0x47, 0xD3, 0x98, 0x3F, 0x52, 0x87,
+						0x62, 0x0D, 0xC7, 0xA0, 0x40, 0xCD, 0x23, 0x03, 0xBD, 0x17, 0x1E, 0xDE, 0xA0, 0x1E, 0x30, 0x1C,
+						0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x0E, 0x31, 0x0F, 0x30, 0x0D, 0x30,
+						0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x80, 0x30, 0x0C, 0x06, 0x08,
+						0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02,
+						0x21, 0x00, 0xEF, 0xA5, 0x91, 0xE8, 0x43, 0x2C, 0x95, 0x54, 0x51, 0xFA, 0x75, 0xAE, 0xF3, 0xE5,
+						0x5B, 0xAE, 0x37, 0x28, 0x43, 0x12, 0xBE, 0xCB, 0x54, 0x67, 0x1C, 0xF8, 0x5F, 0x28, 0xD8, 0x87,
+						0x23, 0x35, 0x02, 0x20, 0x32, 0xB7, 0x86, 0x38, 0xEF, 0x9F, 0x96, 0x25, 0x4B, 0xB5, 0xCD, 0x11,
+						0xBB, 0x23, 0x3F, 0x93, 0x44, 0x31, 0x73, 0xF1, 0x0A, 0xBA, 0x2F, 0x43, 0x21, 0xFB, 0xBD, 0x4B,
+						0xE5, 0xD4, 0xF0, 0x42
+				}, 292
+		},
+		{
+				{
+						0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x12, 0x02, 0xAF, 0xCF, 0x14, 0xEC, 0xDB, 0x72, 0xDF,
+						0x1C, 0x0C, 0xF1, 0xE3, 0x23, 0x97, 0x83, 0x62, 0x31, 0x71, 0x4C, 0xE6, 0x5B, 0x88, 0x9B, 0xF1,
+						0x19, 0x40, 0xE4, 0xBE, 0xE9, 0x34, 0x76, 0xA0, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+						0x03, 0x01, 0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x6D, 0xE7, 0x22, 0xF3, 0xCB, 0x5F, 0x84,
+						0x83, 0xEE, 0x27, 0xE2, 0xA1, 0x24, 0xFF, 0xAC, 0x19, 0xF7, 0x2D, 0xDD, 0xFA, 0x69, 0x20, 0xBE,
+						0x06, 0x7E, 0x8A, 0x20, 0x40, 0x26, 0x90, 0xE9, 0xFB, 0xBA, 0x86, 0x0A, 0xE0, 0x9A, 0x39, 0x1B,
+						0x0F, 0xB8, 0x53, 0xD5, 0xFC, 0xE1, 0x5E, 0x94, 0xBC, 0x1E, 0x97, 0x9C, 0xC2, 0x7B, 0x4E, 0xF7,
+						0x17, 0x36, 0xCA, 0x59, 0xD5, 0x01, 0xBB, 0x56, 0x74
+				}, 121,
+				{
+						0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A,
+						0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x6D, 0xE7, 0x22, 0xF3, 0xCB,
+						0x5F, 0x84, 0x83, 0xEE, 0x27, 0xE2, 0xA1, 0x24, 0xFF, 0xAC, 0x19, 0xF7, 0x2D, 0xDD, 0xFA, 0x69,
+						0x20, 0xBE, 0x06, 0x7E, 0x8A, 0x20, 0x40, 0x26, 0x90, 0xE9, 0xFB, 0xBA, 0x86, 0x0A, 0xE0, 0x9A,
+						0x39, 0x1B, 0x0F, 0xB8, 0x53, 0xD5, 0xFC, 0xE1, 0x5E, 0x94, 0xBC, 0x1E, 0x97, 0x9C, 0xC2, 0x7B,
+						0x4E, 0xF7, 0x17, 0x36, 0xCA, 0x59, 0xD5, 0x01, 0xBB, 0x56, 0x74
+				}, 91, PAL_SHA256, "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd", PAL_X509_KU_NON_REPUDIATION,
+				{
+						0x30, 0x82, 0x01, 0x20, 0x30, 0x81, 0xC5, 0x02, 0x01, 0x00, 0x30, 0x45, 0x31, 0x0B, 0x30, 0x09,
+						0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55,
+						0x04, 0x08, 0x13, 0x0A, 0x53, 0x6F, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21,
+						0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x18, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65,
+						0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4C, 0x74,
+						0x64, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08,
+						0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x6D, 0xE7, 0x22, 0xF3,
+						0xCB, 0x5F, 0x84, 0x83, 0xEE, 0x27, 0xE2, 0xA1, 0x24, 0xFF, 0xAC, 0x19, 0xF7, 0x2D, 0xDD, 0xFA,
+						0x69, 0x20, 0xBE, 0x06, 0x7E, 0x8A, 0x20, 0x40, 0x26, 0x90, 0xE9, 0xFB, 0xBA, 0x86, 0x0A, 0xE0,
+						0x9A, 0x39, 0x1B, 0x0F, 0xB8, 0x53, 0xD5, 0xFC, 0xE1, 0x5E, 0x94, 0xBC, 0x1E, 0x97, 0x9C, 0xC2,
+						0x7B, 0x4E, 0xF7, 0x17, 0x36, 0xCA, 0x59, 0xD5, 0x01, 0xBB, 0x56, 0x74, 0xA0, 0x1E, 0x30, 0x1C,
+						0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x0E, 0x31, 0x0F, 0x30, 0x0D, 0x30,
+						0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x40, 0x30, 0x0C, 0x06, 0x08,
+						0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02,
+						0x21, 0x00, 0xEC, 0xA1, 0xDE, 0x83, 0x89, 0x1A, 0x05, 0xA6, 0x38, 0x7B, 0xC1, 0xDB, 0x0D, 0x67,
+						0xEC, 0x9E, 0x98, 0x3C, 0x92, 0xB3, 0x58, 0x06, 0x34, 0x87, 0x19, 0xAB, 0x57, 0x2B, 0x70, 0x29,
+						0x4C, 0x3D, 0x02, 0x20, 0x6A, 0x9D, 0x7D, 0xFF, 0x8B, 0x00, 0x74, 0x24, 0xA1, 0xD6, 0xD6, 0xEF,
+						0xF7, 0x70, 0x86, 0x8D, 0x2D, 0x52, 0x68, 0x55, 0x18, 0x7C, 0x45, 0xFB, 0xEE, 0x49, 0x50, 0x62,
+						0x9E, 0x6C, 0x1C, 0xCA
+				}, 292
+		}
+};
+
+const unsigned char cert_not_self_signed[] =
+{
+		0x30, 0x82, 0x01, 0xc4, 0x30, 0x82, 0x01, 0x69, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01,
+		0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x3d,
+		0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x07, 0x49, 0x4f, 0x54, 0x5f, 0x50,
+		0x41, 0x4c, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x50, 0x41, 0x4c,
+		0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x31, 0x0e, 0x30,
+		0x0c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x05, 0x49, 0x4f, 0x54, 0x42, 0x55, 0x30, 0x1e, 0x17,
+		0x0d, 0x31, 0x33, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d,
+		0x31, 0x35, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x42, 0x31,
+		0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x08, 0x49, 0x4f, 0x54, 0x5f, 0x54, 0x45,
+		0x53, 0x54, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x04, 0x50, 0x41, 0x41,
+		0x4c, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x31, 0x11,
+		0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x08, 0x49, 0x4f, 0x54, 0x42, 0x55, 0x5f, 0x49,
+		0x4c, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08,
+		0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x18, 0xf7, 0x26, 0xc6,
+		0x86, 0x30, 0xec, 0xed, 0xd6, 0xb4, 0x3a, 0xd3, 0x86, 0x7a, 0x49, 0xbb, 0xb3, 0x93, 0xee, 0x43,
+		0x56, 0x18, 0x71, 0x2a, 0x40, 0xda, 0xc8, 0x2c, 0x4a, 0xc6, 0x3d, 0x09, 0xfc, 0xe0, 0x84, 0x2f,
+		0x0d, 0xce, 0xf8, 0x17, 0xcf, 0x28, 0x8f, 0x4f, 0xb4, 0xea, 0xde, 0xf9, 0xe4, 0x9a, 0x16, 0xeb,
+		0x8c, 0x67, 0x02, 0xfd, 0x64, 0x7b, 0x62, 0x0e, 0x9b, 0x29, 0x05, 0x22, 0xa3, 0x53, 0x30, 0x51,
+		0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01,
+		0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x13, 0xde, 0xa2, 0x8b,
+		0x8d, 0x40, 0x1e, 0xd6, 0x62, 0xfd, 0x7e, 0x27, 0x53, 0xb8, 0x8f, 0x17, 0x18, 0x76, 0x33, 0x20,
+		0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x13, 0xde, 0xa2,
+		0x8b, 0x8d, 0x40, 0x1e, 0xd6, 0x62, 0xfd, 0x7e, 0x27, 0x53, 0xb8, 0x8f, 0x17, 0x18, 0x76, 0x33,
+		0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03,
+		0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x47, 0xb7, 0xf8, 0x12, 0xb0, 0xe7, 0x7b, 0x33, 0x7f, 0x31,
+		0x5e, 0x2f, 0x54, 0x40, 0x8f, 0xff, 0xe1, 0x05, 0x1b, 0xe5, 0xf1, 0xd5, 0xa7, 0x6a, 0xb8, 0x2a,
+		0x6f, 0x22, 0x5a, 0xce, 0x31, 0x84, 0x02, 0x20, 0x51, 0x5d, 0x68, 0x41, 0x7f, 0x26, 0xb2, 0x6b,
+		0x71, 0x1e, 0xd2, 0xa2, 0x2d, 0xd9, 0x43, 0x69, 0xbf, 0xf0, 0x73, 0xf6, 0x01, 0x7f, 0xf7, 0xac,
+		0x0e, 0x5c, 0xb4, 0x4e, 0x56, 0x73, 0x63, 0x3c
+};
+
+//Certificate based on unsupported hash – sha512
+const uint8_t testdata_x509_Sha512[506] = 
+		{ 
+			0x30, 0x82, 0x01, 0xf6, 0x30, 0x82, 0x01, 0x9c, 0x02, 0x09, 0x00, 0xb4, 0x60, 0xcc, 0x6f, 0xa2, 
+			0x55, 0x52, 0xfe, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x30, 
+			0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x4b, 0x31, 
+			0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x4b, 0x66, 0x61, 0x72, 0x2d, 0x6e, 
+			0x65, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x4e, 
+			0x65, 0x74, 0x61, 0x6e, 0x69, 0x61, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 
+			0x03, 0x41, 0x52, 0x4d, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x03, 0x49, 
+			0x4f, 0x54, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x06, 0x44, 0x65, 0x76, 
+			0x69, 0x63, 0x65, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 
+			0x09, 0x01, 0x16, 0x10, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x31, 0x40, 0x61, 0x72, 0x6d, 
+			0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x39, 0x31, 0x30, 0x31, 0x34, 
+			0x30, 0x33, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x32, 0x33, 0x30, 0x33, 0x30, 0x33, 0x31, 0x34, 0x30, 
+			0x33, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 
+			0x13, 0x02, 0x55, 0x4b, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x4b, 
+			0x66, 0x61, 0x72, 0x2d, 0x6e, 0x65, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 
+			0x04, 0x07, 0x0c, 0x07, 0x4e, 0x65, 0x74, 0x61, 0x6e, 0x69, 0x61, 0x31, 0x0c, 0x30, 0x0a, 0x06, 
+			0x03, 0x55, 0x04, 0x0a, 0x0c, 0x03, 0x41, 0x52, 0x4d, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 
+			0x04, 0x0b, 0x0c, 0x03, 0x49, 0x4f, 0x54, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03, 
+			0x0c, 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 
+			0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 
+			0x31, 0x40, 0x61, 0x72, 0x6d, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 
+			0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 
+			0x03, 0x42, 0x00, 0x04, 0x41, 0xdf, 0x03, 0x36, 0x9c, 0xb3, 0xb2, 0x9e, 0x42, 0xbc, 0x48, 0x37, 
+			0x3c, 0x21, 0xc2, 0x99, 0xb1, 0x47, 0x1d, 0x96, 0x84, 0x28, 0xdb, 0x07, 0x30, 0xad, 0x69, 0x86, 
+			0x39, 0x10, 0x10, 0x52, 0xe9, 0x3a, 0xe5, 0x4e, 0xd3, 0x3f, 0xd3, 0x0d, 0xfd, 0x9f, 0xd9, 0x4b, 
+			0xcb, 0xa1, 0x81, 0xbe, 0x3f, 0xbe, 0x24, 0x68, 0xc3, 0xe9, 0x73, 0xbf, 0x34, 0xb7, 0xa0, 0x61, 
+			0x56, 0x96, 0xb5, 0x74, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 
+			0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xa0, 0xa6, 0x46, 0xaa, 0xef, 0x18, 0xa6, 0xa3, 
+			0x7b, 0x81, 0xdb, 0x36, 0xf7, 0x2c, 0xbc, 0xb4, 0x29, 0x7f, 0x3c, 0x35, 0xbd, 0x88, 0xba, 0xa6, 
+			0x98, 0x8f, 0x5f, 0x67, 0x35, 0xf8, 0xf2, 0x18, 0x02, 0x20, 0x65, 0x88, 0x9e, 0x5d, 0x5a, 0x84, 
+			0xb7, 0x42, 0x96, 0xe4, 0xb7, 0x7d, 0x9b, 0x5c, 0x01, 0xc3, 0x5a, 0x40, 0x11, 0x0d, 0xf5, 0xfe, 
+			0x44, 0x9c, 0xbb, 0xd2, 0x2f, 0x37, 0x38, 0xbe, 0x03, 0x56};
+
+//Certificate based on unsupported curve – secp521r1 
+const uint8_t testdata_x509_Curve512r1[641] = 
+		{ 
+			0x30, 0x82, 0x02, 0x7d, 0x30, 0x82, 0x01, 0xdf, 0x02, 0x09, 0x00, 0xe2, 0x16, 0x36, 0x0a, 0x28,
+			0x52, 0x3e, 0x81, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30,
+			0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x4b, 0x31,
+			0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x4b, 0x66, 0x61, 0x72, 0x2d, 0x6e,
+			0x65, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x4e,
+			0x65, 0x74, 0x61, 0x6e, 0x69, 0x61, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
+			0x03, 0x41, 0x52, 0x4d, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x03, 0x49,
+			0x4f, 0x54, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x06, 0x44, 0x65, 0x76,
+			0x69, 0x63, 0x65, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+			0x09, 0x01, 0x16, 0x10, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x31, 0x40, 0x61, 0x72, 0x6d,
+			0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x31, 0x30, 0x30, 0x31, 0x30, 0x38,
+			0x35, 0x36, 0x35, 0x31, 0x5a, 0x17, 0x0d, 0x32, 0x33, 0x30, 0x33, 0x32, 0x34, 0x30, 0x38, 0x35,
+			0x36, 0x35, 0x31, 0x5a, 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+			0x13, 0x02, 0x55, 0x4b, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x4b,
+			0x66, 0x61, 0x72, 0x2d, 0x6e, 0x65, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
+			0x04, 0x07, 0x0c, 0x07, 0x4e, 0x65, 0x74, 0x61, 0x6e, 0x69, 0x61, 0x31, 0x0c, 0x30, 0x0a, 0x06,
+			0x03, 0x55, 0x04, 0x0a, 0x0c, 0x03, 0x41, 0x52, 0x4d, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55,
+			0x04, 0x0b, 0x0c, 0x03, 0x49, 0x4f, 0x54, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03,
+			0x0c, 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86,
+			0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30,
+			0x31, 0x40, 0x61, 0x72, 0x6d, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x81, 0x9b, 0x30, 0x10, 0x06, 0x07,
+			0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, 0x03, 0x81,
+			0x86, 0x00, 0x04, 0x00, 0xf6, 0x6f, 0x0f, 0xbe, 0x33, 0x95, 0xa3, 0xd1, 0x00, 0x47, 0x27, 0xcf,
+			0xd6, 0x3d, 0x0b, 0x69, 0x77, 0x40, 0xba, 0xaa, 0x82, 0xf4, 0xc3, 0x81, 0x41, 0x2b, 0xbd, 0x7b,
+			0x2a, 0xf5, 0xd3, 0xf2, 0x09, 0x5a, 0x61, 0xb4, 0x5d, 0x6e, 0x32, 0x10, 0x61, 0xfd, 0x6e, 0x5a,
+			0x74, 0x89, 0xad, 0xba, 0x23, 0x92, 0x33, 0x37, 0xa0, 0x4f, 0x98, 0x30, 0x4d, 0x8b, 0xae, 0xbf,
+			0x5f, 0x49, 0x56, 0x17, 0x69, 0x00, 0x37, 0x1b, 0xde, 0xa0, 0x11, 0x38, 0x17, 0xb5, 0x15, 0x61,
+			0xbd, 0xa1, 0xd8, 0x8d, 0x71, 0x48, 0x27, 0x4d, 0xbe, 0x60, 0x74, 0x3a, 0xd1, 0xe1, 0xff, 0xea,
+			0x0a, 0xa2, 0x3d, 0xaa, 0x28, 0x39, 0x28, 0x32, 0xa7, 0x0c, 0x9d, 0xfa, 0x52, 0xc1, 0x2c, 0xba,
+			0xac, 0x0f, 0x42, 0xa2, 0xcc, 0x78, 0x01, 0x45, 0x11, 0x62, 0xcf, 0x4f, 0x87, 0xcb, 0xf1, 0xff,
+			0x2a, 0x1a, 0x30, 0xe9, 0x3d, 0x31, 0x59, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+			0x04, 0x03, 0x02, 0x03, 0x81, 0x8b, 0x00, 0x30, 0x81, 0x87, 0x02, 0x41, 0x31, 0x73, 0x8d, 0x4a,
+			0x28, 0x86, 0xa9, 0x06, 0xbd, 0x7f, 0xe8, 0x58, 0x43, 0xc2, 0xce, 0xd9, 0xdb, 0x75, 0xae, 0x42,
+			0x83, 0x98, 0x29, 0x28, 0x61, 0x02, 0xfc, 0x23, 0x54, 0xe3, 0xcd, 0x07, 0x6f, 0xdc, 0xa0, 0x2e,
+			0xdd, 0xd3, 0xc6, 0x2e, 0x11, 0xcc, 0xd9, 0x3c, 0xdf, 0x26, 0xd4, 0x66, 0xdb, 0x03, 0x9e, 0x79,
+			0x9a, 0x60, 0x8f, 0x1d, 0x52, 0x6e, 0x3d, 0x16, 0x2f, 0x7d, 0x86, 0x43, 0x98, 0x02, 0x42, 0x01,
+			0xaa, 0xf2, 0x7f, 0xad, 0xad, 0xaa, 0x16, 0x35, 0x66, 0xe7, 0x52, 0xcc, 0x60, 0xdd, 0x09, 0xae,
+			0x1b, 0x44, 0x33, 0xa1, 0x57, 0x3a, 0xa0, 0xc5, 0xe3, 0x08, 0x84, 0xa7, 0xe3, 0x59, 0xf3, 0x79,
+			0x9a, 0xbf, 0xcb, 0x26, 0x36, 0x45, 0x64, 0x4b, 0x92, 0xb8, 0xc7, 0x51, 0x14, 0x57, 0x94, 0x4c,
+			0x96, 0x59, 0x2a, 0x5f, 0xb1, 0x38, 0x84, 0xc3, 0x26, 0x51, 0x57, 0x64, 0x4e, 0x54, 0x30, 0x3e,
+			0x00};
+
+const unsigned char x509_TI[] =
+{
+		0x30, 0x82, 0x01, 0xc1, 0x30, 0x82, 0x01, 0x64, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01,
+		0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x3d,
+		0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x07, 0x49, 0x4f, 0x54, 0x5f, 0x50,
+		0x41, 0x4c, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x50, 0x41, 0x4c,
+		0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x31, 0x0e, 0x30,
+		0x0c, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x05, 0x49, 0x4f, 0x54, 0x42, 0x55, 0x30, 0x1e, 0x17,
+		0x0d, 0x31, 0x33, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d,
+		0x31, 0x35, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x3d, 0x31,
+		0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x07, 0x49, 0x4f, 0x54, 0x5f, 0x50, 0x41,
+		0x4c, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x50, 0x41, 0x4c, 0x31,
+		0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x31, 0x0e, 0x30, 0x0c,
+		0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x05, 0x49, 0x4f, 0x54, 0x42, 0x55, 0x30, 0x59, 0x30, 0x13,
+		0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+		0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x18, 0xf7, 0x26, 0xc6, 0x86, 0x30, 0xec, 0xed, 0xd6,
+		0xb4, 0x3a, 0xd3, 0x86, 0x7a, 0x49, 0xbb, 0xb3, 0x93, 0xee, 0x43, 0x56, 0x18, 0x71, 0x2a, 0x40,
+		0xda, 0xc8, 0x2c, 0x4a, 0xc6, 0x3d, 0x09, 0xfc, 0xe0, 0x84, 0x2f, 0x0d, 0xce, 0xf8, 0x17, 0xcf,
+		0x28, 0x8f, 0x4f, 0xb4, 0xea, 0xde, 0xf9, 0xe4, 0x9a, 0x16, 0xeb, 0x8c, 0x67, 0x02, 0xfd, 0x64,
+		0x7b, 0x62, 0x0e, 0x9b, 0x29, 0x05, 0x22, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x0f, 0x06, 0x03, 0x55,
+		0x1d, 0x13, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03,
+		0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x13, 0xde, 0xa2, 0x8b, 0x8d, 0x40, 0x1e, 0xd6, 0x62,
+		0xfd, 0x7e, 0x27, 0x53, 0xb8, 0x8f, 0x17, 0x18, 0x76, 0x33, 0x20, 0x30, 0x1f, 0x06, 0x03, 0x55,
+		0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x13, 0xde, 0xa2, 0x8b, 0x8d, 0x40, 0x1e, 0xd6,
+		0x62, 0xfd, 0x7e, 0x27, 0x53, 0xb8, 0x8f, 0x17, 0x18, 0x76, 0x33, 0x20, 0x30, 0x0c, 0x06, 0x08,
+		0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02,
+		0x21, 0x00, 0xb7, 0xbb, 0x7b, 0x05, 0x17, 0x5f, 0x74, 0x0a, 0x91, 0xd7, 0x95, 0x30, 0xa8, 0xb4,
+		0x47, 0x26, 0x2d, 0xc4, 0xbf, 0xb4, 0xba, 0x00, 0x54, 0x92, 0xcd, 0xb8, 0xb4, 0x42, 0x4b, 0x05,
+		0x95, 0xe6, 0x02, 0x21, 0x00, 0xdb, 0x61, 0x24, 0x78, 0xed, 0x54, 0xcd, 0x8e, 0xfa, 0x31, 0x21,
+		0x8b, 0xe7, 0x11, 0x7e, 0x6e, 0xe2, 0x17, 0x63, 0xbe, 0x31, 0x90, 0x2b, 0xf8, 0xd2, 0x11, 0x5d,
+		0x9d, 0x8d, 0x5a, 0xaa, 0xdd
+};
+
+const unsigned char x509_TI_PEM[] = "-----BEGIN CERTIFICATE-----\r\n"
+		"MIIFIzCCBAugAwIBAgIQVYyM7bV85U+m+zUfuEsiLzANBgkqhkiG9w0BAQUFADCB\r\n"
+		"tDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL\r\n"
+		"ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2Ug\r\n"
+		"YXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykxMDEuMCwGA1UEAxMl\r\n"
+		"VmVyaVNpZ24gQ2xhc3MgMyBDb2RlIFNpZ25pbmcgMjAxMCBDQTAeFw0xNDA0MTUw\r\n"
+		"MDAwMDBaFw0xNTA0MTYyMzU5NTlaMHQxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIEwVU\r\n"
+		"ZXhhczEPMA0GA1UEBxMGRGFsbGFzMRowGAYDVQQKFBFUZXhhcyBJbnN0cnVtZW50\r\n"
+		"czEMMAoGA1UECxQDV0NTMRowGAYDVQQDFBFUZXhhcyBJbnN0cnVtZW50czCCASIw\r\n"
+		"DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMuAIvJOnebITQe2qli+t6Juwoy7\r\n"
+		"I9qenavTt7D2cYsEBO+Oj/SLWjkieGPKek1Q+DIo66h3ZAYB9mDhxIAxY8bMmO61\r\n"
+		"SOwxtcjA7nLgoqacMi61ly5OmjDuTholKjCyFCYmun7YPiI4b0BRNwFIMxOjfKdc\r\n"
+		"9Jj1UCl7TH0DFsn1ly583NOlJey7AV5v4sijU5AWSR+JeaV/yFw1MPbY58ekjnS8\r\n"
+		"tv5K8r5k5D770jDOZ/nuLpVZ3oNvhP9uMb6abEcUcVnxHkPu8ovFa43T1FwAKYSF\r\n"
+		"4FAPpe4P9EQVUBJAupMt91J6iPWeiSjKYMYbd3dgNHNabsoT1gACAhCWwJkCAwEA\r\n"
+		"AaOCAW4wggFqMAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoG\r\n"
+		"CCsGAQUFBwMDMGYGA1UdIARfMF0wWwYLYIZIAYb4RQEHFwMwTDAjBggrBgEFBQcC\r\n"
+		"ARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIwGRoXaHR0cHM6\r\n"
+		"Ly9kLnN5bWNiLmNvbS9ycGEwHwYDVR0jBBgwFoAUz5mp6nsm9EvJjo/X8AUm7+PS\r\n"
+		"p50wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3NmLnN5bWNiLmNvbS9zZi5jcmww\r\n"
+		"VwYIKwYBBQUHAQEESzBJMB8GCCsGAQUFBzABhhNodHRwOi8vc2Yuc3ltY2QuY29t\r\n"
+		"MCYGCCsGAQUFBzAChhpodHRwOi8vc2Yuc3ltY2IuY29tL3NmLmNydDARBglghkgB\r\n"
+		"hvhCAQEEBAMCBBAwFgYKKwYBBAGCNwIBGwQIMAYBAQABAf8wDQYJKoZIhvcNAQEF\r\n"
+		"BQADggEBACKIttb6LKlpjDHUFo9BHdYw6qxbF3Ham5GPjAn+ofYqpv3KoF7L2Rc9\r\n"
+		"jhYDIA5IHmYAjDdHLUBx+DdzMP80cXcRIdBGgOFFw++rRboUi0yOpg47yD0AipNT\r\n"
+		"Q00rBdoeEzs3ERiPir20402OmFUBkCcwM85XaXh1hvOKDZaCEj/6vlK/Y6++y1QC\r\n"
+		"tQGm08HAAuEz4VsnE/mcVeuaVM8DqFInrp9mpCNiCCwdiG3TEC1UgACjxFmFk0UH\r\n"
+		"mrUNww35tofUjAoXIkcegm2d/ld8bZxludWG2sJRydVTAQe1jJJDg+N7IdyH/gv7\r\n"
+		"y8i1xf5goGEvMqLiYY5njLCSSpCeNqE=\r\n"
+		"-----END CERTIFICATE-----\r\n";
+
+const unsigned char x509_selfsign[] =
+{
+		0x30, 0x82, 0x01, 0x9a, 0x30, 0x82, 0x01, 0x3e, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01,
+		0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x2d,
+		0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x02, 0x43, 0x41, 0x31, 0x11, 0x30,
+		0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x6d, 0x62, 0x65, 0x64, 0x20, 0x54, 0x4c, 0x53,
+		0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x4b, 0x30, 0x1e, 0x17,
+		0x0d, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d,
+		0x33, 0x30, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x2d, 0x31,
+		0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x02, 0x43, 0x41, 0x31, 0x11, 0x30, 0x0f,
+		0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x6d, 0x62, 0x65, 0x64, 0x20, 0x54, 0x4c, 0x53, 0x31,
+		0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x4b, 0x30, 0x59, 0x30, 0x13,
+		0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+		0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xf7, 0xc6, 0x63, 0x68, 0x8d, 0x48, 0x3a, 0xcc, 0xeb,
+		0xc1, 0x01, 0xcb, 0xd5, 0xc9, 0xa9, 0xc8, 0x42, 0x62, 0x2e, 0xd0, 0xb2, 0x34, 0x6a, 0x9f, 0xc9,
+		0xce, 0xe0, 0x1c, 0x57, 0xc7, 0x0a, 0x62, 0x6e, 0x8e, 0x2e, 0xc5, 0x9f, 0xef, 0x8e, 0x04, 0x44,
+		0x7e, 0xf3, 0xd0, 0xe6, 0x92, 0xc9, 0x0a, 0x49, 0x72, 0x98, 0x7f, 0x73, 0x3e, 0xf6, 0x97, 0x70,
+		0x74, 0xb7, 0x9f, 0xe1, 0xb5, 0xef, 0xce, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55,
+		0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
+		0x14, 0x0f, 0xc6, 0x27, 0x51, 0xce, 0x06, 0x0b, 0x3b, 0xbd, 0xf1, 0xd1, 0x8e, 0x25, 0x6d, 0xcd,
+		0x12, 0x64, 0x8f, 0x73, 0x4d, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16,
+		0x80, 0x14, 0x0f, 0xc6, 0x27, 0x51, 0xce, 0x06, 0x0b, 0x3b, 0xbd, 0xf1, 0xd1, 0x8e, 0x25, 0x6d,
+		0xcd, 0x12, 0x64, 0x8f, 0x73, 0x4d, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04,
+		0x03, 0x02, 0x05, 0x00, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xf1, 0x6a, 0x24, 0x08,
+		0x99, 0xf1, 0xe0, 0x55, 0x4f, 0x0a, 0x52, 0x72, 0x68, 0x63, 0x6e, 0xec, 0x2f, 0x9d, 0x54, 0x61,
+		0x9d, 0x7f, 0xa3, 0x5d, 0xa5, 0x79, 0x69, 0xc2, 0xab, 0xcf, 0x0f, 0x48, 0x02, 0x20, 0x51, 0x41,
+		0x26, 0x4b, 0xdf, 0x1b, 0x5e, 0xda, 0xa4, 0x53, 0x8d, 0xe5, 0x92, 0xa6, 0x1b, 0x8a, 0x0d, 0x58,
+		0x59, 0x9e, 0x77, 0x99, 0xd6, 0x81, 0xf1, 0x5d, 0xcd, 0x28, 0xcc, 0x03, 0x75, 0x96
+};
+
+const unsigned char x509_verify_ca[] =
+{
+		0x30, 0x82, 0x01, 0xf6, 0x30, 0x82, 0x01, 0x9c, 0x02, 0x09, 0x00, 0xe3, 0x22, 0x71, 0x24, 0xb8,
+		0xa6, 0x9b, 0xce, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30,
+		0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x4b, 0x31,
+		0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x4b, 0x66, 0x61, 0x72, 0x2d, 0x6e,
+		0x65, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x4e,
+		0x65, 0x74, 0x61, 0x6e, 0x69, 0x61, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
+		0x03, 0x41, 0x52, 0x4d, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x03, 0x49,
+		0x4f, 0x54, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x06, 0x44, 0x65, 0x76,
+		0x69, 0x63, 0x65, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+		0x09, 0x01, 0x16, 0x10, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x31, 0x40, 0x61, 0x72, 0x6d,
+		0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x33, 0x30, 0x31, 0x31, 0x37,
+		0x34, 0x33, 0x35, 0x33, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x38, 0x32, 0x32, 0x31, 0x37, 0x34,
+		0x33, 0x35, 0x33, 0x5a, 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+		0x13, 0x02, 0x55, 0x4b, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x4b,
+		0x66, 0x61, 0x72, 0x2d, 0x6e, 0x65, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
+		0x04, 0x07, 0x0c, 0x07, 0x4e, 0x65, 0x74, 0x61, 0x6e, 0x69, 0x61, 0x31, 0x0c, 0x30, 0x0a, 0x06,
+		0x03, 0x55, 0x04, 0x0a, 0x0c, 0x03, 0x41, 0x52, 0x4d, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55,
+		0x04, 0x0b, 0x0c, 0x03, 0x49, 0x4f, 0x54, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03,
+		0x0c, 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86,
+		0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30,
+		0x31, 0x40, 0x61, 0x72, 0x6d, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a,
+		0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
+		0x03, 0x42, 0x00, 0x04, 0x24, 0xb5, 0x1b, 0xaf, 0x82, 0xd6, 0xc6, 0xc4, 0x66, 0xba, 0xe7, 0xdf,
+		0x41, 0xd2, 0x03, 0xdb, 0xbf, 0x49, 0xf0, 0x99, 0x66, 0xf1, 0xe1, 0x15, 0x37, 0x94, 0x66, 0x2b,
+		0x22, 0x4c, 0x8e, 0xc6, 0xd4, 0x5e, 0x6f, 0x1a, 0xdb, 0x44, 0xe5, 0x06, 0xd8, 0x34, 0xad, 0xf2,
+		0x1e, 0x92, 0x23, 0xd8, 0xd4, 0xd2, 0x01, 0x6a, 0x6e, 0x3c, 0x09, 0x7b, 0x5b, 0xff, 0x0e, 0x6f,
+		0xb4, 0x28, 0xe6, 0x28, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
+		0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xae, 0xaf, 0x9e, 0xfb, 0xea, 0x53, 0xe7, 0xe3,
+		0xd5, 0xe0, 0x90, 0x87, 0x15, 0xaf, 0x48, 0x9f, 0x50, 0x2c, 0x44, 0x4d, 0x2a, 0x68, 0x38, 0xa0,
+		0x3c, 0x09, 0xbc, 0x32, 0xb8, 0x78, 0xcf, 0xfa, 0x02, 0x20, 0x0c, 0x0d, 0xc8, 0xda, 0xcd, 0x09,
+		0x7a, 0xa9, 0x6d, 0x18, 0x6c, 0xc1, 0x58, 0x1a, 0xec, 0x9a, 0x8b, 0x0d, 0x8a, 0xc4, 0xea, 0x9d,
+		0x49, 0x5f, 0xa1, 0x9e, 0xcc, 0xcf, 0xbe, 0xb5, 0x25, 0xfd
+};
+
+const unsigned char x509_verify_cert[] =
+{
+		0x30, 0x82, 0x01, 0xf2, 0x30, 0x82, 0x01, 0x98, 0x02, 0x01, 0x03, 0x30, 0x0a, 0x06, 0x08, 0x2a,
+		0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+		0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x4b, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+		0x0c, 0x0a, 0x4b, 0x66, 0x61, 0x72, 0x2d, 0x6e, 0x65, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e,
+		0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x4e, 0x65, 0x74, 0x61, 0x6e, 0x69, 0x61, 0x31, 0x0c,
+		0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x03, 0x41, 0x52, 0x4d, 0x31, 0x0c, 0x30, 0x0a,
+		0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x03, 0x49, 0x4f, 0x54, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03,
+		0x55, 0x04, 0x03, 0x0c, 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x31, 0x1f, 0x30, 0x1d, 0x06,
+		0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x64, 0x65, 0x76, 0x69,
+		0x63, 0x65, 0x30, 0x31, 0x40, 0x61, 0x72, 0x6d, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d,
+		0x31, 0x37, 0x30, 0x33, 0x30, 0x31, 0x31, 0x37, 0x34, 0x33, 0x35, 0x33, 0x5a, 0x17, 0x0d, 0x31,
+		0x37, 0x30, 0x33, 0x33, 0x31, 0x31, 0x37, 0x34, 0x33, 0x35, 0x33, 0x5a, 0x30, 0x81, 0x86, 0x31,
+		0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x4b, 0x31, 0x13, 0x30, 0x11,
+		0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x4b, 0x66, 0x61, 0x72, 0x2d, 0x6e, 0x65, 0x74, 0x65,
+		0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x4e, 0x65, 0x74, 0x61,
+		0x6e, 0x69, 0x61, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x03, 0x41, 0x52,
+		0x4d, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x03, 0x49, 0x4f, 0x54, 0x31,
+		0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0a, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x20,
+		0x43, 0x45, 0x52, 0x54, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+		0x01, 0x09, 0x01, 0x16, 0x10, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x31, 0x40, 0x61, 0x72,
+		0x6d, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+		0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04,
+		0x6b, 0x28, 0x07, 0xf4, 0x9a, 0xf7, 0x19, 0x2b, 0x3f, 0x6a, 0xf4, 0xa1, 0xcb, 0x5f, 0x21, 0x18,
+		0x46, 0xef, 0xcf, 0x9c, 0xbd, 0x31, 0x89, 0xac, 0x9c, 0xb6, 0xe4, 0x2c, 0xb9, 0x81, 0xae, 0x6d,
+		0xb6, 0x57, 0x88, 0x18, 0xde, 0x06, 0x12, 0xe4, 0xfe, 0x63, 0xea, 0x13, 0x8b, 0xf7, 0x76, 0xe3,
+		0x97, 0xc9, 0xbd, 0x47, 0xbf, 0x50, 0x92, 0xba, 0x1e, 0x3e, 0x3b, 0x8d, 0x6e, 0x8f, 0x86, 0xfd,
+		0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30,
+		0x45, 0x02, 0x20, 0x30, 0xc2, 0xd4, 0xbd, 0xa9, 0x5d, 0xe1, 0xd0, 0xc5, 0xcb, 0xb5, 0xb3, 0x31,
+		0x8a, 0xad, 0x7a, 0xab, 0xc7, 0x85, 0xf2, 0x1a, 0x0a, 0x4f, 0xd1, 0x63, 0x33, 0x05, 0x20, 0x1f,
+		0xb4, 0xd6, 0x6e, 0x02, 0x21, 0x00, 0x8c, 0xcd, 0x36, 0x73, 0x9c, 0xb7, 0xc2, 0xee, 0xf3, 0x0a,
+		0xbf, 0x4f, 0xd3, 0x95, 0x08, 0xa6, 0xcd, 0xdd, 0x5b, 0x78, 0x8f, 0x83, 0x90, 0xef, 0x2a, 0x8a,
+		0x27, 0x0d, 0x73, 0x0b, 0xa0, 0xfa
+};
+
+unsigned char cert_sha224_der[] = {
+  		0x30, 0x82, 0x01, 0xf5, 0x30, 0x82, 0x01, 0x9c, 0x02, 0x09, 0x00, 0x9c, 0xe8, 0x23, 0xd2, 0x32,
+		0xa3, 0x6a, 0x44, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x01, 0x30, 
+		0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x4b, 0x31, 
+		0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x4b, 0x66, 0x61, 0x72, 0x2d, 0x6e,
+		0x65, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x4e,
+		0x65, 0x74, 0x61, 0x6e, 0x69, 0x61, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
+		0x03, 0x41, 0x52, 0x4d, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x03, 0x49,
+		0x4f, 0x54, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x06, 0x44, 0x65, 0x76,
+		0x69, 0x63, 0x65, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+		0x09, 0x01, 0x16, 0x10, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30, 0x31, 0x40, 0x61, 0x72, 0x6d,
+		0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x39, 0x31, 0x30, 0x31, 0x34,
+		0x30, 0x33, 0x33, 0x33, 0x5a, 0x17, 0x0d, 0x32, 0x33, 0x30, 0x33, 0x30, 0x33, 0x31, 0x34, 0x30,
+		0x33, 0x33, 0x33, 0x5a, 0x30, 0x81, 0x82, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+		0x13, 0x02, 0x55, 0x4b, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x4b,
+		0x66, 0x61, 0x72, 0x2d, 0x6e, 0x65, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
+		0x04, 0x07, 0x0c, 0x07, 0x4e, 0x65, 0x74, 0x61, 0x6e, 0x69, 0x61, 0x31, 0x0c, 0x30, 0x0a, 0x06,
+		0x03, 0x55, 0x04, 0x0a, 0x0c, 0x03, 0x41, 0x52, 0x4d, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55,
+		0x04, 0x0b, 0x0c, 0x03, 0x49, 0x4f, 0x54, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x03,
+		0x0c, 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x09, 0x2a, 0x86,
+		0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x10, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x30,
+		0x31, 0x40, 0x61, 0x72, 0x6d, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a,
+		0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
+		0x03, 0x42, 0x00, 0x04, 0x41, 0xdf, 0x03, 0x36, 0x9c, 0xb3, 0xb2, 0x9e, 0x42, 0xbc, 0x48, 0x37,
+		0x3c, 0x21, 0xc2, 0x99, 0xb1, 0x47, 0x1d, 0x96, 0x84, 0x28, 0xdb, 0x07, 0x30, 0xad, 0x69, 0x86,
+		0x39, 0x10, 0x10, 0x52, 0xe9, 0x3a, 0xe5, 0x4e, 0xd3, 0x3f, 0xd3, 0x0d, 0xfd, 0x9f, 0xd9, 0x4b,
+		0xcb, 0xa1, 0x81, 0xbe, 0x3f, 0xbe, 0x24, 0x68, 0xc3, 0xe9, 0x73, 0xbf, 0x34, 0xb7, 0xa0, 0x61,
+		0x56, 0x96, 0xb5, 0x74, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x01,
+		0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x15, 0x93, 0xc8, 0xc3, 0x11, 0x3d, 0x66, 0x90, 0xf4,
+		0xff, 0x9a, 0xb2, 0x1f, 0x97, 0x98, 0xb4, 0xde, 0xec, 0xef, 0x3a, 0xf1, 0x70, 0xd5, 0x04, 0x3b,
+		0x64, 0x3b, 0x66, 0x5a, 0x31, 0x86, 0x6e, 0x02, 0x20, 0x37, 0xf7, 0xcf, 0x21, 0x30, 0xe7, 0xf8,
+		0xff, 0x0c, 0x2a, 0x4a, 0xa7, 0xc3, 0x45, 0xee, 0x90, 0xd8, 0xda, 0xaf, 0x57, 0x9c, 0x32, 0xbd,
+		0x2c, 0x4f, 0x3f, 0x3b, 0x43, 0x97, 0x18, 0xaa, 0x3d
+};
+
+typedef struct palX509VertifyTestVector
+{
+	const unsigned char* ca;
+	size_t ca_size;
+	const unsigned char* crt;
+	size_t crt_size;
+	palStatus_t result;
+}palX509VertifyTestVector_t;
+
+#if (PAL_USE_SECURE_TIME == 1)
+
+static const palX509VertifyTestVector_t x509_verify_data[] =
+{
+		{ x509_selfsign, sizeof(x509_selfsign), x509_selfsign, sizeof(x509_selfsign), 0 },
+		{ cert_sha224_der, sizeof(cert_sha224_der), cert_sha224_der, sizeof(cert_sha224_der), 0},
+		{ NULL, 0, x509_selfsign, sizeof(x509_selfsign), PAL_ERR_X509_BADCERT_NOT_TRUSTED },
+		{ x509_verify_ca, sizeof(x509_verify_ca), x509_verify_cert, sizeof(x509_verify_cert), PAL_ERR_X509_BADCERT_EXPIRED },
+		{ x509_verify_cert, sizeof(x509_verify_cert), x509_verify_ca, sizeof(x509_verify_ca), PAL_ERR_X509_BADCERT_NOT_TRUSTED }
+		//should simulate one of the cert verify tests to be future error
+};
+
+#else
+
+static const palX509VertifyTestVector_t x509_verify_data[] = 
+{
+		{ x509_selfsign, sizeof(x509_selfsign), x509_selfsign, sizeof(x509_selfsign), 0 },
+		{ cert_sha224_der, sizeof(cert_sha224_der), cert_sha224_der, sizeof(cert_sha224_der),0},
+		{ NULL, 0, x509_selfsign, sizeof(x509_selfsign), PAL_ERR_X509_BADCERT_NOT_TRUSTED },
+		{ x509_verify_ca, sizeof(x509_verify_ca), x509_verify_cert, sizeof(x509_verify_cert), 0 },
+		{ x509_verify_cert, sizeof(x509_verify_cert), x509_verify_ca, sizeof(x509_verify_ca), PAL_ERR_X509_BADCERT_NOT_TRUSTED }
+};
+
+
+#endif //PAL_USE_SECURE_TIME
+
+
+typedef struct palMdHMACTestVector
+{
+	const unsigned char key[131];
+	const unsigned char input[152];
+	unsigned char output[32];
+	size_t keyLen;
+	size_t inputLen;
+	size_t outputLen;
+} palMdHMACTestVector_t;
+
+const palMdHMACTestVector_t mdHMACVector[7] =
+{
+		{
+				{
+						0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+						0x0b, 0x0b, 0x0b, 0x0b
+				},
+				{
+						0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65
+				},
+				{
+						0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
+						0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7,	0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7
+				}, 20, 8, 32
+		},
+		{
+				{
+						0x4a, 0x65, 0x66, 0x65
+				},
+				{
+						0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
+						0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x3f
+				},
+				{
+						0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
+						0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,	0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43
+				}, 4, 28, 32
+		},
+		{
+				{
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa
+				},
+				{
+						0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+						0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+						0xdd, 0xdd, 0xdd, 0xdd,	0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+						0xdd, 0xdd
+				},
+				{
+						0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb,	0xd0, 0x91, 0x81, 0xa7,
+						0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22,	0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe
+				}, 20, 50, 32
+		},
+		{
+				{
+						0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+						0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19
+				},
+				{
+						0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+						0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+						0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
+						0xcd, 0xcd
+				},
+				{
+						0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a,
+						0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b
+				}, 25, 50, 32
+		},
+		{
+				{
+						0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+						0x0c, 0x0c, 0x0c, 0x0c
+				},
+				{
+						0x54, 0x65, 0x73, 0x74, 0x20, 0x57, 0x69, 0x74, 0x68, 0x20, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61,
+						0x74, 0x69, 0x6f, 0x6e
+				},
+				{
+						0xa3, 0xb6, 0x16, 0x74, 0x73, 0x10, 0x0e, 0xe0, 0x6e, 0x0c, 0x79, 0x6c, 0x29, 0x55, 0x55, 0x2b
+				}, 20, 20, 16
+		},
+		{
+				{
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa
+				},
+
+				{
+						0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,
+						0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,
+						0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20, 0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
+						0x20, 0x46, 0x69, 0x72, 0x73, 0x74
+				},
+
+				{
+						0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
+						0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54
+				}, 131, 54, 32
+		},
+		{
+				{
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+						0xaa, 0xaa, 0xaa
+				},
+				{
+						0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75,
+						0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68,
+						0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65,
+						0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74,
+						0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64,
+						0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65,
+						0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20,
+						0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65,
+						0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c,
+						0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e
+				},
+				{
+						0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44,
+						0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2
+				}, 131, 152, 32
+		}
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Crypto/pal_crypto_test_runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "unity.h"
+#include "unity_fixture.h"
+
+
+// PAL Socket API tests
+TEST_GROUP_RUNNER(pal_crypto)
+{
+	// AES cryptography
+    RUN_TEST_CASE(pal_crypto, AES_CTR);
+    RUN_TEST_CASE(pal_crypto, AES_ECB);
+    RUN_TEST_CASE(pal_crypto, AES_CCM);
+
+    //Hashing using SHA256
+    RUN_TEST_CASE(pal_crypto, SHA256);
+    RUN_TEST_CASE(pal_crypto, md);
+
+    //Random Number Generation
+    RUN_TEST_CASE(pal_crypto, CTR_DRBG);
+
+    //CMAC
+    RUN_TEST_CASE(pal_crypto, CMAC_one_shot);
+    RUN_TEST_CASE(pal_crypto, CMAC_Iterative);
+
+    //MD HMAC SHA256
+    RUN_TEST_CASE(pal_crypto, HMAC_SHA256_one_shot);
+
+    //Certificate
+    RUN_TEST_CASE(pal_crypto, ASN1);
+    RUN_TEST_CASE(pal_crypto, X509_Parse);
+    RUN_TEST_CASE(pal_crypto, X509_ReadAttributes);
+    RUN_TEST_CASE(pal_crypto, X509_Verify);
+
+    //Elliptic Curves
+    RUN_TEST_CASE(pal_crypto, ECKey_checkKey);
+    RUN_TEST_CASE(pal_crypto, ECKey_parseKey);
+#if 0
+    //Not required for R1.2
+    RUN_TEST_CASE(pal_crypto, CSR);
+#endif //0
+    RUN_TEST_CASE(pal_crypto, X509_tbs_hash);
+
+    RUN_TEST_CASE(pal_crypto, ECKey_GenerateKeys);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/FileSystem/pal_fileSystem_test.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1280 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal.h"
+#include "unity.h"
+#include "unity_fixture.h"
+
+
+#define TEST_DIR "dir1"
+#define TEST_DIR2 "dir2"
+#define TEST_WORKING_DIR "work1"
+#define TEST_DIR_FILE "dir1/test.txt"
+#define TEST_NUMBER_OF_FILE_TO_CREATE 20
+#define TEST_BUFFER_SIZE 100
+#define TEST_BUFFER_SMALL_SIZE 17
+//#define TEST_BYTES_TO_WRITE 300*4
+#define TEST_BYTES_TO_WRITE 100
+#define TEST_FILE_NAME "%s/test_f%d"
+#define BUFFER_TEST_SIZE 1123
+
+#if (false == PAL_PRIMARY_PARTITION_PRIVATE)
+    #define PAL_TEST_PRIMARY_PATH "/pri"
+#else
+    #define PAL_TEST_PRIMARY_PATH ""
+#endif
+
+#if (false == PAL_SECONDARY_PARTITION_PRIVATE)
+    #define PAL_TEST_SECONDARY_PATH "/sec"
+#else
+    #define PAL_TEST_SECONDARY_PATH ""
+#endif
+
+//out should in length be PAL_MAX_FILE_AND_FOLDER_LENGTH
+static char* addRootToPath(const char* in, char* out,pal_fsStorageID_t id)
+{
+    char root[PAL_MAX_FILE_AND_FOLDER_LENGTH] = { 0 };
+    size_t len = 0;
+    palStatus_t status;
+
+    memset(out,0,PAL_MAX_FILE_AND_FOLDER_LENGTH);
+    status = pal_fsGetMountPoint(id, PAL_MAX_FILE_AND_FOLDER_LENGTH, root);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    strncat(out, root, PAL_MAX_FILE_AND_FOLDER_LENGTH-1); //-1 for null terminator space
+    len = strlen(out);
+    if (PAL_FS_PARTITION_PRIMARY == id)
+    {
+        strncat(out, PAL_TEST_PRIMARY_PATH, PAL_MAX_FILE_AND_FOLDER_LENGTH - len);
+    }
+    else
+    {
+        strncat(out, PAL_TEST_SECONDARY_PATH, PAL_MAX_FILE_AND_FOLDER_LENGTH - len);
+    }
+    len = strlen(out);
+    if (*in != '\0')
+    {
+        strncat(out,"/",PAL_MAX_FILE_AND_FOLDER_LENGTH - len);
+        strncat(out,in,PAL_MAX_FILE_AND_FOLDER_LENGTH -len -1);
+    }
+    return(out);
+}
+
+
+
+PAL_PRIVATE uint8_t *bufferTest = NULL;
+PAL_PRIVATE uint8_t *bufferTest2  = NULL;
+
+PAL_PRIVATE palFileDescriptor_t g_fd1 = 0;
+PAL_PRIVATE palFileDescriptor_t g_fd2 = 0;
+
+PAL_PRIVATE palStatus_t pal_fsClearAndInitialyze(pal_fsStorageID_t id)
+{
+    palStatus_t status = PAL_SUCCESS;
+
+    if (pal_fsIsPrivatePartition(id))
+    {
+        status = pal_fsFormat(id);
+    }
+    else
+    {
+        char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+        status = pal_fsRmFiles(addRootToPath("",buffer,id));
+    }
+    return(status);
+}
+
+/*! \brief This function compare two files
+*
+* @param[in]    *pathCmp1 - pointer to the null-terminated string that specifies the first filename to be compare
+* @param[in]    *pathCmp2 - pointer to the null-terminated string that specifies the second filename to be compare
+*
+* \return PAL_SUCCESS upon successful operation.\n
+*
+*/
+PAL_PRIVATE palStatus_t fileSystemCompareUtil(const char * pathCmp1, const char * pathCmp2)
+{
+    palStatus_t status = PAL_SUCCESS;
+
+    char bufferCmp1[TEST_BUFFER_SIZE];
+    char bufferCmp2[TEST_BUFFER_SIZE];
+    size_t numOfBytesCmp1 = 0;
+    size_t numOfBytesCmp2 = 0;
+    palFileDescriptor_t  fdCmp1 = 0;
+    palFileDescriptor_t  fdCmp2 = 0;
+
+    status =  pal_fsFopen(pathCmp1, PAL_FS_FLAG_READONLY, &fdCmp1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+    status =  pal_fsFopen(pathCmp2, PAL_FS_FLAG_READONLY, &fdCmp2);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+    while(true)
+    {
+
+        status  = pal_fsFread(&fdCmp1, bufferCmp1, TEST_BUFFER_SIZE, &numOfBytesCmp1);
+        TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+        status  = pal_fsFread(&fdCmp2, bufferCmp2, TEST_BUFFER_SIZE, &numOfBytesCmp2);
+        TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+        if ((numOfBytesCmp2 == 0) && (numOfBytesCmp1 == 0))
+        {//End of file reached
+            break;
+        }
+
+        TEST_ASSERT_EQUAL(numOfBytesCmp1, numOfBytesCmp2);
+        TEST_ASSERT_EQUAL_MEMORY(bufferCmp1, bufferCmp2, numOfBytesCmp1);
+    }
+
+    status =  pal_fsFclose(&fdCmp1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+    status =  pal_fsFclose(&fdCmp2);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+    return status;
+}
+
+TEST_GROUP(pal_fileSystem);
+
+TEST_SETUP(pal_fileSystem)
+{
+
+    pal_init();
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+
+    pal_fsRmFiles(addRootToPath(TEST_DIR,buffer,PAL_FS_PARTITION_PRIMARY));//Remove all files in the testing DIRECTORY
+    pal_fsRmDir(addRootToPath(TEST_DIR,buffer,PAL_FS_PARTITION_PRIMARY)); //Delete Directory if exist
+    pal_fsRmFiles(addRootToPath(TEST_WORKING_DIR,buffer,PAL_FS_PARTITION_PRIMARY));//Remove all files in the testing DIRECTORY
+    pal_fsRmDir(addRootToPath(TEST_WORKING_DIR,buffer,PAL_FS_PARTITION_PRIMARY)); //Delete Directory if exist
+    pal_fsRmFiles(addRootToPath(TEST_DIR2,buffer,PAL_FS_PARTITION_PRIMARY));//Remove all files in the testing DIRECTORY
+    pal_fsRmDir(addRootToPath(TEST_DIR2,buffer,PAL_FS_PARTITION_PRIMARY)); //Delete Directory if exist
+
+
+    pal_fsRmFiles(addRootToPath(TEST_DIR,buffer,PAL_FS_PARTITION_SECONDARY));//Remove all files in the testing DIRECTORY
+    pal_fsRmDir(addRootToPath(TEST_DIR,buffer,PAL_FS_PARTITION_SECONDARY)); //Delete Directory if exist
+    pal_fsRmFiles(addRootToPath(TEST_WORKING_DIR,buffer,PAL_FS_PARTITION_SECONDARY));//Remove all files in the testing DIRECTORY
+    pal_fsRmDir(addRootToPath(TEST_WORKING_DIR,buffer,PAL_FS_PARTITION_SECONDARY)); //Delete Directory if exist
+    pal_fsRmFiles(addRootToPath(TEST_DIR2,buffer,PAL_FS_PARTITION_SECONDARY));//Remove all files in the testing DIRECTORY
+    pal_fsRmDir(addRootToPath(TEST_DIR2,buffer,PAL_FS_PARTITION_SECONDARY)); //Delete Directory if exist
+
+    g_fd1 = 0;
+    g_fd2 = 0;
+    bufferTest = NULL;
+    bufferTest2 = NULL;
+    if(!pal_fsIsPrivatePartition(PAL_FS_PARTITION_PRIMARY))
+    {
+
+        addRootToPath("",buffer,PAL_FS_PARTITION_PRIMARY);
+        pal_fsMkDir(buffer);
+    }
+    if(!pal_fsIsPrivatePartition(PAL_FS_PARTITION_SECONDARY))
+    {
+        addRootToPath("",buffer,PAL_FS_PARTITION_SECONDARY);
+        pal_fsMkDir(buffer);
+    }
+}
+
+TEST_TEAR_DOWN(pal_fileSystem)
+{
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    if (g_fd1) 
+    {
+        pal_fsFclose(&g_fd1);
+    }
+    if (g_fd2) 
+    {
+        pal_fsFclose(&g_fd2);
+    }
+    g_fd1 = 0;
+    g_fd2 = 0;
+
+    if (bufferTest != NULL)
+    {
+        free(bufferTest);
+        bufferTest = NULL;
+    }
+    if (bufferTest2 != NULL)
+    {
+        free(bufferTest2);
+        bufferTest2 = NULL;
+    }
+    pal_fsClearAndInitialyze(PAL_FS_PARTITION_PRIMARY);
+    pal_fsClearAndInitialyze(PAL_FS_PARTITION_SECONDARY);
+
+    if(!pal_fsIsPrivatePartition(PAL_FS_PARTITION_PRIMARY))
+    {
+
+        addRootToPath("",buffer,PAL_FS_PARTITION_PRIMARY);
+        pal_fsRmDir(buffer);
+    }
+    if(!pal_fsIsPrivatePartition(PAL_FS_PARTITION_SECONDARY))
+    {
+        addRootToPath("",buffer,PAL_FS_PARTITION_SECONDARY);
+        pal_fsRmDir(buffer);
+    }
+    pal_destroy();
+
+}
+
+/*! \brief /b SDFormat function tests formatting an SD card.
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | create TEST_DIR with pal_fsMkDir                                                | PAL_SUCCESS |
+* | 2 | create TEST_DIR_FILE file with pal_fsOpen                                       | PAL_SUCCESS |
+* | 3 | close file TEST_DIR_FILE with pal_fsClose                                       | PAL_SUCCESS |
+* | 4 | Format SD card with pal_FormatSDPartition                                       | PAL_SUCCESS |
+* | 5 | TEST_DIR_FILE should not exist after format                                     | PAL_ERR_FS_NO_FILE |
+* | 6 | create TEST_DIR with pal_fsMkDir                                                | PAL_SUCCESS |
+*/
+void SDFormat_1Partition()
+{
+    palStatus_t status = PAL_SUCCESS;
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+
+    /*#1*/
+    status = pal_fsMkDir(addRootToPath(TEST_DIR,buffer,PAL_FS_PARTITION_PRIMARY)); //Create Directory
+    if (PAL_SUCCESS == status)
+    {
+        /*#2*/
+        status = pal_fsFopen(addRootToPath(TEST_DIR_FILE,buffer,PAL_FS_PARTITION_PRIMARY), PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd1);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        /*#3*/
+        status = pal_fsFclose(&g_fd1);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+
+
+    /*#4*/
+    status = pal_fsClearAndInitialyze(PAL_FS_PARTITION_PRIMARY); //Format SD
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+    /*#5*/
+    status = pal_fsFopen(addRootToPath(TEST_DIR_FILE,buffer,PAL_FS_PARTITION_PRIMARY), PAL_FS_FLAG_READONLY, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_ERR_FS_NO_FILE, status);    //Failed all files where deleted in previous step
+    
+    status = pal_fsClearAndInitialyze(PAL_FS_PARTITION_SECONDARY); //Format SD
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+
+    /*#6*/
+    status = pal_fsMkDir(addRootToPath(TEST_DIR,buffer,PAL_FS_PARTITION_PRIMARY)); //Create Directory
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+}
+
+/*! \brief /b SDFormat function tests formatting an SD card.
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | create TEST_DIR with pal_fsMkDir primary partition                              | PAL_SUCCESS |
+* | 2 | create TEST_DIR_FILE file with pal_fsOpen primary partition                     | PAL_SUCCESS |
+* | 3 | close file TEST_DIR_FILE with pal_fsClose                                       | PAL_SUCCESS |
+* | 4 | create TEST_DIR with pal_fsMkDir secondary partition                            | PAL_SUCCESS |
+* | 5 | create TEST_DIR_FILE file with pal_fsOpen secondary partition                   | PAL_SUCCESS |
+* | 6 | close file TEST_DIR_FILE with pal_fsClose                                       | PAL_SUCCESS |
+* | 7 | Format SD card primary partition with pal_FormatSDPartition                     | PAL_SUCCESS |
+* | 8 | TEST_DIR_FILE in primary should not exist after format                          | PAL_ERR_FS_NO_FILE |
+* | 9 | TEST_DIR_FILE in secondary should  exist after format                           | PAL_SUCCESS |
+* | 10| Format SD card secondary partition with pal_FormatSDPartition                   | PAL_SUCCESS |
+* | 11| TEST_DIR_FILE in secondary should not exist after format                        | PAL_ERR_FS_NO_FILE |
+* | 12| create TEST_DIR with pal_fsMkDir in primary partition                           | PAL_SUCCESS |
+* | 13| create TEST_DIR with pal_fsMkDir in secondary partition                         | PAL_SUCCESS |
+*/
+void SDFormat_2Partition()
+{
+    palStatus_t status = PAL_SUCCESS;
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+
+    /*#1*/
+    status = pal_fsMkDir(addRootToPath(TEST_DIR,buffer,PAL_FS_PARTITION_PRIMARY)); //Create Directory
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_fsFopen(addRootToPath(TEST_DIR_FILE,buffer,PAL_FS_PARTITION_PRIMARY), PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#3*/
+    status = pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#4*/
+    status = pal_fsMkDir(addRootToPath(TEST_DIR,buffer,PAL_FS_PARTITION_SECONDARY)); //Create Directory
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#5*/
+    status = pal_fsFopen(addRootToPath(TEST_DIR_FILE,buffer,PAL_FS_PARTITION_SECONDARY), PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#6*/
+    status = pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+
+    /*#7*/
+    status = pal_fsClearAndInitialyze(PAL_FS_PARTITION_PRIMARY); //Format SD
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#8*/
+    status = pal_fsFopen(addRootToPath(TEST_DIR_FILE,buffer,PAL_FS_PARTITION_PRIMARY), PAL_FS_FLAG_READONLY, &g_fd1);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_FS_NO_FILE, status);    //Failed all files where deleted in previous step
+
+    /*#9*/
+    status = pal_fsFopen(addRootToPath(TEST_DIR_FILE,buffer,PAL_FS_PARTITION_SECONDARY), PAL_FS_FLAG_READONLY, &g_fd1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);    //the file still exists in secondary
+
+    status = pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#10*/
+    status = pal_fsClearAndInitialyze(PAL_FS_PARTITION_SECONDARY); //Format SD
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#11*/
+    status = pal_fsFopen(addRootToPath(TEST_DIR_FILE,buffer,PAL_FS_PARTITION_SECONDARY), PAL_FS_FLAG_READONLY, &g_fd1);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_FS_NO_FILE, status);    //Failed all files where deleted in previous step
+
+    /*#12*/
+    status = pal_fsMkDir(addRootToPath(TEST_DIR,buffer,PAL_FS_PARTITION_PRIMARY)); //Create Directory
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#13*/
+    status = pal_fsMkDir(addRootToPath(TEST_DIR,buffer,PAL_FS_PARTITION_SECONDARY)); //Create Directory
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+}
+
+
+
+TEST(pal_fileSystem, SDFormat)
+{
+    SDFormat_2Partition();
+    SDFormat_1Partition();
+}
+
+
+/*! \brief /b directoryTests function Tests  root Directory commands
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | get root directory with pal_fsGetMountPoint                                    | PAL_SUCCESS |
+* | 2 | create TEST_WORKING_DIR with pal_fsMkDir                                       | PAL_SUCCESS |
+* | 3 | Change Root Directory to TEST_WORKING_DIR with     pal_fsSetMountPoint         | PAL_SUCCESS |
+* | 4 | create TEST_WORKING_DIR with pal_fsMkDir                                       | PAL_ERR_FS_NAME_ALREADY_EXIST |
+* | 5 | get root directory with pal_fsGetMountPoint                                    | PAL_SUCCESS |
+*/
+void rootDirectoryTests(pal_fsStorageID_t storageId)
+{
+    palStatus_t status = PAL_SUCCESS;
+    char getRootPath[TEST_BUFFER_SIZE] = { 0 };
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+/*#1*/
+    status = pal_fsGetMountPoint(storageId, TEST_BUFFER_SIZE, getRootPath); //Setting New working Directory
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+    
+/*#2*/
+    status = pal_fsMkDir(addRootToPath(TEST_WORKING_DIR,buffer,storageId)); //Create Directory
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#3*/
+    status = pal_fsSetMountPoint(storageId, addRootToPath(TEST_WORKING_DIR,buffer,storageId)); //Setting New working Directory
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#4*/
+    status = pal_fsMkDir(getRootPath); //should fail because already exits and path is absolute
+    TEST_ASSERT_EQUAL(PAL_ERR_FS_NAME_ALREADY_EXIST, status);
+
+/*#5*/
+    status = pal_fsGetMountPoint(storageId, TEST_BUFFER_SIZE, getRootPath); //Setting New working Directory
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+}
+
+
+TEST(pal_fileSystem, rootDirectoryTests)
+{
+
+    rootDirectoryTests(PAL_FS_PARTITION_PRIMARY);
+
+}
+
+
+/*! \brief /b directoryTests function Tests Directory commands
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | create TEST_DIR with pal_fsMkDir                                                | PAL_SUCCESS |
+* | 2 | create TEST_DIR with pal_fsMkDir                                                | PAL_ERR_FS_NAME_ALREADY_EXIST |
+* | 3 | Create File TEST_DIR_FILE With PAL_ERR_FS_READWRITEEXCLUSIVE with pal_fsFopen   | PAL_SUCCESS |
+* | 4 | Create File TEST_DIR_FILE With PAL_ERR_FS_READWRITEEXCLUSIVE with pal_fsFopen   | PAL_ERR_FS_NAME_ALREADY_EXIST |
+* | 5 | Close file with uninitialized file descriptor                                   | PAL_ERR_FS_BAD_FD |
+* | 6 | Close file with initialized file descriptor                                     | PAL_SUCCESS |
+* | 7 | Delete directory with  pal_fsRmDir (directory not empty)                        | PAL_ERR_FS_ERROR |
+* | 8 | Delete file TEST_DIR_FILE with pal_fsUnlink                                     | PAL_SUCCESS |
+* | 9 | Delete file TEST_DIR_FILE with pal_fsUnlink                                     | PAL_SUCCESS |
+* | 10 | Delete a folder which not exists with pal_fsUnlink                             | PAL_ERR_FS_NO_PATH |
+*
+*/
+void directoryTests(pal_fsStorageID_t storageId)
+{
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    char *pathToFile = NULL;
+    palStatus_t status = PAL_SUCCESS;
+
+/*#1*/
+    pathToFile = addRootToPath(TEST_DIR,buffer,storageId);
+    status = pal_fsMkDir(pathToFile); //Create Directory
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+/*#2*/
+    pathToFile = addRootToPath(TEST_DIR,buffer,storageId);
+    status = pal_fsMkDir(pathToFile); //Create same Directory Shall failed
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_FS_NAME_ALREADY_EXIST, status);
+
+/*#3*/
+    pathToFile = addRootToPath(TEST_DIR_FILE,buffer,storageId);
+    status =  pal_fsFopen(pathToFile, PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+/*#4*/
+    pathToFile = addRootToPath(TEST_DIR_FILE,buffer,storageId);
+    status =  pal_fsFopen(pathToFile, PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd2); // Failed open Exclusively and file already created
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_FS_NAME_ALREADY_EXIST, status);
+/*#5*/
+    #ifdef DEBUG
+        pal_fsFclose(&g_fd2);//Failed fd1 was not a valid File descriptor
+    #endif
+    //TEST_ASSERT_EQUAL(PAL_ERR_FS_BAD_FD, status); //TODO Pass on mbedOS
+
+/*#6*/    
+    status =  pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+/*#7*/
+    pathToFile = addRootToPath(TEST_DIR,buffer,storageId);
+    status = pal_fsRmDir(pathToFile); //Delete Directory Failed Directory not empty
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_FS_DIR_NOT_EMPTY, status);
+
+/*#8*/
+    pathToFile = addRootToPath(TEST_DIR_FILE,buffer,storageId);
+    status = pal_fsUnlink(pathToFile); //Delete the file in a directory
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+/*#9*/
+    pathToFile = addRootToPath(TEST_DIR,buffer,storageId);
+    status = pal_fsRmDir(pathToFile); //Delete Directory success
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+/*#10*/
+    
+    pathToFile = addRootToPath(TEST_DIR,buffer,storageId);
+    status = pal_fsRmDir(pathToFile); //Delete not existing Directory
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_FS_NO_PATH, status);
+}
+
+TEST(pal_fileSystem, directoryTests)
+{
+    directoryTests(PAL_FS_PARTITION_PRIMARY);
+    directoryTests(PAL_FS_PARTITION_SECONDARY);
+}
+
+/*! \brief /b FilesTests function Tests files commands
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Init Test                                                                                                       | |
+* | 2 | create TEST_DIR with pal_fsMkDir                                                                                | PAL_SUCCESS |
+* | 3 | create TEST_DIR2 with pal_fsMkDir                                                                               | PAL_SUCCESS |
+* | 4 | Start Loop i from [0 - TEST_NUMBER_OF_FILE_TO_CREATE]                                                           | |
+* | 5 | Create File in DIR_FILE named f_i (i - index of loop)with PAL_ERR_FS_READWRITEEXCLUSIVE mode using pal_fsFopen  | PAL_SUCCESS |
+* | 6 | Write random buffer[TEST_BYTES_TO_WRITE] to file with pal_fsFwrite                                              | PAL_SUCCESS |
+* | 7 | close file handler with pal_fsFclose                                                                            | PAL_SUCCESS |
+* | 8 | End Loop                                                                                                        | |
+* | 9 | Copy TEST_DIR folder to TEST_DIR2 with pal_fsCpFolder                                                           | PAL_SUCCESS |
+* | 10 | Compare Folders                                                                                                | |
+* | 11 | remove all files from TEST_DIR2                                                                                | PAL_SUCCESS |
+* | 12 | remove all files from TEST_DIR                                                                                 | PAL_SUCCESS |
+* | 13 | Start Loop i from [0 - TEST_NUMBER_OF_FILE_TO_CREATE]                                                          | |
+* | 14 | open Files in DIR_FILE named f_i (i - index of loop) with PAL_ERR_FS_READONLY mode using pal_fsFopen           | PAL_ERR_FS_NO_FILE |
+* | 15 | open Files in DIR_FILE named f_i (i - index of loop) with PAL_ERR_FS_READWRITE mode using pal_fsFopen          | PAL_ERR_FS_NO_FILE |
+* | 16 | open Files in DIR_FILE2 named f_i (i - index of loop) with PAL_ERR_FS_READONLY mode using pal_fsFopen          | PAL_ERR_FS_NO_FILE |
+* | 17 | open Files in DIR_FILE2 named f_i (i - index of loop) with PAL_ERR_FS_READWRITE mode using pal_fsFopen         | PAL_ERR_FS_NO_FILE |
+* | 18 | remove TEST_DIR with pal_fsRmDir                                                                               | PAL_SUCCESS |
+* | 19 | remove TEST_DIR2 with pal_fsRmDir                                                                              | PAL_SUCCESS |
+* | 20 | try to remove a file that does not exist                                                                       | PAL_ERR_FS_NO_FILE |
+* | 21 | try to remove a a variety of files that does not exist                                                         | PAL_ERR_FS_NO_PATH |
+* | 22 | try to copy a non existing folder                                                                              | PAL_ERR_FS_NO_PATH |
+*
+*/
+void FilesTests(pal_fsStorageID_t storageId)
+{
+    palStatus_t status = PAL_SUCCESS;
+    char rootPathBuffer1[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    char rootPathBuffer2[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    char buffer1[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    char buffer2[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    int i = 0;
+    size_t numOfBytes;
+/*#1*/
+    //---------------- INIT TESTS----------------------------//
+    memset(rootPathBuffer1, '1', PAL_MAX_FILE_AND_FOLDER_LENGTH);
+    memset(rootPathBuffer2, '1', PAL_MAX_FILE_AND_FOLDER_LENGTH);
+    //----------------END INIT TESTS-------------------------//
+
+/*#2*/
+    status = pal_fsMkDir(addRootToPath(TEST_DIR,rootPathBuffer1,storageId)); //Create Directory
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#3*/
+    status = pal_fsMkDir(addRootToPath(TEST_DIR2,rootPathBuffer2,storageId)); //Create Directory
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#4*/
+    for(i = 0; i < TEST_NUMBER_OF_FILE_TO_CREATE; i++)
+    {
+/*#5*/
+        snprintf(rootPathBuffer1, PAL_MAX_FILE_AND_FOLDER_LENGTH, TEST_FILE_NAME, TEST_DIR, i);
+        status =  pal_fsFopen(addRootToPath(rootPathBuffer1,buffer1,storageId), PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd1);
+        TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#6*/
+        status =  pal_fsFwrite(&g_fd1, (void *)rootPathBuffer1, TEST_BYTES_TO_WRITE, &numOfBytes);
+        TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#7*/
+        status =  pal_fsFclose(&g_fd1);
+        TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+/*#8*/
+    }
+
+/*#9*/
+    status = pal_fsCpFolder(addRootToPath(TEST_DIR,rootPathBuffer1,storageId), addRootToPath(TEST_DIR2,rootPathBuffer2,storageId));//Copy all files from TEST_DIR to TEST_DIR2
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+/*#10*/
+    for(i = 0; i < TEST_NUMBER_OF_FILE_TO_CREATE; i++)
+    {
+        snprintf(rootPathBuffer1, PAL_MAX_FILE_AND_FOLDER_LENGTH, TEST_FILE_NAME, TEST_DIR, i);
+        snprintf(rootPathBuffer2, PAL_MAX_FILE_AND_FOLDER_LENGTH, TEST_FILE_NAME, TEST_DIR2, i);
+
+        fileSystemCompareUtil(addRootToPath(rootPathBuffer1,buffer1,storageId), addRootToPath(rootPathBuffer2,buffer2,storageId));
+    }
+
+/*#11*/
+    status = pal_fsRmFiles(addRootToPath(TEST_DIR2,rootPathBuffer2,storageId));//Remove all files in the testing DIRECTORY
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#12*/
+    status = pal_fsRmFiles(addRootToPath(TEST_DIR,rootPathBuffer1,storageId));//Remove all files in the testing DIRECTORY
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#13*/
+    for(i = 0; i < TEST_NUMBER_OF_FILE_TO_CREATE; i++)
+    {
+/*#14*/
+        snprintf(buffer1, PAL_MAX_FILE_AND_FOLDER_LENGTH, TEST_FILE_NAME, TEST_DIR, i);
+        status =  pal_fsFopen(addRootToPath(buffer1,rootPathBuffer1,storageId), PAL_FS_FLAG_READONLY, &g_fd1);
+        TEST_ASSERT_EQUAL(PAL_ERR_FS_NO_FILE, status);    //Failed all files where deleted in previous step
+
+/*#15*/
+        status =  pal_fsFopen(addRootToPath(buffer1,rootPathBuffer1,storageId), PAL_FS_FLAG_READWRITE, &g_fd1);
+        TEST_ASSERT_EQUAL(PAL_ERR_FS_NO_FILE, status);    //Failed all files where deleted in previous step
+
+/*#16*/
+        snprintf(buffer2, PAL_MAX_FILE_AND_FOLDER_LENGTH, TEST_FILE_NAME, TEST_DIR2, i);
+        status =  pal_fsFopen(addRootToPath(buffer2,rootPathBuffer2,storageId), PAL_FS_FLAG_READONLY, &g_fd1);
+        TEST_ASSERT_EQUAL(PAL_ERR_FS_NO_FILE, status);    //Failed all files where deleted in previous step
+
+/*#17*/
+        status =  pal_fsFopen(addRootToPath(buffer1,rootPathBuffer1,storageId), PAL_FS_FLAG_READWRITE, &g_fd1);
+        TEST_ASSERT_EQUAL(PAL_ERR_FS_NO_FILE, status);    //Failed all files where deleted in previous step
+
+    }
+
+/*#18*/
+    status = pal_fsRmDir(addRootToPath(TEST_DIR,buffer1,storageId));
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#19*/
+    status = pal_fsRmDir(addRootToPath(TEST_DIR2,buffer2,storageId));
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#20*/
+    status = pal_fsUnlink(addRootToPath("aaaa.t",rootPathBuffer1, storageId));//not existing file
+    TEST_ASSERT_EQUAL(PAL_ERR_FS_NO_FILE, status);
+
+/*#21*/
+    status = pal_fsRmFiles(addRootToPath("aaaaa",rootPathBuffer1, storageId));//Remove all file in not existing directory
+    TEST_ASSERT_EQUAL(PAL_ERR_FS_NO_PATH, status);
+
+/*#22*/
+
+    status = pal_fsCpFolder(addRootToPath("aaaaa", rootPathBuffer1, storageId), addRootToPath("bbbb" ,rootPathBuffer2,storageId)); //copy from not existing dir
+    TEST_ASSERT_EQUAL(PAL_ERR_FS_NO_PATH, status);
+}
+
+TEST(pal_fileSystem, FilesTests)
+{
+    FilesTests(PAL_FS_PARTITION_PRIMARY);
+    FilesTests(PAL_FS_PARTITION_SECONDARY);
+}
+
+/*! \brief /b FilesTestsSeek function Tests \b fseek() , \b fteel() & \b fread() function
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | create TEST_DIR with pal_fsMkDir                                                        | PAL_SUCCESS |
+* | 2 | Create File TEST_DIR_FILE With PAL_ERR_FS_READWRITETRUNC with pal_fsFopen               | PAL_SUCCESS |
+* | 3 | Create buffer[TEST_BUFFER_SIZE] with incremental data, Buffer size TEST_BUFFER_SIZE     | PAL_SUCCESS |
+* | 4 | Write buffer to file with pal_fsFwrite                                                  | PAL_SUCCESS |
+* | 5 | Start Loop     i from [0 - TEST_BUFFER_SIZE]                                            | |
+* | 6 | run pal_fsFseek with PAL_FS_OFFSET_SEEKSET option and incremental offset i              | PAL_SUCCESS |
+* | 7 | run    pal_fsFtell and compare offset to i                                              | PAL_SUCCESS |
+* | 8 | run    pal_fsFread, read one byte and compare it to the buffer[i]                       | PAL_SUCCESS |
+* | 9 | End Loop                                                                                | |
+* | 10 | Start Loop i from [0 - TEST_BUFFER_SIZE]                                               | |
+* | 11 | run pal_fsFseek with PAL_FS_OFFSET_SEEKEND option and incremental offset (-1)*i        | PAL_SUCCESS |
+* | 12 | run pal_fsFtell and compare offset to TEST_BUFFER_SIZE - i                             | PAL_SUCCESS |
+* | 13 | End Loop                                                                               | |
+* | 14 | run pal_fsFseek with PAL_FS_OFFSET_SEEKSET option offset TEST_BUFFER_SIZE/2            | PAL_SUCCESS |
+* | 15 | Start Loop i from [0 - TEST_BUFFER_SIZE/10]                                            | |
+* | 16 | run pal_fsFseek with PAL_FS_OFFSET_SEEKEND option and incremental offset i             | PAL_SUCCESS |
+* | 17 | run    pal_fsFtell and compare offset to i                                             | PAL_SUCCESS |
+* | 18 | End Loop                                                                               | |
+* | 19 | Cleanup                                                                                | PAL_SUCCESS |
+*
+*/
+void FilesTestsSeek(pal_fsStorageID_t storageId)
+{
+    palStatus_t status = PAL_SUCCESS;
+    char buffer[TEST_BUFFER_SIZE];
+    int i = 0;
+    size_t numOfBytes;
+    int32_t pos = 0;
+    char read_buf = 1;
+    size_t prePos = 0;
+/*#1*/
+    status = pal_fsMkDir(addRootToPath(TEST_DIR,buffer,storageId)); //Create Directory
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#2*/
+    status =  pal_fsFopen(addRootToPath(TEST_DIR_FILE,buffer,storageId), PAL_FS_FLAG_READWRITETRUNC, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#3*/
+    for(i = 0; i < TEST_BUFFER_SIZE; i++)
+    {
+        buffer[i] = i;
+    }
+
+/*#4*/
+    status =  pal_fsFwrite(&g_fd1, (void *)buffer, TEST_BUFFER_SIZE, &numOfBytes);  //Write incremental buffer for seek testing
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(TEST_BUFFER_SIZE, numOfBytes);
+
+/*#5*/
+    //Test Seek "PAL_FS_OFFSET_SEEKSET"
+    for(i = 0; i < TEST_BUFFER_SIZE; i++)
+    {
+
+/*#6*/    
+        status = pal_fsFseek(&g_fd1, i, PAL_FS_OFFSET_SEEKSET); //Set position to start of the stream
+        TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#7*/    
+        status = pal_fsFtell(&g_fd1, &pos); //Check if position is in the start of the stream
+        TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+        TEST_ASSERT_EQUAL(i, pos);
+
+/*#8*/    
+        status  = pal_fsFread(&g_fd1, &read_buf, 1, &numOfBytes);
+        TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+        TEST_ASSERT_EQUAL(1, numOfBytes);
+        TEST_ASSERT_EQUAL(buffer[i], read_buf);
+
+/*#9*/
+    }
+    
+/*#10*/
+    //Test Seek "PAL_FS_OFFSET_SEEKEND"
+    for(i = 0; i < TEST_BUFFER_SIZE; i++)
+    {
+/*#11*/    
+        status = pal_fsFseek(&g_fd1, (-1)*i, PAL_FS_OFFSET_SEEKEND); //Set position to end  of the stream
+        TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#12*/    
+        status = pal_fsFtell(&g_fd1, &pos); //Get position
+        TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+        TEST_ASSERT_EQUAL(TEST_BUFFER_SIZE - i, pos);
+
+/*#13*/
+    }
+
+/*#14*/
+    //Test Seek "PAL_ERR_FS_SEEKCUR"
+    status = pal_fsFseek(&g_fd1, TEST_BUFFER_SIZE/2, PAL_FS_OFFSET_SEEKSET); //Set position to middle of the stream
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+    prePos = TEST_BUFFER_SIZE/2;
+
+/*#15*/
+    for(i = 0; i < TEST_BUFFER_SIZE/10 ; i++)
+    {
+
+/*#16*/    
+        status = pal_fsFseek(&g_fd1, i, PAL_FS_OFFSET_SEEKCUR); //Set position to start of the stream
+        TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*17*/    
+        status = pal_fsFtell(&g_fd1, &pos); //Get position
+        TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+        TEST_ASSERT_EQUAL(prePos + i, pos);
+        prePos = pos;
+
+/*#18*/
+    }
+
+/*#19*/
+    status =  pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+}
+
+
+TEST(pal_fileSystem, FilesTestsSeek)
+{
+    FilesTestsSeek(PAL_FS_PARTITION_PRIMARY);
+#if (PAL_NUMBER_OF_PARTITIONS == 2)
+    FilesTestsSeek(PAL_FS_PARTITION_SECONDARY);
+#endif
+}
+
+/*! \brief /b FilesPermission function Tests \b fopen() with r
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Init Test                                                                               | Success |
+* | 2 | create TEST_DIR with pal_fsMkDir                                                        | PAL_SUCCESS |
+* | 3 | create new file using fopen with PAL_FS_FLAG_READWRITEEXCLUSIVE                         | PAL_SUCCESS |
+* | 4 | write buffer to file                                                                    | PAL_SUCCESS |
+* | 5 | close file                                                                              | PAL_SUCCESS |
+* | 6 | open file using fopen() with PAL_FS_FLAG_READONLY                                       | PAL_SUCCESS |
+* | 7 | write buffer to file with fwrite()                                                      | failed |
+* | 8 | read buffer from file with fread()                                                      | PAL_SUCCESS |
+* | 9 | close file                                                                              | PAL_SUCCESS |
+* | 10 | remove all files in folder                                                             | PAL_SUCCESS |
+* | 11 | remove folder                                                                          | PAL_SUCCESS |
+*/
+void FilesPermission_read_only(pal_fsStorageID_t storageId)
+{
+    palStatus_t status = PAL_SUCCESS;
+    char readBuffer[TEST_BUFFER_SIZE];
+    char readBuffer2[TEST_BUFFER_SIZE];
+    char filename[TEST_BUFFER_SIZE];
+    size_t numOfBytes = 0;
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+
+/*#1*/
+    //---------------- INIT TESTS----------------------------//
+    memset(readBuffer, '1', TEST_BUFFER_SIZE);
+    //----------------END INIT TESTS-------------------------//
+
+/*#2*/
+    status = pal_fsMkDir(addRootToPath(TEST_DIR,buffer,storageId)); //Create Directory
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+    snprintf(filename, TEST_BUFFER_SIZE, TEST_FILE_NAME, TEST_DIR, 1);
+/*#3*/
+    status =  pal_fsFopen(addRootToPath(filename,buffer,storageId), PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#4*/
+    status =  pal_fsFwrite(&g_fd1, (void *)readBuffer, TEST_BYTES_TO_WRITE, &numOfBytes);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(TEST_BYTES_TO_WRITE, numOfBytes);
+
+/*#5*/
+    status =  pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#6*/
+    status =  pal_fsFopen(addRootToPath(filename,buffer,storageId), PAL_FS_FLAG_READONLY, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#7*/
+    pal_fsFwrite(&g_fd1, (void *)readBuffer, TEST_BYTES_TO_WRITE, &numOfBytes);
+    TEST_ASSERT_EQUAL(0, numOfBytes);
+
+/*#8*/
+    status = pal_fsFread(&g_fd1, readBuffer2, TEST_BUFFER_SIZE, &numOfBytes);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(TEST_BUFFER_SIZE, numOfBytes);
+    TEST_ASSERT_EQUAL_MEMORY(readBuffer, readBuffer2, TEST_BUFFER_SIZE);
+
+/*#9*/
+    status =  pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#10*/
+    status = pal_fsRmFiles(addRootToPath(TEST_DIR,buffer,storageId));//Remove all files in the testing DIRECTORY
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#11*/
+    status = pal_fsRmDir(addRootToPath(TEST_DIR,buffer,storageId)); //Delete Directory if exist
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+}
+
+TEST(pal_fileSystem, FilesPermission_read_only)
+{
+    FilesPermission_read_only(PAL_FS_PARTITION_PRIMARY);
+    FilesPermission_read_only(PAL_FS_PARTITION_SECONDARY);
+}
+
+
+/*! \brief /b FilesPermission function Tests \b fopen() with r+
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Init Test                                                                               | Success |
+* | 2 | create TEST_DIR with pal_fsMkDir                                                        | PAL_SUCCESS |
+* | 3 | create new file using fopen with PAL_FS_FLAG_READWRITEEXCLUSIVE                         | PAL_SUCCESS |
+* | 4 | write buffer to file                                                                    | PAL_SUCCESS |
+* | 5 | close file                                                                              | PAL_SUCCESS |
+* | 6 | open file using fopen() with PAL_FS_FLAG_READONLY                                       | PAL_SUCCESS |
+* | 7 | write buffer to file with fwrite()                                                      | PAL_SUCCESS |
+* | 8 | seek to the begining of the file                                                        | PAL_SUCCESS |
+* | 9 | read buffer from file with fread()                                                      | PAL_SUCCESS |
+* | 10 | close file                                                                             | PAL_SUCCESS |
+* | 11 | remove all files in folder                                                             | PAL_SUCCESS |
+* | 12 | remove folder                                                                          | PAL_SUCCESS |
+*/
+void FilesPermission_read_write(pal_fsStorageID_t storageId)
+{
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    palStatus_t status = PAL_SUCCESS;
+    char readBuffer[TEST_BUFFER_SIZE];
+    char readBuffer2[TEST_BUFFER_SIZE];
+    char filename[TEST_BUFFER_SIZE];
+    size_t numOfBytes = 0;
+
+/*#1*/
+    //---------------- INIT TESTS----------------------------//
+    memset(readBuffer, '1', TEST_BUFFER_SIZE);
+    //----------------END INIT TESTS-------------------------//
+
+/*#2*/
+    status = pal_fsMkDir(addRootToPath(TEST_DIR,buffer,storageId)); //Create Directory
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+    snprintf(filename, TEST_BUFFER_SIZE, TEST_FILE_NAME, TEST_DIR, 1);
+/*#3*/
+    status =  pal_fsFopen(addRootToPath(filename,buffer,storageId), PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#4*/
+    status =  pal_fsFwrite(&g_fd1, (void *)readBuffer, TEST_BYTES_TO_WRITE, &numOfBytes);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(TEST_BYTES_TO_WRITE, numOfBytes);
+
+/*#5*/
+    status =  pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#6*/
+    status =  pal_fsFopen(addRootToPath(filename,buffer,storageId), PAL_FS_FLAG_READWRITE, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#7*/
+    status =  pal_fsFwrite(&g_fd1, (void *)readBuffer, TEST_BYTES_TO_WRITE, &numOfBytes);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(TEST_BYTES_TO_WRITE, numOfBytes);
+
+/*#8*/
+    status = pal_fsFseek(&g_fd1, 0, PAL_FS_OFFSET_SEEKSET); //Set position to start of the stream
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#9*/
+    status = pal_fsFread(&g_fd1, readBuffer2, TEST_BUFFER_SIZE, &numOfBytes);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(TEST_BYTES_TO_WRITE, numOfBytes);
+    TEST_ASSERT_EQUAL_MEMORY(readBuffer, readBuffer2, TEST_BUFFER_SIZE);
+
+/*#10*/
+    status =  pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#11*/
+    status = pal_fsRmFiles(addRootToPath(TEST_DIR,buffer,storageId));//Remove all files in the testing DIRECTORY
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#12*/
+    status = pal_fsRmDir(addRootToPath(TEST_DIR,buffer,storageId)); //Delete Directory if exist
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+}
+
+
+TEST(pal_fileSystem, FilesPermission_read_write)
+{
+    FilesPermission_read_write(PAL_FS_PARTITION_PRIMARY);
+    FilesPermission_read_write(PAL_FS_PARTITION_SECONDARY);
+}
+
+
+/*! \brief /b FilesPermission function Tests \b fopen() with w+x
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Init Test                                                                               | Success |
+* | 2 | create TEST_DIR with pal_fsMkDir                                                        | PAL_SUCCESS |
+* | 3 | create new file using fopen with PAL_FS_FLAG_READWRITEEXCLUSIVE                         | PAL_SUCCESS |
+* | 4 | write buffer to file                                                                    | PAL_SUCCESS |
+* | 5 | close file                                                                              | PAL_SUCCESS |
+* | 6 | open file using fopen() withPAL_FS_FLAG_READWRITETRUNC                                  | PAL_SUCCESS |
+* | 7 | read buffer from file with fread()                                                      | PAL_SUCCESS with read length 0 |
+* | 8 | close file                                                                              | PAL_SUCCESS |
+* | 9 | remove all files in folder                                                              | PAL_SUCCESS |
+* | 10 | remove folder                                                                          | PAL_SUCCESS |
+*/
+void FilesPermission_read_write_trunc(pal_fsStorageID_t storageId)
+{
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    palStatus_t status = PAL_SUCCESS;
+    char readBuffer[TEST_BUFFER_SIZE];
+    char filename[TEST_BUFFER_SIZE];
+    size_t numOfBytes = 0;
+
+/*#1*/
+    //---------------- INIT TESTS----------------------------//
+    memset(readBuffer, '1', TEST_BUFFER_SIZE);
+    //----------------END INIT TESTS-------------------------//
+
+/*#2*/
+    status = pal_fsMkDir(addRootToPath(TEST_DIR,buffer,storageId)); //Create Directory
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+    snprintf(filename, TEST_BUFFER_SIZE, TEST_FILE_NAME, TEST_DIR, 1);
+/*#3*/
+    status = pal_fsFopen(addRootToPath(filename,buffer,storageId), PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#4*/
+    status = pal_fsFwrite(&g_fd1, (void *)readBuffer, TEST_BYTES_TO_WRITE, &numOfBytes);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(TEST_BYTES_TO_WRITE, numOfBytes);
+
+/*#5*/
+    status = pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#6*/
+    status = pal_fsFopen(addRootToPath(filename,buffer,storageId), PAL_FS_FLAG_READWRITETRUNC, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#7*/
+    status = pal_fsFread(&g_fd1, readBuffer, TEST_BUFFER_SIZE, &numOfBytes);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(0, numOfBytes); //nothing to read empty file
+
+/*#8*/
+    status = pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#9*/
+    status = pal_fsRmFiles(addRootToPath(TEST_DIR,buffer,storageId));//Remove all files in the testing DIRECTORY
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+
+/*#10*/
+    status = pal_fsRmDir(addRootToPath(TEST_DIR,buffer,storageId)); //Delete Directory if exist
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+}
+
+
+TEST(pal_fileSystem, FilesPermission_read_write_trunc)
+{
+    FilesPermission_read_write_trunc(PAL_FS_PARTITION_PRIMARY);
+    FilesPermission_read_write_trunc(PAL_FS_PARTITION_SECONDARY);
+}
+
+
+void create_write_and_read_pal_file(pal_fsStorageID_t storageId)
+{
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    char fileName[] = "fileName";
+    palStatus_t res = PAL_SUCCESS;
+    size_t num_bytes_write = 0;
+    size_t num_bytes_read = 0;
+
+    uint32_t i = 0;
+
+    bufferTest = malloc(BUFFER_TEST_SIZE);
+    TEST_ASSERT_NOT_EQUAL(bufferTest, NULL);
+    bufferTest2 = malloc(BUFFER_TEST_SIZE);
+    TEST_ASSERT_NOT_EQUAL(bufferTest2, NULL);
+    memset(bufferTest, 0, BUFFER_TEST_SIZE);
+    memset(bufferTest2, 0, BUFFER_TEST_SIZE);
+
+    for (i = 0; i < BUFFER_TEST_SIZE; i++){
+            bufferTest[i] = (uint8_t)(i % 256);
+    }
+
+    pal_fsUnlink(addRootToPath(fileName,buffer,storageId));
+
+    res = pal_fsFopen(addRootToPath(fileName,buffer,storageId), PAL_FS_FLAG_READWRITEEXCLUSIVE, &(g_fd1));
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsFwrite(&(g_fd1), bufferTest, BUFFER_TEST_SIZE, &num_bytes_write);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(BUFFER_TEST_SIZE, num_bytes_write);
+
+    res = pal_fsFclose(&(g_fd1));
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsFopen(addRootToPath(fileName,buffer,storageId), PAL_FS_FLAG_READONLY, &(g_fd1));
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsFread(&(g_fd1), bufferTest2, 223, &num_bytes_read);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(223, num_bytes_read);
+
+    // split the reads
+    res = pal_fsFread(&(g_fd1), bufferTest2, 900, &num_bytes_read);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(900, num_bytes_read);
+
+
+    // Compare the buffers � here we have a mismatch in location buffer2[288]
+    TEST_ASSERT_EQUAL_INT8_ARRAY(&(bufferTest[223]), bufferTest2, 900);
+
+    res = pal_fsFclose(&(g_fd1));
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsUnlink(addRootToPath(fileName,buffer,storageId));
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    free(bufferTest);
+    bufferTest = NULL;
+    free(bufferTest2);
+    bufferTest2 = NULL;
+    
+}
+
+
+TEST(pal_fileSystem, create_write_and_read_pal_file)
+{
+    create_write_and_read_pal_file(PAL_FS_PARTITION_PRIMARY);
+    create_write_and_read_pal_file(PAL_FS_PARTITION_SECONDARY);
+}
+
+void WriteInTheMiddle(pal_fsStorageID_t storageId)
+{
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    char fileName[] = "fileName";
+    const uint32_t inputSizeSmall = (TEST_BUFFER_SIZE * 6) + 1;
+    const uint32_t inputSizeBig = BUFFER_TEST_SIZE;
+    palStatus_t res = PAL_SUCCESS;
+    size_t num_bytes_write = 0;
+    size_t num_bytes_read = 0;
+    unsigned char *smallBuffer = NULL;
+    const size_t offset = 200;
+    uint32_t residue = inputSizeBig - (offset + inputSizeSmall);
+
+    bufferTest = malloc(inputSizeBig);
+    TEST_ASSERT_NOT_EQUAL(bufferTest, NULL);
+    bufferTest2 = malloc(inputSizeBig);
+    TEST_ASSERT_NOT_EQUAL(bufferTest2, NULL);
+    smallBuffer = malloc(inputSizeSmall);
+    TEST_ASSERT_NOT_EQUAL(smallBuffer, NULL);
+    memset(bufferTest, 0, inputSizeBig);
+    memset(bufferTest2, 0, inputSizeBig);
+    memset(smallBuffer, 0, inputSizeSmall);
+
+    // create 1123 bytes buffer filled with the numbers 0..255
+    for (uint32_t i = 0; i < inputSizeBig; i++)
+    {
+        bufferTest[i] = (uint8_t)(i % 256);
+    }
+
+    // create 601 bytes buffer filled with only 0xCC
+    for (uint32_t i = 0; i < inputSizeSmall; i++)
+    {
+        smallBuffer[i] = 0xCC;
+    }
+
+    pal_fsUnlink(addRootToPath(fileName,buffer,storageId));
+    TEST_ASSERT((PAL_SUCCESS == res) || (PAL_ERR_FS_NO_FILE == res));
+
+    /* 1. Write bufferTest data to file, read it and compare read content to bufferTest */
+    res = pal_fsFopen(addRootToPath(fileName,buffer,storageId), PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsFwrite(&g_fd1, bufferTest, inputSizeBig, &num_bytes_write);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(inputSizeBig, num_bytes_write);
+
+    res = pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsFopen(addRootToPath(fileName,buffer,storageId), PAL_FS_FLAG_READONLY, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsFread(&g_fd1, bufferTest2, inputSizeBig, &num_bytes_read);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(inputSizeBig, num_bytes_read);
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(bufferTest, bufferTest2, inputSizeBig);
+
+    res = pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    /* 
+    2. Write smallBuffer data to offset 201 of the file and then compare each fragment:
+        - offset 0..200 equal to bufferTest[0..200]
+        - offset 201..801 equal to smallBuffer
+        - offset 802..1122 equal to bufferTest[802..1122]
+    */
+    res = pal_fsFopen(addRootToPath(fileName,buffer,storageId), PAL_FS_FLAG_READWRITE, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsFseek(&g_fd1, offset, PAL_FS_OFFSET_SEEKSET);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsFwrite(&g_fd1, smallBuffer, inputSizeSmall, &num_bytes_write);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(inputSizeSmall, num_bytes_write);
+
+    res = pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsFopen(addRootToPath(fileName,buffer,storageId), PAL_FS_FLAG_READONLY, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    // offset 0..200 equal to bufferTest[0..200]
+    res = pal_fsFread(&g_fd1, bufferTest2, offset, &num_bytes_read);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(offset, num_bytes_read);
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(bufferTest, bufferTest2, offset);
+
+    // offset 201..801 equal to smallBuffer
+    res = pal_fsFread(&g_fd1, bufferTest2, inputSizeSmall, &num_bytes_read);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(inputSizeSmall, num_bytes_read);
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(smallBuffer, bufferTest2, inputSizeSmall);
+
+    // offset 802..1122 equal to bufferTest[802..1122]
+    res = pal_fsFread(&g_fd1, bufferTest2, residue, &num_bytes_read);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(residue, num_bytes_read);
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(bufferTest + offset + inputSizeSmall, bufferTest2, residue);
+
+    res = pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsUnlink(addRootToPath(fileName,buffer,storageId));
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    free(bufferTest);
+    bufferTest = NULL;
+    free(bufferTest2);
+    bufferTest2 = NULL;
+    free(smallBuffer);
+    smallBuffer = NULL;
+}
+
+TEST(pal_fileSystem, WriteInTheMiddle)
+{
+    WriteInTheMiddle(PAL_FS_PARTITION_PRIMARY);
+    WriteInTheMiddle(PAL_FS_PARTITION_SECONDARY);
+}
+
+
+
+
+void SequentialWriteAndRead(pal_fsStorageID_t storageId)
+{
+    char buffer[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    char fileName[] = "fileName";
+    palStatus_t res = PAL_SUCCESS;
+    size_t num_bytes_write = 0;
+    size_t num_bytes_read = 0;
+    unsigned char small_write_buffer[TEST_BUFFER_SMALL_SIZE] = {
+        0x2D, 0x6B, 0xAC, 0xCC, 0x08, 0x6B, 0x14, 0x82,
+        0xF3, 0x0C, 0xF5, 0x67, 0x17, 0x23, 0x50, 0xB4,
+        0xFF
+    };
+    unsigned char small_read_buffer[TEST_BUFFER_SMALL_SIZE] = { 0 };
+    bufferTest = malloc(BUFFER_TEST_SIZE);
+    TEST_ASSERT_NOT_EQUAL(bufferTest, NULL);
+    bufferTest2 = malloc(BUFFER_TEST_SIZE);
+    TEST_ASSERT_NOT_EQUAL(bufferTest2, NULL);
+    memset(bufferTest, 0, BUFFER_TEST_SIZE);
+    memset(bufferTest2, 0, BUFFER_TEST_SIZE);
+
+    // create 1123 bytes buffer filled with the numbers 0..255
+    for (uint32_t i = 0; i < BUFFER_TEST_SIZE; i++)
+    {
+        bufferTest[i] = (uint8_t)(i % 256);
+    }
+    res = pal_fsUnlink(addRootToPath(fileName,buffer,storageId));
+    TEST_ASSERT((PAL_SUCCESS == res) || (PAL_ERR_FS_NO_FILE == res));
+
+    res = pal_fsFopen(addRootToPath(fileName,buffer,storageId), PAL_FS_FLAG_READWRITEEXCLUSIVE, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    // split the writes
+    res = pal_fsFwrite(&g_fd1, small_write_buffer, TEST_BUFFER_SMALL_SIZE, &num_bytes_write);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(TEST_BUFFER_SMALL_SIZE, num_bytes_write);
+
+    res = pal_fsFwrite(&g_fd1, bufferTest, BUFFER_TEST_SIZE, &num_bytes_write);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(BUFFER_TEST_SIZE, num_bytes_write);
+
+    res = pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsFopen(addRootToPath(fileName,buffer,storageId), PAL_FS_FLAG_READONLY, &g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    // split the reads
+    res = pal_fsFread(&g_fd1, small_read_buffer, TEST_BUFFER_SMALL_SIZE, &num_bytes_read);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(TEST_BUFFER_SMALL_SIZE, num_bytes_read);
+
+    res = pal_fsFread(&g_fd1, bufferTest2, BUFFER_TEST_SIZE, &num_bytes_read);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+    TEST_ASSERT_EQUAL(BUFFER_TEST_SIZE, num_bytes_read);
+
+    TEST_ASSERT_EQUAL_INT8_ARRAY(bufferTest, bufferTest2, BUFFER_TEST_SIZE);
+
+    res = pal_fsFclose(&g_fd1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    res = pal_fsUnlink(addRootToPath(fileName,buffer,storageId));
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, res);
+
+    free(bufferTest);
+    bufferTest = NULL;
+    free(bufferTest2);
+    bufferTest2 = NULL;    
+}
+
+TEST(pal_fileSystem, SequentialWriteAndRead)
+{
+    SequentialWriteAndRead(PAL_FS_PARTITION_PRIMARY);
+    SequentialWriteAndRead(PAL_FS_PARTITION_SECONDARY);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/FileSystem/pal_fileSystem_test_runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "unity.h"
+#include "unity_fixture.h"
+#include "pal.h"
+
+TEST_GROUP_RUNNER(pal_fileSystem)
+{
+    RUN_TEST_CASE(pal_fileSystem, SDFormat);
+	RUN_TEST_CASE(pal_fileSystem, rootDirectoryTests);
+	RUN_TEST_CASE(pal_fileSystem, directoryTests);
+	RUN_TEST_CASE(pal_fileSystem, FilesTests);
+	RUN_TEST_CASE(pal_fileSystem, FilesTestsSeek);
+	RUN_TEST_CASE(pal_fileSystem, FilesPermission_read_only);
+	RUN_TEST_CASE(pal_fileSystem, FilesPermission_read_write);
+	RUN_TEST_CASE(pal_fileSystem, FilesPermission_read_write_trunc);
+	RUN_TEST_CASE(pal_fileSystem, create_write_and_read_pal_file);
+    RUN_TEST_CASE(pal_fileSystem, WriteInTheMiddle);
+    RUN_TEST_CASE(pal_fileSystem, SequentialWriteAndRead);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Networking/pal_socket_test.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1546 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal.h"
+#include "pal_network.h"
+#include "unity.h"
+#include "unity_fixture.h"
+#include "PlatIncludes.h"
+#include "pal_BSP.h"
+#include "string.h"
+
+#ifdef __LINUX__
+#include <netdb.h>
+#define test_getAddressInfo getAddressInfoIPv4
+#else
+#define test_getAddressInfo pal_getAddressInfo
+#endif
+
+TEST_GROUP(pal_socket);
+
+//Sometimes you may want to get local data in a module,
+//for example if you need to pass a reference.
+//However, you should usually avoid this.
+//extern int Counter;
+
+#define PAL_NET_SUPPORT_LWIP 1
+#define PAL_NET_TEST_SERVER_NAME   "www.arm.com"
+#define PAL_NET_TEST_SERVER_NAME_UDP   "8.8.8.8"
+#define PAL_TEST_KEEPALIVE_SERVER_ADDRESS "62.44.193.186"
+#define PAL_TEST_KEEPALIVE_NUM_OF_ACK 4
+
+#define PAL_NET_TEST_SERVER_HTTP_PORT 80
+#define PAL_TEST_SERVER_KEEPALIVE_PORT 5533
+
+#define PAL_NET_TEST_SERVER_UDP_PORT 53
+#define PAL_NET_TEST_INCOMING_PORT 8002
+#define PAL_NET_TEST_INCOMING_PORT2 8989
+
+#define PAL_NET_TEST_LOCAL_LOOPBACK_IF_INDEX 0
+extern void * g_palTestNetworkInterface; // this is set by the palTestMain funciton
+PAL_PRIVATE uint32_t g_interfaceCTXIndex = 0;
+PAL_PRIVATE uint32_t s_callbackcounter = 0;
+
+#define PAL_NET_TEST_SOCKETS 4
+PAL_PRIVATE palSocket_t g_testSockets[PAL_NET_TEST_SOCKETS] = {0,0,0,0};
+
+#define PAL_NET_TEST_GOOGLE_CDN_HOST "ajax.googleapis.com" /*! CDN host server */
+#define PAL_NET_TEST_GOOGLE_CDN_HOST_PORT 80 /*! CDN host port */
+#define PAL_NET_TEST_GOOGLE_CDN_REQUEST "GET /ajax/libs/jquery/3.2.1/jquery.js HTTP/1.0\r\nHost:" PAL_NET_TEST_GOOGLE_CDN_HOST "\r\n\r\n" /*! HTTP get request */
+#define PAL_NET_TEST_BUFFERED_TCP_BUF_SIZE_SMALL 4
+#define PAL_NET_TEST_BUFFERED_TCP_BUF_SIZE_LARGE 1024
+#define PAL_NET_TEST_BUFFERED_UDP_BUF_SIZE_SMALL 64
+#define PAL_NET_TEST_BUFFERED_UDP_BUF_SIZE_LARGE 512
+#define PAL_NET_TEST_BUFFERED_UDP_PORT 2606
+#define PAL_NET_TEST_BUFFERED_UDP_MESSAGE_SIZE (1024 * 256)
+PAL_PRIVATE uint8_t *g_testRecvBuffer = NULLPTR;
+PAL_PRIVATE uint8_t *g_testSendBuffer = NULLPTR;
+
+typedef struct pal_udp_test_data /*! structure used to hold state in UDP buffered tests */
+{
+    const size_t messageSize;
+    const size_t bufferSize;
+    const uint8_t startValue;
+    palNetInterfaceInfo_t interfaceInfo;
+    uint8_t currentValue;
+    size_t totalSize;
+    size_t chunkSize;
+} pal_udp_test_data_t;
+
+TEST_SETUP(pal_socket)
+{
+    uint32_t i = 0;
+    palStatus_t status = PAL_SUCCESS;
+    //This is run before *each test*
+    pal_init();
+    if ( NULL == g_palTestNetworkInterface )
+    {
+        PAL_LOG(ERR, "error: net interface not configutred correctly");
+    }
+    else
+    {
+        status = pal_registerNetworkInterface(g_palTestNetworkInterface, &g_interfaceCTXIndex);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+
+    for (i = 0; i < PAL_NET_TEST_SOCKETS; i++)
+    {
+        g_testSockets[i] = 0;
+    }
+}
+
+TEST_TEAR_DOWN(pal_socket)
+{
+    uint32_t i = 0;
+    for (i = 0; i < PAL_NET_TEST_SOCKETS; i++)
+    {
+        if (g_testSockets[i] != 0)
+        {
+            pal_close(&(g_testSockets[i]));
+        }
+    }
+
+    if (g_testRecvBuffer != NULLPTR)
+    {
+        free(g_testRecvBuffer);
+        g_testRecvBuffer = NULLPTR;
+    }
+    if (g_testSendBuffer != NULLPTR)
+    {
+        free(g_testSendBuffer);
+        g_testSendBuffer = NULLPTR;
+    }
+
+    pal_destroy();
+}
+
+#define PAL_TEST_BUFFER_SIZE 50
+PAL_PRIVATE void socketCallback1( void * arg)
+{
+    s_callbackcounter++;
+}
+
+/*! \brief Test socket creation, destruction and modification, as well as getting address infromation and checking the blocking status of sockets.
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Register a net interface using `pal_registerNetworkInterface`.                          | PAL_SUCCESS |
+* | 2 | Register a net interface using `pal_registerNetworkInterface`, and check that the ID is the same as the previous step.  | PAL_SUCCESS |
+* | 3 | Get the interface address using `pal_getNetInterfaceInfo`.                       | PAL_SUCCESS |
+* | 4 | Create a blocking UDP socket using `pal_socket`.                                        | PAL_SUCCESS |
+* | 5 | Create a blocking UDP socket using `pal_socket`.                                        | PAL_SUCCESS |
+* | 6 | Create a non-blocking UDP socket using `pal_socket`.                                    | PAL_SUCCESS |
+* | 7 | Create a blocking asynchronous TCP socket with `socketCallback1` as callback.           | PAL_SUCCESS |
+* | 8 | Check the number of net interfaces registered using `pal_getNetInterfaceInfo`.           | PAL_SUCCESS |
+* | 9 | Set the socket receive timeout using `pal_setSocketOptions`.                              | PAL_SUCCESS |
+* | 10 | Check that the sockets return the correct blocking status using `pal_isNonBlocking`.      | PAL_SUCCESS |
+* | 11 | Check the `pal_getAddressInfo` function with an invalid address.                       | PAL_ERR_SOCKET_DNS_ERROR |
+* | 12 | Close all sockets.                                                              | PAL_SUCCESS |
+*/
+TEST(pal_socket, socketUDPCreationOptionsTest)
+{
+    palStatus_t result = PAL_SUCCESS;
+    uint32_t numInterface = 0;
+    palNetInterfaceInfo_t interfaceInfo;
+    uint32_t interfaceIndex = 0;
+    uint32_t interfaceIndex2 = 0;
+    uint32_t sockOptVal = 5000;
+    uint32_t sockOptLen = sizeof(sockOptVal);
+    palSocketAddress_t address = { 0 };
+    palSocketLength_t addrlen = 0;
+    bool isNonBlocking = false;
+
+    memset(&interfaceInfo,0,sizeof(interfaceInfo));
+    // Check that re-adding the network interface returns the same index
+    /*#1*/
+    result = pal_registerNetworkInterface(g_palTestNetworkInterface, &interfaceIndex);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#2*/
+    result = pal_registerNetworkInterface(g_palTestNetworkInterface, &interfaceIndex2);
+    TEST_ASSERT_EQUAL_HEX(interfaceIndex, interfaceIndex2);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+#if PAL_SUPPORT_IP_V4
+    /*#3*/
+    result = pal_getNetInterfaceInfo(interfaceIndex, &interfaceInfo);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    PAL_PRINTF("Default interface address: %u %u %u %u \r\n",
+        (unsigned char)interfaceInfo.address.addressData[2],
+        (unsigned char)interfaceInfo.address.addressData[3],
+        (unsigned char)interfaceInfo.address.addressData[4],
+        (unsigned char)interfaceInfo.address.addressData[5]);;
+#endif
+
+    //Blocking
+    /*#4*/
+    result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM, false, interfaceIndex, &g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+    /*#5*/
+    result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM, false, interfaceIndex, &g_testSockets[1]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+    //Non-blocking
+    /*#6*/
+    result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM, true, interfaceIndex, &g_testSockets[3]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+#if    PAL_NET_ASYNCHRONOUS_SOCKET_API
+    /*#7*/
+    result = pal_asynchronousSocket(PAL_AF_INET, PAL_SOCK_STREAM, false, interfaceIndex, socketCallback1, &g_testSockets[2]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+#endif // PAL_NET_ASYNCHRONOUS_SOCKET_API
+
+    /*#8*/
+    result = pal_getNumberOfNetInterfaces(&numInterface);
+    TEST_ASSERT_NOT_EQUAL(numInterface, 0);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#9*/
+    result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO, &sockOptVal, sockOptLen);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#10*/
+    result = pal_isNonBlocking(g_testSockets[0],&isNonBlocking);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_HEX(isNonBlocking, false);
+
+    result = pal_isNonBlocking(g_testSockets[3], &isNonBlocking);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_HEX(isNonBlocking, true);
+
+    /*#11*/
+    result = pal_getAddressInfo("0.0.0.0", &address, &addrlen);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_SOCKET_DNS_ERROR, result);
+
+    /*#12*/
+#if    PAL_NET_ASYNCHRONOUS_SOCKET_API
+    result = pal_close(&g_testSockets[2]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+#endif // PAL_NET_ASYNCHRONOUS_SOCKET_API
+
+    result = pal_close(&g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+    result = pal_close(&g_testSockets[1]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+    result = pal_close(&g_testSockets[3]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+    result = pal_close(&g_testSockets[3]); //double close - should succeed
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+}
+
+
+/*! \brief Test TCP socket creation, connection, send and receive with a test server.
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a blocking TCP socket using `pal_socket`.                                         | PAL_SUCCESS |
+* | 2 | Look up the IP address of the test server using `pal_getAddressInfo`.                          | PAL_SUCCESS |
+* | 3 | Set the port to a test port in the address structure using `pal_setSockAddrPort` and set timeout. | PAL_SUCCESS |
+* | 4 | Connect the socket to the test server using `pal_connect`.                                     | PAL_SUCCESS |
+* | 5 | Send a test message (short HTTP request) to the test server using `pal_send`.                  | PAL_SUCCESS |
+* | 6 | Receive (blocking) the server's response using `pal_recv` and check it is HTTP.          | PAL_SUCCESS |
+* | 7 | Close the socket.                                                                        | PAL_SUCCESS |
+*/
+TEST(pal_socket, basicTCPclientSendRecieve)
+{
+    palStatus_t result = PAL_SUCCESS;
+    palSocketAddress_t address = { 0 };
+    const char message[] = "GET / HTTP/1.0\r\n\r\n";
+    size_t sent = 0;
+    char buffer[100] = { 0 };
+    size_t read = 0;
+    palSocketLength_t addrlen = 0;
+    int timeout = PAL_MILLI_PER_SECOND;
+
+    /*#1*/
+
+    result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#2*/
+    result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME, &address, &addrlen);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)");
+        goto end;
+    }
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#3*/
+    result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_HTTP_PORT);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO, &timeout, sizeof(timeout));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO, &timeout, sizeof(timeout));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+
+    /*#4*/
+    result = pal_connect(g_testSockets[0], &address, 16);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#5*/
+    result = pal_send(g_testSockets[0], message, sizeof(message) - 1, &sent);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#6*/
+    result = pal_recv(g_testSockets[0], buffer, 99, &read);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    TEST_ASSERT(read >= 4);
+    TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P');
+
+end: //unified cleanup
+    /*#7*/
+    pal_close(&g_testSockets[0]);
+
+}
+
+/*! \brief Test UDP socket creation, connection, send and recieve with a test server.
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a blocking UDP socket using `pal_socket`.                                     | PAL_SUCCESS |
+* | 2 | Look up the IP address of the test server using `pal_getAddressInfo`.                      | PAL_SUCCESS |
+* | 3 | Set the port to a test port in the address structure using `pal_setSockAddrPort`.            | PAL_SUCCESS |
+* | 4 | Connect the socket to the test server using `pal_connect`.                                 | PAL_SUCCESS |
+* | 5 | Send a test message (short DNS request) to the test server using `pal_send`.                | PAL_SUCCESS |
+* | 6 | Receive (blocking) the server's response using `pal_recv`.                           | PAL_SUCCESS |
+* | 7 | Close the socket.                                                                    | PAL_SUCCESS |
+*/
+TEST(pal_socket, basicUDPclientSendRecieve)
+{
+    palStatus_t result = PAL_SUCCESS;
+    palSocketAddress_t address = { 0 };
+    palSocketAddress_t address2 = { 0 };
+    uint8_t buffer[33] = { 0x8e, 0xde, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x61, 0x72, 0x73, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, 0x61, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 };
+    uint8_t buffer_in[10];
+    size_t sent = 0;
+    size_t read = 0;
+    size_t socket_timeout_ms = 5000;
+    palSocketLength_t addrlen = 0;
+
+    /*#1*/
+    result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM, false, 0, &g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#2*/
+    result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME_UDP, &address, &addrlen);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration can't continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)");
+        goto end;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#3*/
+    result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_UDP_PORT);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#4*/
+    //We set a timeout for receiving so we won't get stuck in the test
+    result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO, &socket_timeout_ms, sizeof(socket_timeout_ms));
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#5*/
+    result = pal_sendTo(g_testSockets[0], buffer, sizeof(buffer), &address, 16, &sent);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL(sent, sizeof(buffer));
+
+    /*#6*/
+    result = pal_receiveFrom(g_testSockets[0], buffer_in, 10, &address2, &addrlen, &read);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL(read, 10);
+end:
+    /*#7*/
+    pal_close(&g_testSockets[0]);
+}
+
+
+
+
+// This is an example showing how to check for a socket that has been closed remotely.
+#if 0
+PAL_PRIVATE void basicSocketScenario3Callback(void * arg)
+{
+    char buffer[400];
+    size_t read = 0;
+    palStatus_t result;
+
+
+    s_callbackcounter++;
+    result = pal_recv(g_testSockets[0], buffer, 999, &read);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    // If 0 bytes are read it means that the peer has performed an orderly shutdown so we must close the socket
+    // to avoid ppoll from checking it. Checking a socket whose other end has been shut down causes ppoll to immediately return
+    // with events == 0x1.
+    if(read == 0)
+    {
+        pal_close(&g_testSockets[0]);
+    }
+    else
+    {
+        buffer[read] = '\0';
+        if(s_callbackcounter == 0)
+        {
+            TEST_ASSERT(read >= 4);
+            TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P');
+        }
+    }
+
+}
+#endif
+palSemaphoreID_t s_semaphoreID = NULLPTR;
+
+PAL_PRIVATE void socketCallback2(void * arg)
+{
+    palStatus_t result;
+    if(s_callbackcounter == 0)
+    {
+        result = pal_osSemaphoreRelease(s_semaphoreID);
+        TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+    }
+    s_callbackcounter++;
+
+}
+
+static int s_secondCallbackCounter = 0;
+PAL_PRIVATE void socketCallbackErr(void * arg)
+{
+    s_secondCallbackCounter++;
+}
+
+/*! \brief Test asynchronous socket callbacks.
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Look up the IP address of the test server using `pal_getAddressInfo`.                      | PAL_SUCCESS |
+* | 2 | Create a blocking asynchronous TCP socket with `socketCallback2` as callback.        | PAL_SUCCESS |
+* | 3 | Set port to a test port in the address structure using `pal_setSockAddrPort`.            | PAL_SUCCESS |
+* | 4 | Connect the socket to the test server using `pal_connect`.                                 | PAL_SUCCESS |
+* | 5 | Send a test message (short HTTP request) to the test server using `pal_send`.               | PAL_SUCCESS |
+* | 6 | Wait for a callback to release the semaphore when the response arrives.                    | PAL_SUCCESS |
+* | 7 | Receive (blocking) the server's response using `pal_recv` and check that the response is HTTP.| PAL_SUCCESS |
+* | 8 | Close the socket.                                                                    | PAL_SUCCESS |
+*/
+TEST(pal_socket, basicSocketScenario3)
+{
+    palStatus_t result = PAL_SUCCESS;
+    palSocketAddress_t address = { 0 };
+    const char* message = "GET / HTTP/1.0\r\nHost:10.45.48.68:8000\r\n\r\n";
+    size_t sent = 0;
+    char buffer[100] = { 0 };
+    size_t read = 0;
+    s_callbackcounter = 0;
+    palSocketLength_t addrlen = 0;
+    int32_t countersAvailable;
+
+    result = pal_osSemaphoreCreate(1, &s_semaphoreID);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+    result = pal_osSemaphoreWait(s_semaphoreID, 40000, &countersAvailable);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#1*/
+    result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME, &address, &addrlen);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)");
+        return;
+    }
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+    /*#2*/
+    result = pal_asynchronousSocketWithArgument(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, socketCallback2, "socketCallback2Arg", &g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    s_secondCallbackCounter = 0;
+    result = pal_asynchronousSocketWithArgument(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, socketCallbackErr, "socketCallback2Arg", &g_testSockets[1]);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    TEST_ASSERT_EQUAL_HEX(0, s_secondCallbackCounter);
+    /*#3*/
+    result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_HTTP_PORT);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#4*/
+    result = pal_connect(g_testSockets[0], &address, 16);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    TEST_ASSERT_EQUAL_HEX(0, s_secondCallbackCounter);
+    /*#5*/
+    result = pal_send(g_testSockets[0], message, strlen(message), &sent);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    TEST_ASSERT_EQUAL_HEX(0, s_secondCallbackCounter);
+    // Give a chance for the callback to be called.
+    /*#6*/
+    result=pal_osSemaphoreWait(s_semaphoreID, 40000,  &countersAvailable);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    result=pal_osSemaphoreDelete(&s_semaphoreID);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#7*/
+    result = pal_recv(g_testSockets[0], buffer, 99, &read);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+    TEST_ASSERT(read >= 4);
+    TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P');
+    TEST_ASSERT(s_callbackcounter > 0);
+
+
+    TEST_ASSERT_EQUAL_HEX(0, s_secondCallbackCounter);
+    /*#8*/
+    pal_close(&g_testSockets[0]);
+#endif // PAL_NET_ASYNCHRONOUS_SOCKET_API
+}
+
+
+
+
+typedef struct palNetTestThreadData{
+    palSemaphoreID_t sem1;
+    palSemaphoreID_t sem2;
+    uint16_t port;
+} palNetTestThreadData_t;
+
+char s_rcv_buffer[20] = {0};
+char s_rcv_buffer2[50]  = {0};
+
+void palNetClientFunc(void const *argument)
+{
+    palStatus_t result = PAL_SUCCESS;
+    int32_t tmp = 0;
+    size_t sent = 0;
+    size_t read = 0;
+    palNetTestThreadData_t* dualSem = (palNetTestThreadData_t*)argument;
+    palSocketLength_t addrlen = 16;
+    //palSocketAddress_t address = { 0 };
+    palNetInterfaceInfo_t interfaceInfo;
+    const char* message = "GET / HTTP/1.0\r\n\r\n";
+
+    /*#C1*/
+    result = pal_osSemaphoreWait(dualSem->sem1, 500, &tmp);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#C2*/
+    result = pal_getNetInterfaceInfo(PAL_NET_TEST_LOCAL_LOOPBACK_IF_INDEX, &interfaceInfo);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#C3*/
+    uint16_t incoming_port = dualSem->port;
+    PAL_PRINTF("client port = %u", incoming_port);
+    result = pal_setSockAddrPort(&(interfaceInfo.address), incoming_port);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#C4*/
+    result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[2]);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#C5*/
+    result = pal_connect(g_testSockets[2], &(interfaceInfo.address), addrlen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#C6*/
+    result = pal_send(g_testSockets[2], message, 18, &sent);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#C7*/
+    result = pal_recv(g_testSockets[2], s_rcv_buffer, 15, &read);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#C8*/
+    pal_close(&g_testSockets[2]);
+
+    result = pal_osSemaphoreRelease(dualSem->sem2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+}
+
+/*! \brief /b ServerSocketScenario tests a TCP client-server scenario using device loopback.
+*
+* \note The test steps are divided into those in the server main thread (S1..S13) and those in the client thread (C1..C8).
+* The sequence below is an approximation of the actual order of execution.
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | S1 | Look up the IP address of loopback using `pal_getAddressInfo`.                           | PAL_SUCCESS |
+* | S2 | Create a blocking TCP server socket using `pal_socket`.                                | PAL_SUCCESS |
+* | S3 | Create a blocking TCP socket using `pal_socket`.                                       | PAL_SUCCESS |
+* | S4 | Set the port to test port in address structure using `pal_setSockAddrPort`.              | PAL_SUCCESS |
+* | S5 | Bind the server socket to the port and address using `pal_bind`.                             | PAL_SUCCESS |
+* | S6 | Create synchronization sepmaphores and set count to 0.                             | PAL_SUCCESS |
+* | S7 | Create a client thread with `BelowNormal` priority running `palNetClientFunc`.           | PAL_SUCCESS |
+* | C1 | Client thread blocks on client sepmaphore s1.                                      | PAL_SUCCESS |
+* | S8 | Listen to the server port using `pal_listen`.                                            | PAL_SUCCESS |
+* | S9 | Release the client sepmahore s1.                                                       | PAL_SUCCESS |
+* | S10 | Call `accept` (blocking) to accept a new connection (retry in case of failure).     | PAL_SUCCESS |
+* | C2 | Look up the IP address of the loopback using `pal_getAddressInfo`.                           | PAL_SUCCESS |
+* | C3 | Set the port to test port in the address structure using `pal_setSockAddrPort`.              | PAL_SUCCESS |
+* | C4 | Create a blocking TCP socket using `pal_socket`.                                       | PAL_SUCCESS |
+* | C5 | Connect to the server using `pal_connect`.                                               | PAL_SUCCESS |
+* | C6 | Send data to server.                                                               | PAL_SUCCESS |
+* | S11 | Receive data from the client.                                                         | PAL_SUCCESS |
+* | S12 | Send data to the client.                                                              | PAL_SUCCESS |
+* | C7 | Receive data from the server.                                                          | PAL_SUCCESS |
+* | C8 | Client thread cleanup - close the socket and release the semaphore.                        | PAL_SUCCESS |
+* | S13 | Cleanup: close sockets and delete semaphores.                                     | PAL_SUCCESS |
+*/
+
+TEST(pal_socket, ServerSocketScenario)
+{
+    palStatus_t result = PAL_SUCCESS;
+    palSocketAddress_t address2 = { 0 };
+    const char* messageOut = "HTTP/1.0 200 OK";
+    size_t sent = 0;
+    size_t read = 0;
+    palSocketLength_t addrlen = 16;
+
+    palSemaphoreID_t semaphoreID = NULLPTR;
+    palSemaphoreID_t semaphoreID2 = NULLPTR;
+    palNetTestThreadData_t dualSem = {0};
+    palThreadID_t threadID1 = NULLPTR;
+    int32_t tmp = 0;
+    palNetInterfaceInfo_t interfaceInfo;
+    memset(&interfaceInfo,0,sizeof(interfaceInfo));
+
+
+    /*#S1*/
+    result = pal_getNetInterfaceInfo(PAL_NET_TEST_LOCAL_LOOPBACK_IF_INDEX, &interfaceInfo);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)");
+        return;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#S2*/
+    result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM_SERVER, false, 0, &g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#S3*/
+    result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[1]);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#S4*/
+    uint32_t rand_number = 0;
+    uint16_t incoming_port;
+
+    for (int i=0; i<5; i++) {
+    	pal_osRandomBuffer((uint8_t*)&rand_number, sizeof(rand_number));
+        incoming_port = (uint16_t)(35400 + (rand_number % (40000 - 35400)));
+        PAL_PRINTF("server port = %u", incoming_port);
+
+        result = pal_setSockAddrPort(&(interfaceInfo.address), incoming_port);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+        /*#S5*/
+        result = pal_bind(g_testSockets[0], &(interfaceInfo.address), interfaceInfo.addressSize);
+
+        if (PAL_SUCCESS == result) {
+            PAL_PRINTF("bind succeeded on port %u", incoming_port);
+            break;
+        } else {
+            PAL_PRINTF("bind failed on port %u", incoming_port);
+        }
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#S6*/
+
+    // start client thread to connect to the server.
+    result = pal_osSemaphoreCreate(1 ,&semaphoreID);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    result = pal_osSemaphoreWait(semaphoreID, 1000, &tmp);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+
+    result = pal_osSemaphoreCreate(1 ,&semaphoreID2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    result = pal_osSemaphoreWait(semaphoreID2, 1000, &tmp);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    dualSem.sem1 = semaphoreID;
+    dualSem.sem2 = semaphoreID2;
+    dualSem.port = incoming_port;
+
+    /*#S7*/
+    result = pal_osThreadCreateWithAlloc(palNetClientFunc, &dualSem , PAL_osPriorityBelowNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#S8*/
+    result = pal_listen(g_testSockets[0], 10);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#S9*/
+    result = pal_osSemaphoreRelease(dualSem.sem1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+
+    PAL_PRINTF("waiting for connection:\r\n");
+    /*#S10*/
+    result = pal_accept(g_testSockets[0], &address2, &addrlen, &g_testSockets[1]);
+    PAL_PRINTF("after accept: %" PRIu32 "\r\n", result);
+    if (PAL_SUCCESS != result )
+    {
+         result = pal_accept(g_testSockets[0], &address2, &addrlen, &g_testSockets[1]);
+         PAL_PRINTF("after accept: %" PRIu32 "\r\n",result);
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#S11*/
+    result = pal_recv(g_testSockets[1], s_rcv_buffer2, 49, &read);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#S12*/
+    result = pal_send(g_testSockets[1], messageOut, 15, &sent);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+
+//cleanup
+
+/*#S13*/
+
+    pal_close(&g_testSockets[1]);
+    pal_close(&g_testSockets[0]);
+
+    result = pal_osSemaphoreWait(semaphoreID2, 5000, &tmp);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    pal_osDelay(2000);
+       pal_osThreadTerminate(&threadID1);
+    result = pal_osSemaphoreDelete(&semaphoreID);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_HEX(NULLPTR, semaphoreID);
+
+    result = pal_osSemaphoreDelete(&semaphoreID2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_HEX(NULLPTR, semaphoreID2);
+}
+
+
+
+PAL_PRIVATE volatile uint32_t s_callbackCounterNonBlock = 0;
+
+PAL_PRIVATE void nonBlockCallback(void * arg)
+{
+    s_callbackCounterNonBlock++;
+}
+
+#define PAL_NET_TEST_HTTP_HEADER_LEN 5
+
+/*! \brief /b nonBlockingAsyncTest checks the asynchronous- nonblocking socket scenario.
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Look up the IP address of the test server using `pal_getAddressInfo`.                        | PAL_SUCCESS |
+* | 2 | Create an asynchronous non-blocking TCP socket with `nonBlockCallback` as callback.     | PAL_SUCCESS |
+* | 3 | Set the port to test port in the address structure using `pal_setSockAddrPort`.              | PAL_SUCCESS |
+* | 4 | Connect the socket.                                                                    | PAL_SUCCESS or PAL_ERR_SOCKET_IN_PROGRES |
+* | 5 | Send a test message to the test server using `pal_send` (repeat until success).           | PAL_SUCCESS or PAL_ERR_SOCKET_IN_PROGRES |
+* | 6 | Wait for the callback and receive server response using `pal_recv` (repeat until success). | PAL_SUCCESS or PAL_ERR_SOCKET_WOULD_BLOCK|
+* | 7 | Close the socket.                                                                      | PAL_SUCCESS |
+*/
+TEST(pal_socket, nonBlockingAsyncTest)
+{
+    palStatus_t result = PAL_SUCCESS;
+    palSocketAddress_t address = { 0 };
+    const char* message = "GET / HTTP/1.0\r\nHost:10.45.48.68:8000\r\n\r\n";
+    size_t sent = 0;
+    char buffer[100] = { 0 };
+    size_t read = 0;
+    s_callbackcounter = 0;
+    palSocketLength_t addrlen = 0;
+    int32_t waitIterations = 0;
+
+    /*#1*/
+    result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME, &address, &addrlen);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)");
+        return;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+    /*#2*/
+    result = pal_asynchronousSocketWithArgument(PAL_AF_INET, PAL_SOCK_STREAM, true, 0, nonBlockCallback, "non-blockSocketCallbackArg", &g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#3*/
+    result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_HTTP_PORT);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#4*/
+    result = pal_connect(g_testSockets[0], &address, 16);
+    if (PAL_ERR_SOCKET_IN_PROGRES == result)
+    {
+        result = pal_connect(g_testSockets[0], &address, 16);
+        if ((result != PAL_SUCCESS) && (result != PAL_ERR_SOCKET_ALREADY_CONNECTED) && (result != PAL_ERR_SOCKET_IN_PROGRES) && (result != PAL_ERR_SOCKET_WOULD_BLOCK)) // check expected result codes.(connection should either be in progress or connected already)
+        {
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        }
+        pal_osDelay(400);
+    }
+    else
+    {
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    }
+    s_callbackCounterNonBlock = 0;
+
+    /*#5*/
+    result = pal_send(g_testSockets[0], message, strlen(message), &sent);
+
+    while (PAL_ERR_SOCKET_IN_PROGRES == result)
+    {
+        pal_osDelay(100);
+        result = pal_send(g_testSockets[0], message, strlen(message), &sent);
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#6*/
+    result = pal_recv(g_testSockets[0], buffer, PAL_NET_TEST_HTTP_HEADER_LEN, &read); // may block
+    while ((PAL_ERR_SOCKET_WOULD_BLOCK == result) && (10 > waitIterations ))
+    {
+        s_callbackCounterNonBlock = 0;
+        while (s_callbackCounterNonBlock == 0)
+        {
+            waitIterations++;
+            pal_osDelay(100);
+        }
+        result = pal_recv(g_testSockets[0], buffer, PAL_NET_TEST_HTTP_HEADER_LEN, &read); // shouldnt block
+    }
+
+    /*#7*/
+    pal_close(&g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT(read >= 4);
+    TEST_ASSERT(buffer[0] == 'H' && buffer[1] == 'T'&& buffer[2] == 'T' && buffer[3] == 'P');
+    TEST_ASSERT(s_callbackCounterNonBlock > 0);
+
+#endif // PAL_NET_ASYNCHRONOUS_SOCKET_API
+}
+
+/*! \brief /b tProvUDPTest tests UDP socket send/receive and checks that we get the correct error for receive timeout.
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a blocking UDP socket using `pal_socket`.                                       | PAL_SUCCESS |
+* | 2 | Look up the IP address of the test server using `pal_getAddressInfo`.                        | PAL_SUCCESS |
+* | 3 | Set the port to test port in the address structure using `pal_setSockAddrPort`.              | PAL_SUCCESS |
+* | 4 | Set socket timeouts using `pal_setSocketOptions`.                                    | PAL_SUCCESS |
+* | 5 | Send a test message (short HTTP request) to test the server using `pal_send`.                 | PAL_SUCCESS |
+* | 6 | Receive the (blocking) server response using `pal_recv`.                                 | PAL_SUCCESS |
+* | 7 | Receive  the (blocking) server response again using `pal_recv` and fail.                  | PAL_ERR_SOCKET_WOULD_BLOCK |
+* | 8 | Close the socket.                                                                      | PAL_SUCCESS |
+*/
+TEST(pal_socket, tProvUDPTest)
+{
+    palStatus_t result = PAL_SUCCESS;
+    palSocketAddress_t address = { 0,{0} };
+    uint8_t buffer[100] = { 0 };
+    uint8_t buffer_dns[33] = { 0x8e, 0xde, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x61, 0x72, 0x73, 0x74, 0x65, 0x63, 0x68, 0x6e, 0x69, 0x63, 0x61, 0x03, 0x63, 0x6f, 0x6d, 0x00, 0x00, 0x01, 0x00, 0x01 };
+    size_t sent = 0;
+    size_t read = 0;
+    palSocketLength_t addrlen = 16;
+    int timeout = PAL_MILLI_PER_SECOND;
+
+    /*#1*/
+    result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM, false, 0, &g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#2*/
+    result = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME_UDP, &address, &addrlen);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)");
+        goto end;
+    }
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#3*/
+    result = pal_setSockAddrPort(&address, PAL_NET_TEST_SERVER_UDP_PORT);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#4*/
+    result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO, &timeout, sizeof(timeout));
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    timeout = 1000;
+    result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO, &timeout, sizeof(timeout));
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#5*/
+    result = pal_sendTo(g_testSockets[0], buffer_dns, sizeof(buffer_dns), &address, addrlen, &sent);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_HEX(sent, sizeof(buffer_dns));
+
+    /*#6*/
+    result = pal_receiveFrom(g_testSockets[0], buffer, 16, NULL, NULL, &read);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL(read, 16);
+
+    /*#7*/
+    result = pal_receiveFrom(g_testSockets[0], buffer, 100, NULL, NULL, &read); //  should get timeout
+    TEST_ASSERT_EQUAL_HEX(result, PAL_ERR_SOCKET_WOULD_BLOCK);
+
+end:
+    /*#8*/
+    pal_close(&g_testSockets[0]);
+}
+
+
+PAL_PRIVATE void fillUDPTestBuffer(pal_udp_test_data_t *data, uint8_t* buffer)
+{
+    memset(buffer, 0, data->bufferSize);
+    data->chunkSize = (data->messageSize - data->totalSize > data->bufferSize) ? data->bufferSize : (data->messageSize - data->totalSize);
+    memset(buffer, ++(data->currentValue), data->chunkSize);
+    data->totalSize += data->chunkSize;
+}
+
+// UDP test sender thread function.
+PAL_PRIVATE void socketUDPBufferedTestSender(const void *arg)
+{
+    palStatus_t result = PAL_SUCCESS;
+    pal_udp_test_data_t *data = (pal_udp_test_data_t*)arg; // cast from const to non-const
+    size_t sent = 0, totalSent = 0;
+
+    g_testSendBuffer = (uint8_t*)malloc(sizeof(uint8_t) * data->bufferSize);
+    TEST_ASSERT_NOT_EQUAL(NULLPTR, g_testSendBuffer);
+
+    data->totalSize = 0;
+    data->chunkSize = 0;
+    data->currentValue = data->startValue;
+    while (totalSent != data->messageSize)
+    {
+        fillUDPTestBuffer(data, g_testSendBuffer);
+        result = pal_sendTo(g_testSockets[0], g_testSendBuffer, data->chunkSize, &(data->interfaceInfo.address), data->interfaceInfo.addressSize, &sent);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        totalSent += sent;
+        pal_osDelay(5); // allow some time for the RX bits to be set
+    };
+
+    free(g_testSendBuffer);
+    g_testSendBuffer = NULLPTR;
+}
+
+/*! \brief Test UDP socket read in chunks
+*
+* \note The test generates data and calculates its hash, then this data is re-generated from a dedicated thread and 
+* received on the current thread which calculates the received data hash and compares it to the original hash
+*
+* @param[in]    bufSize - the read buffer size
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize the MD context.                                                           | PAL_SUCCESS |
+* | 2 | Allocate buffer.                                                                     | PAL_SUCCESS |
+* | 3 | Generate data incrementally and update the MD context.                               | PAL_SUCCESS |
+* | 4 | Get the hash output size and validate it.                                            | PAL_SUCCESS |
+* | 5 | Get the calculated hash.                                                             | PAL_SUCCESS |
+* | 6 | Free the MD context resources.                                                       | PAL_SUCCESS |
+* | 7 | Get the interface address.                                                           | PAL_SUCCESS |
+* | 8 | Create a (blocking) UDP socket.                                                      | PAL_SUCCESS |
+* | 9 | Set the socket port and set send/receive timeouts.                                   | PAL_SUCCESS |
+* | 10 | Bind the socket.                                                                    | PAL_SUCCESS |
+* | 11 | Initialize the MD context.                                                          | PAL_SUCCESS |
+* | 12 | Launch the data sender thread.                                                      | PAL_SUCCESS |
+* | 13 | Read data from the socket until there's no more data or all data has been received. | PAL_SUCCESS |
+* | 14 | Update the MD context.                                                              | PAL_SUCCESS |
+* | 15 | Terminate the sending thread.                                                       | PAL_SUCCESS |
+* | 16 | Close the socket.                                                                   | PAL_SUCCESS |
+* | 17 | Get the hash output size and validate it.                                           | PAL_SUCCESS |
+* | 18 | Get the calculated hash and compare it.                                             | PAL_SUCCESS |
+* | 19 | Free the MD context resources.                                                      | PAL_SUCCESS |
+* | 20 | Free allocated buffer.                                                              | PAL_SUCCESS |
+*/
+PAL_PRIVATE void socketUDPBuffered(size_t bufSize)
+{
+    palStatus_t result = PAL_SUCCESS;
+    pal_udp_test_data_t data = { PAL_NET_TEST_BUFFERED_UDP_MESSAGE_SIZE, bufSize, 0 };
+    uint8_t expectedHash[PAL_SHA256_SIZE] = { 0 }, actualHash[PAL_SHA256_SIZE] = { 0 };
+    size_t read = 0, totalRead = 0, hashlen = 0;
+    int timeout = PAL_MILLI_PER_SECOND;
+    palMDHandle_t handle = NULLPTR;
+    palThreadID_t thread = NULLPTR;
+    
+    /*#1*/
+    result = pal_mdInit(&handle, PAL_SHA256);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_NOT_EQUAL(NULLPTR, handle);
+
+    /*#2*/
+    g_testRecvBuffer = (uint8_t*)malloc(sizeof(uint8_t) * bufSize);
+    TEST_ASSERT_NOT_EQUAL(NULLPTR, g_testRecvBuffer);
+
+    /*#3*/
+    data.totalSize = data.chunkSize = 0;
+    data.currentValue = data.startValue;
+    while (data.totalSize != data.messageSize)
+    {
+        fillUDPTestBuffer(&data, g_testRecvBuffer);
+        result = pal_mdUpdate(handle, g_testRecvBuffer, data.chunkSize);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    };
+
+    /*#4*/
+    result = pal_mdGetOutputSize(handle, &hashlen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_HEX(PAL_SHA256_SIZE, hashlen);
+
+    /*#5*/
+    result = pal_mdFinal(handle, expectedHash);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#6*/
+    result = pal_mdFree(&handle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#7*/
+    memset(&(data.interfaceInfo), 0, sizeof(data.interfaceInfo));
+    result = pal_getNetInterfaceInfo(0, &(data.interfaceInfo));
+    if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)");
+        goto end;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#8*/
+    result = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM, false, 0, &g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#9*/
+    result = pal_setSockAddrPort(&(data.interfaceInfo.address), PAL_NET_TEST_BUFFERED_UDP_PORT);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO, &timeout, sizeof(timeout));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO, &timeout, sizeof(timeout));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#10*/
+    result = pal_bind(g_testSockets[0], &(data.interfaceInfo.address), data.interfaceInfo.addressSize);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#11*/
+    handle = NULLPTR;
+    result = pal_mdInit(&handle, PAL_SHA256);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_NOT_EQUAL(NULLPTR, handle);
+
+    /*#12*/
+    result = pal_osThreadCreateWithAlloc(socketUDPBufferedTestSender, &data, PAL_osPriorityNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &thread);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_NOT_EQUAL(NULLPTR, thread);
+
+    /*#13*/
+    do
+    {
+        read = 0;
+        memset(g_testRecvBuffer, 0, data.bufferSize);
+        result = pal_receiveFrom(g_testSockets[0], g_testRecvBuffer, data.bufferSize, &(data.interfaceInfo.address), &(data.interfaceInfo.addressSize), &read);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        /*#14*/
+        result = pal_mdUpdate(handle, g_testRecvBuffer, read);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+        totalRead += read;
+    } while (read > 0 && totalRead < data.messageSize);
+
+    /*#15*/
+    result = pal_osThreadTerminate(&thread);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#16*/
+    result = pal_close(&g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#17*/
+    hashlen = 0;
+    result = pal_mdGetOutputSize(handle, &hashlen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_HEX(PAL_SHA256_SIZE, hashlen);
+
+    /*#18*/
+    result = pal_mdFinal(handle, actualHash);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_MEMORY(expectedHash, actualHash, PAL_SHA256_SIZE);
+
+    /*#19*/
+    result = pal_mdFree(&handle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#20*/
+end:
+    free(g_testRecvBuffer);
+    g_testRecvBuffer = NULLPTR;
+}
+
+/*! \brief Test function UDP socket read in small chunks
+*
+** \test
+*/
+TEST(pal_socket, socketUDPBufferedSmall)
+{
+    socketUDPBuffered(PAL_NET_TEST_BUFFERED_UDP_BUF_SIZE_SMALL);
+}
+
+/*! \brief Test function UDP socket read in large chunks
+*
+** \test
+*/
+TEST(pal_socket, socketUDPBufferedLarge)
+{
+    socketUDPBuffered(PAL_NET_TEST_BUFFERED_UDP_BUF_SIZE_LARGE);
+}
+
+#ifdef __LINUX__ // Linux CI tests for socketTCPBufferedSmall & socketTCPBufferedLarge must use an ipv4 address in order to connect to the external host
+#if PAL_SUPPORT_IP_V4
+PAL_PRIVATE palStatus_t getAddressInfoIPv4(char const *url, palSocketAddress_t *address, palSocketLength_t* addressLength)
+{
+    struct addrinfo *info = NULLPTR;
+    struct addrinfo hints = { 0 };
+    struct sockaddr_in *sockAddress = NULLPTR;
+    palIpV4Addr_t ipV4Address = { 0 };
+    int ret;
+    palStatus_t result;
+
+    hints.ai_family = AF_INET;
+    ret = getaddrinfo(url, NULL, &hints, &info);
+    TEST_ASSERT_EQUAL(0, ret);
+    TEST_ASSERT_NOT_EQUAL(NULLPTR, info);
+    TEST_ASSERT_EQUAL(AF_INET, info->ai_family);
+
+    sockAddress = (struct sockaddr_in*)info->ai_addr;
+    memcpy(ipV4Address, &(sockAddress->sin_addr), PAL_IPV4_ADDRESS_SIZE);
+    freeaddrinfo(info);
+
+    result = pal_setSockAddrIPV4Addr(address, ipV4Address);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    *addressLength = sizeof(struct sockaddr_in);
+    return result;
+}
+#endif
+#endif
+
+/*! \brief Test TCP socket read in chunks
+*
+* \note The test attempts to perform an HTTP get request to a google (jquery) CDN, read the file in chunks (ignoring HTTP headers) and compare its hash to a pre-known hash using SHA256.
+*
+* @param[in]    bufSize - the read buffer size
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a (blocking) TCP socket.                                                                     | PAL_SUCCESS |
+* | 2 | Look up the IP address of the CDN server.                                                           | PAL_SUCCESS |
+* | 3 | Set the port to the CDN server's HTTP port and set send/receive timeouts.                           | PAL_SUCCESS |
+* | 4 | Connect the socket to the CDN server.                                                               | PAL_SUCCESS |
+* | 5 | Send an HTTP get request to the CDN server.                                                         | PAL_SUCCESS |
+* | 6 | Initialize the MD context.                                                                          | PAL_SUCCESS |
+* | 7 | Allocate HTTP response buffer.                                                                      | PAL_SUCCESS |
+* | 8 | Read the server's response until there's no more data to read.                                      | PAL_SUCCESS |
+* | 9 | If we're done dealing with the HTTP headers then update the MD context.                             | PAL_SUCCESS |
+* | 10 | Locate the end of the HTTP headers in the server's response (HTTP headers end with a double CRLF). | PAL_SUCCESS |
+* | 11 | Update the MD context.                                                                             | PAL_SUCCESS |
+* | 12 | Close the socket.                                                                                  | PAL_SUCCESS |
+* | 13 | Get the hash output size and validate it.                                                          | PAL_SUCCESS |
+* | 14 | Get the calculated hash and compare it to the pre-known hash.                                      | PAL_SUCCESS |
+* | 15 | Free the MD context resources.                                                                     | PAL_SUCCESS |
+* | 16 | Free HTTP response buffer.                                                                         | PAL_SUCCESS |
+*/
+PAL_PRIVATE void socketTCPBuffered(size_t bufSize)
+{
+    palStatus_t result = PAL_SUCCESS;
+    palSocketAddress_t address = { 0 };
+    palSocketLength_t addrlen = 0;
+    int timeout = 5000;
+    uint8_t next = '\r', state = 0;
+    size_t read = 0, sent = 0, hashlen = 0;
+    bool body = false;
+    palMDHandle_t handle = NULLPTR;
+    uint8_t actualHash[PAL_SHA256_SIZE] = { 0 };
+    const uint8_t expectedHash[] = // pre-calculated jquery.js 3.2.1 SHA256
+    {
+        0x0d, 0x90, 0x27, 0x28, 0x9f, 0xfa, 0x5d, 0x9f, 0x6c, 0x8b, 0x4e, 0x07, 0x82, 0xbb, 0x31, 0xbb, 
+        0xff, 0x2c, 0xef, 0x5e, 0xe3, 0x70, 0x8c, 0xcb, 0xcb, 0x7a, 0x22, 0xdf, 0x91, 0x28, 0xbb, 0x21
+    };
+      
+
+
+    /*#2*/    
+    result = test_getAddressInfo(PAL_NET_TEST_GOOGLE_CDN_HOST, &address, &addrlen);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)");
+        return;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#1*/
+    result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#3*/
+    result = pal_setSockAddrPort(&address, PAL_NET_TEST_GOOGLE_CDN_HOST_PORT);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO, &timeout, sizeof(timeout));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO, &timeout, sizeof(timeout));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#4*/
+    result = pal_connect(g_testSockets[0], &address, addrlen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#5*/
+    result = pal_send(g_testSockets[0], PAL_NET_TEST_GOOGLE_CDN_REQUEST, sizeof(PAL_NET_TEST_GOOGLE_CDN_REQUEST) - 1, &sent);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#6*/
+    result = pal_mdInit(&handle, PAL_SHA256);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_NOT_EQUAL(NULLPTR, handle);
+    
+    /*#7*/
+    g_testRecvBuffer = (uint8_t*)malloc(sizeof(uint8_t) * bufSize + 1);
+    TEST_ASSERT_NOT_EQUAL(NULLPTR, g_testRecvBuffer);
+    
+    /*#8*/
+    do
+    {
+        read = 0;
+        memset(g_testRecvBuffer, 0, bufSize + 1);
+        result = pal_recv(g_testSockets[0], g_testRecvBuffer, bufSize, &read);
+        TEST_ASSERT_TRUE((PAL_SUCCESS == result && read > 0) || (PAL_ERR_SOCKET_CONNECTION_CLOSED == result && read == 0));
+
+        /*#9*/
+        if (body)
+        {
+            result = pal_mdUpdate(handle, g_testRecvBuffer, read);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+            continue;
+        }
+
+        /*#10*/
+        for (size_t i = 0; i < bufSize; i++) // dealing with the HTTP headers - headers end on a double CRLF
+        {
+            if (g_testRecvBuffer[i] == next)
+            {
+                next = (next == '\r') ? '\n' : '\r';
+                state = state | (state + 1);
+                if (state == 0xf)
+                {
+                    /*#11*/
+                    body = true;
+                    result = pal_mdUpdate(handle, (g_testRecvBuffer + i + 1), strlen(((char*)g_testRecvBuffer) + i + 1));
+                    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+                    break;
+                }
+            }
+            else if (state != 0)
+            {
+                next = '\r';
+                state = 0;
+            }
+        }
+    } while (read > 0);
+
+    /*#12*/
+    result = pal_close(&g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+    /*#13*/
+    result = pal_mdGetOutputSize(handle, &hashlen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_HEX(PAL_SHA256_SIZE, hashlen);
+
+    /*#14*/
+    result = pal_mdFinal(handle, actualHash);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    TEST_ASSERT_EQUAL_MEMORY(expectedHash, actualHash, PAL_SHA256_SIZE);
+
+    /*#15*/
+    result = pal_mdFree(&handle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);    
+
+    /*#16*/
+    free(g_testRecvBuffer);
+    g_testRecvBuffer = NULLPTR;
+
+}
+
+/*! \brief Test function TCP socket read in small chunks
+*
+** \test
+*/
+TEST(pal_socket, socketTCPBufferedSmall)
+{
+    socketTCPBuffered(PAL_NET_TEST_BUFFERED_TCP_BUF_SIZE_SMALL);
+}
+
+/*! \brief Test function TCP socket read in large chunks
+*
+** \test
+*/
+TEST(pal_socket, socketTCPBufferedLarge)
+{
+    socketTCPBuffered(PAL_NET_TEST_BUFFERED_TCP_BUF_SIZE_LARGE);
+}
+
+// flag marking if the pal_getAddressInfoAsync callback has been invoked
+PAL_PRIVATE bool g_getAddressInfoAsyncCallbackInvoked = false;
+
+// callback invoked from the call to pal_getAddressInfoAsync
+PAL_PRIVATE void getAddressInfoAsyncCallback(const char* url, palSocketAddress_t* address, palSocketLength_t* addressLength, palStatus_t status, void* arg)
+{
+    palStatus_t* statusArg = (palStatus_t*)arg;
+    *statusArg = status;
+    g_getAddressInfoAsyncCallbackInvoked = true;
+}
+
+/*! \brief Test get address info asynchronously
+** \test
+* | # |    Step                                                                                               |  Expected   |
+* |---|-------------------------------------------------------------------------------------------------------|-------------|
+* | 1 | Invoke a synchronous get address info so we'll have something to compare to the asynchronous results. | PAL_SUCCESS |
+* | 2 | Invoke an asynchronous get address info.                                                              | PAL_SUCCESS |
+* | 3 | Wait until the asynchronous get address info callback is called or max wait time has ended.           | PAL_SUCCESS |
+* | 4 | Compare the synchronous results to the asynchronous results.                                          | PAL_SUCCESS |
+*/
+TEST(pal_socket, getAddressInfoAsync)
+{
+    int counter = 0;
+    palSocketAddress_t addressSync = { 0 }, addressAsync = { 0 };
+    palSocketLength_t addrlenSync = 0, addrlenAsync = 0;
+    palStatus_t status, statusCallback;
+
+    /*#1*/
+    status = pal_getAddressInfo(PAL_NET_TEST_SERVER_NAME, &addressSync, &addrlenSync);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == status) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == status))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)");
+        return;
+    }
+    TEST_ASSERT_TRUE_MESSAGE((PAL_SUCCESS == status), "synchronous call to pal_getAddressInfo failed");
+
+    /*#2*/
+    statusCallback = PAL_ERR_SOCKET_ERROR_BASE;
+    status = pal_getAddressInfoAsync(PAL_NET_TEST_SERVER_NAME, &addressAsync, &addrlenAsync, getAddressInfoAsyncCallback, &statusCallback);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#3*/
+    while ((!g_getAddressInfoAsyncCallbackInvoked) && counter < 20) // wait until callback is invoked or max time of ~5 seconds
+    {
+        counter++;
+        pal_osDelay(250);
+    }
+    TEST_ASSERT_TRUE_MESSAGE(g_getAddressInfoAsyncCallbackInvoked, "getAddressInfoAsyncCallback was not invoked");
+    g_getAddressInfoAsyncCallbackInvoked = false;
+
+    /*#4*/
+    TEST_ASSERT_EQUAL_HEX(status, statusCallback);
+    TEST_ASSERT_EQUAL_HEX(addrlenSync, addrlenAsync);
+    TEST_ASSERT_EQUAL_HEX(addressSync.addressType, addressAsync.addressType);
+    TEST_ASSERT_EQUAL_MEMORY(addressSync.addressData, addressAsync.addressData, PAL_NET_MAX_ADDR_SIZE);
+
+}
+
+/*! \brief Test pal socket APIs input parameter validations
+** \test
+*/
+TEST(pal_socket, socketApiInputParamValidation)
+{
+#ifdef DEBUG
+    palStatus_t status;
+    palSocketAddress_t addr;
+    addr.addressType = PAL_AF_UNSPEC;
+    uint16_t port = 0;
+
+    status = pal_registerNetworkInterface(NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_setSockAddrPort(NULL, 0);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_setSockAddrPort(&addr, 0);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY, status);
+#if PAL_SUPPORT_IP_V4
+    status = pal_setSockAddrIPV4Addr(NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_getSockAddrIPV4Addr(NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_getSockAddrIPV4Addr(&addr, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY, status);
+#endif
+#if PAL_SUPPORT_IP_V6
+    status = pal_setSockAddrIPV6Addr(NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_getSockAddrIPV6Addr(NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_getSockAddrIPV6Addr(&addr, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY, status);
+#endif
+    status = pal_getSockAddrPort(NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_getSockAddrPort(&addr, &port);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY, status);
+    status = pal_setSocketOptions(NULL, 0, NULL, 0);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_isNonBlocking(NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_bind(NULL, NULL, 0);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_receiveFrom(NULL, NULL, 0, NULL, NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_sendTo(NULL, NULL, 0, NULL, 0, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_close(NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_getNumberOfNetInterfaces(NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_getNetInterfaceInfo(0, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+#if PAL_NET_TCP_AND_TLS_SUPPORT    
+    status = pal_accept(NULL, NULL, NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_connect(NULL, NULL, 0);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_recv(NULL, NULL, 0, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_send(NULL, NULL, 0, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+#endif // PAL_NET_TCP_AND_TLS_SUPPORT
+#if PAL_NET_ASYNCHRONOUS_SOCKET_API
+    status = pal_asynchronousSocketWithArgument(PAL_AF_UNSPEC, PAL_SOCK_DGRAM, false, 0, NULL, NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+#endif // PAL_NET_ASYNCHRONOUS_SOCKET_API
+#if PAL_NET_DNS_SUPPORT
+    status = pal_getAddressInfo(NULL, NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    status = pal_getAddressInfoAsync(NULL, NULL, NULL, NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+#endif // PAL_NET_DNS_SUPPORT
+#endif //DEBUG
+}
+
+PAL_PRIVATE void keepAliveFunc(bool keepalive)
+{
+    palStatus_t result = PAL_SUCCESS;
+    palSocketAddress_t address = { 0 };
+    char buffer[100] = { 0 };
+    size_t read = 0;
+    palSocketLength_t addrlen = 0;
+    int timeout = PAL_MILLI_PER_SECOND;
+    int KeepAliveOn = 0, KeepAliveIntvl = 0, KeepAliveIdle = 0;
+    int keepaliveNumber=0;
+
+    if (keepalive)
+    {
+    	KeepAliveOn=1;
+    	KeepAliveIntvl=1;
+    	KeepAliveIdle =1;
+    }
+    /*#1*/
+    result = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#2*/
+    result = pal_getAddressInfo(PAL_TEST_KEEPALIVE_SERVER_ADDRESS, &address, &addrlen);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == result) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == result))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration)");
+        goto end;
+    }
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#3*/
+    result = pal_setSockAddrPort(&address, PAL_TEST_SERVER_KEEPALIVE_PORT);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    result = pal_setSocketOptions(g_testSockets[0], PAL_SO_SNDTIMEO, &timeout, sizeof(timeout));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+    result = pal_setSocketOptions(g_testSockets[0], PAL_SO_RCVTIMEO, &timeout, sizeof(timeout));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+
+	result = pal_setSocketOptions(g_testSockets[0], PAL_SO_KEEPALIVE, &KeepAliveOn, sizeof(KeepAliveOn));
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+	if (keepalive) {
+		result = pal_setSocketOptions(g_testSockets[0], PAL_SO_KEEPIDLE, &KeepAliveIdle, sizeof(KeepAliveIdle));
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+		result = pal_setSocketOptions(g_testSockets[0], PAL_SO_KEEPINTVL, &KeepAliveIntvl, sizeof(KeepAliveIntvl));
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, result);
+	}
+
+    /*#4*/
+    result = pal_connect(g_testSockets[0], &address, 16);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+
+    /*#6*/
+    while (result != PAL_ERR_SOCKET_CONNECTION_CLOSED)
+    {
+        result = pal_recv(g_testSockets[0], buffer, sizeof(buffer)-1 , &read);
+        if (result != PAL_ERR_SOCKET_CONNECTION_CLOSED)
+        {
+			if((read != 0) && (buffer[0]!=0))
+            {
+				keepaliveNumber=atoi(buffer);
+				if (keepalive){
+					TEST_ASSERT_TRUE(keepaliveNumber > PAL_TEST_KEEPALIVE_NUM_OF_ACK);
+				}
+				else{
+					TEST_ASSERT_TRUE(keepaliveNumber < PAL_TEST_KEEPALIVE_NUM_OF_ACK);
+				}
+				break;
+            }
+        }
+
+    }
+end:
+    result = pal_close(&g_testSockets[0]);
+    TEST_ASSERT_EQUAL_HEX( PAL_SUCCESS, result);
+}
+
+/*! \brief Test keepAlive On/Off
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a blocking TCP socket using `pal_socket`.                                         			| PAL_SUCCESS |
+* | 2 | Look up the IP address of the test server using `pal_getAddressInfo`.                          		| PAL_SUCCESS |
+* | 3 | Set the port to a test port in the address structure using `pal_setSockAddrPort` and set timeout. 	| PAL_SUCCESS |
+* | 4 | Set keepalive socket options : if keepalive is on set keepalibe idel and intvl  . 					| PAL_SUCCESS |
+* | 5 | Connect the socket to the test server using `pal_connect`.                                    	 	| PAL_SUCCESS |
+* | 6 | Receive (blocking) the server's response using `pal_recv` and check it keepalive packates sent. 	| PAL_SUCCESS |
+* | 7 | Close the socket.                                                                        			| PAL_SUCCESS |
+*/
+
+TEST(pal_socket, keepaliveOn)
+{
+	keepAliveFunc(true);
+}
+
+TEST(pal_socket, keepaliveOff)
+{
+	keepAliveFunc(false);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Networking/pal_socket_test_runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "unity.h"
+#include "unity_fixture.h"
+#include "pal.h"
+#define PAL_RUN_ALL_TESTS 1
+
+// pal Socket API tests
+TEST_GROUP_RUNNER(pal_socket)
+{
+    RUN_TEST_CASE(pal_socket, socketUDPCreationOptionsTest);
+    RUN_TEST_CASE(pal_socket, basicTCPclientSendRecieve);
+    RUN_TEST_CASE(pal_socket, basicUDPclientSendRecieve);
+    RUN_TEST_CASE(pal_socket, basicSocketScenario3);
+    RUN_TEST_CASE(pal_socket, tProvUDPTest);
+    RUN_TEST_CASE(pal_socket, nonBlockingAsyncTest);
+    RUN_TEST_CASE(pal_socket, ServerSocketScenario);
+    RUN_TEST_CASE(pal_socket, socketTCPBufferedSmall);
+    RUN_TEST_CASE(pal_socket, socketTCPBufferedLarge);
+    RUN_TEST_CASE(pal_socket, socketUDPBufferedSmall);
+    RUN_TEST_CASE(pal_socket, socketUDPBufferedLarge);
+    RUN_TEST_CASE(pal_socket, getAddressInfoAsync);
+    RUN_TEST_CASE(pal_socket, keepaliveOn);
+    RUN_TEST_CASE(pal_socket, keepaliveOff);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/RTOS/pal_rtos_test.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1590 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal.h"
+#include "unity.h"
+#include "unity_fixture.h"
+#include "pal_rtos_test_utils.h"
+#include <string.h>
+#include <stdlib.h>
+#include "sotp.h"
+#include "pal_plat_rtos.h"
+
+TEST_GROUP(pal_rtos);
+
+//Sometimes you may want to get local data in a module,
+//for example if you need to pass a reference.
+//However, you should usually avoid this.
+//extern int Counter;
+threadsArgument_t g_threadsArg = {0};
+timerArgument_t g_timerArgs = {0};
+palMutexID_t mutex1 = NULLPTR;
+palMutexID_t mutex2 = NULLPTR;
+palSemaphoreID_t semaphore1 = NULLPTR;
+palRecursiveMutexParam_t* recursiveMutexData = NULL;
+#define PAL_RUNNING_TEST_TIME   5  //estimation on length of test in seconds
+#define PAL_TEST_HIGH_RES_TIMER 100
+#define PAL_TEST_HIGH_RES_TIMER2 10
+#define PAL_TEST_PERCENTAGE_LOW 95
+#define PAL_TEST_PERCENTAGE_HIGH 105
+#define PAL_TEST_PERCENTAGE_HUNDRED  100
+
+//Forward declarations
+void palRunThreads(void);
+
+
+TEST_SETUP(pal_rtos)
+{
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_init();
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+}
+
+TEST_TEAR_DOWN(pal_rtos)
+{
+    if (NULL != recursiveMutexData)
+    {
+        if (recursiveMutexData->higherPriorityThread != NULLPTR)
+        {
+            pal_osThreadTerminate(&(recursiveMutexData->higherPriorityThread));
+        }
+        if (recursiveMutexData->lowerPriorityThread != NULLPTR)
+        {
+            pal_osThreadTerminate(&(recursiveMutexData->lowerPriorityThread));
+        }
+        if (recursiveMutexData->mtx != NULLPTR)
+        {
+            pal_osMutexDelete(&(recursiveMutexData->mtx));
+        }
+        if (recursiveMutexData->sem != NULLPTR)
+        {
+            pal_osSemaphoreDelete(&recursiveMutexData->sem);
+        }
+        free(recursiveMutexData);
+        recursiveMutexData = NULL;
+    }
+    pal_destroy();
+}
+
+/*! \brief Sanity check of the kernel system tick API.
+ * Fails if system tic value is zero (**note:** this can sometimes happen on wrap-around).
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Get current tick count using `pal_osKernelSysTick` and check that it is not 0.  | PAL_SUCCESS |
+ */
+TEST(pal_rtos, pal_osKernelSysTick_Unity)
+{
+    uint32_t tick1 = 0, tick2 = 0;
+    /*#1*/
+    tick1 = pal_osKernelSysTick();
+    PAL_PRINTF("%" PRIu32 " %" PRIu32 "\n", tick1, tick2);
+
+    TEST_ASSERT_TRUE(tick2 != tick1);
+}
+
+/*! \brief Sanity check of the kernel system tick API.
+ * Fails if two calls return the same `sysTick` value.
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Get current tick count using `pal_osKernelSysTick`.       | PAL_SUCCESS |
+ * | 2 | Get current tick count using `pal_osKernelSysTick`.       | PAL_SUCCESS |
+ * | 3 | Check that the two tick count values are not the same. | PAL_SUCCESS |
+ */
+TEST(pal_rtos, pal_osKernelSysTick64_Unity)
+{
+    uint64_t tick1 = 0, tick2 = 0;
+    /*#1*/
+    tick1 = pal_osKernelSysTick();
+    /*#2*/
+    tick2 = pal_osKernelSysTick();
+    /*#3*/
+    TEST_ASSERT_TRUE(tick2 >= tick1);
+}
+
+/*! \brief Check the conversion from a non-zero `sysTick` value to microseconds.
+ * Verify that the result is not 0.
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Convert a nubmer in `sysTicks` to microseconds using `pal_osKernelSysTickMicroSec` and check it is not 0. | PAL_SUCCESS |
+ */
+TEST(pal_rtos, pal_osKernelSysTickMicroSec_Unity)
+{
+    uint64_t tick = 0;
+    uint64_t microSec = 2000 * 1000;
+    /*#1*/
+    tick = pal_osKernelSysTickMicroSec(microSec);
+    TEST_ASSERT_TRUE(0 != tick);
+}
+
+/*! \brief Sanity check of non-zero values conversion between microseconds to ticks to milliseconds.
+ * Verify that the result is correct when converting the input (microseconds) to the test output (milliseconds).
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Convert a nubmer in `sysTicks` to mircorseconds using `pal_osKernelSysTickMicroSec` and check it is not 0. | PAL_SUCCESS |
+ * | 2 | Convert a nubmer in `sysTicks` to milliseconds using `pal_osKernelSysMilliSecTick` and check the returned value. | PAL_SUCCESS |
+ */
+TEST(pal_rtos, pal_osKernelSysMilliSecTick_Unity)
+{
+    uint64_t tick = 0;
+    uint64_t microSec = 200 * 1000;
+    uint64_t milliseconds = 0;
+    /*#1*/
+    tick = pal_osKernelSysTickMicroSec(microSec);
+    TEST_ASSERT_TRUE(0 != tick);
+    /*#2*/
+    milliseconds = pal_osKernelSysMilliSecTick(tick);
+    TEST_ASSERT_EQUAL(microSec/1000, milliseconds);
+   
+}
+
+/*! \brief Verify that the tick frequency function returns a non-zero value.
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Get the kernel `sysTick` frequency and check that it is positive.     | PAL_SUCCESS |
+ */
+TEST(pal_rtos, pal_osKernelSysTickFrequency_Unity)
+{
+    uint64_t frequency = 0;
+    /*#1*/
+    frequency = pal_osKernelSysTickFrequency();
+
+    TEST_ASSERT_TRUE(frequency > 0);
+}
+
+/*! \brief Sanity check for the Delay API, verifying that `sysTick` increments after delay.
+ * The test reads two system tick values. Between the two calls, it calls the delay function and
+ * verifies that the tick values are different.
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Get the kernel `sysTick` value.                           | PAL_SUCCESS |
+ * | 2 | Sleep for a short period .                              | PAL_SUCCESS |
+ * | 3 | Get the kernel `sysTick` value.                          | PAL_SUCCESS |
+ * | 4 | Check that second tick value is greater than the first. | PAL_SUCCESS |
+ */
+TEST(pal_rtos, pal_osDelay_Unity)
+{
+    palStatus_t status = PAL_SUCCESS;
+    uint32_t tick1 , tick2;
+    /*#1*/
+    tick1 = pal_osKernelSysTick();
+    /*#2*/
+    status = pal_osDelay(200);
+    /*#3*/
+    tick2 = pal_osKernelSysTick();
+    /*#4*/
+    TEST_ASSERT_TRUE(tick2 > tick1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+}
+
+/*! \brief Test for basic timing scenarios based on calls for the ticks and delay
+* functionality while verifying that results meet the defined deltas.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Get the kernel `sysTick` value.                                      | PAL_SUCCESS |
+* | 2 | Sleep for a very short period.                                     | PAL_SUCCESS |
+* | 3 | Get the kernel `sysTick` value.                                      | PAL_SUCCESS |
+* | 4 | Check that second tick value is greater than the first.            | PAL_SUCCESS |
+* | 5 | Get the kernel `sysTick` value.                                      | PAL_SUCCESS |
+* | 6 | Sleep for a longer period.                                         | PAL_SUCCESS |
+* | 7 | Get the kernel `sysTick` value.                                      | PAL_SUCCESS |
+* | 8 | Check that second tick value is greated than the first.           | PAL_SUCCESS |
+* | 9 | Calculate the difference between the ticks.                                | PAL_SUCCESS |
+* | 10 | Convert last sleep period to ticks.                              | PAL_SUCCESS |
+* | 11 | Check that the tick period is correct (same as sleep period +/-delta). | PAL_SUCCESS |
+*/
+TEST(pal_rtos, BasicTimeScenario)
+{
+    palStatus_t status = PAL_SUCCESS;
+    uint64_t tick, tick1 , tick2 , tickDiff, tickDelta;
+
+    /*#1*/
+    tick1 = pal_osKernelSysTick();
+    /*#2*/
+    status = pal_osDelay(1);
+    /*#3*/
+    tick2 = pal_osKernelSysTick();
+
+    /*#4*/
+    TEST_ASSERT_TRUE(tick1 != tick2);
+    TEST_ASSERT_TRUE(tick2 > tick1);  // To check that the tick counts are incremental - be aware of wrap-arounds
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /****************************************/
+    /*#5*/
+    tick1 = pal_osKernelSysTick();
+    /*#6*/
+    status = pal_osDelay(2000);
+    /*#7*/
+    tick2 = pal_osKernelSysTick();
+
+    /*#8*/
+    TEST_ASSERT_TRUE(tick1 != tick2);
+    TEST_ASSERT_TRUE(tick2 > tick1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#9*/
+    tickDiff = tick2 - tick1;
+    /*#10*/
+    tick = pal_osKernelSysTickMicroSec(2000 * 1000);
+    // 10 milliseconds delta
+    /*#11*/
+    tickDelta = pal_osKernelSysTickMicroSec(10 * 1000);
+    TEST_ASSERT_TRUE((tick - tickDelta < tickDiff) && (tickDiff < tick + tickDelta));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+}
+
+/*! \brief Create two timers: periodic and one-shot. Starts both timers,
+* then causes a delay to allow output from the timer functions to be printed on the console.
+*
+* | # |    Step                                                                                          |   Expected                     |
+* |---|--------------------------------------------------------------------------------------------------|--------------------------------|
+* | 1 | Create a one-shot timer, which calls `palTimerFunc1` when triggered, using `pal_osTimerCreate`.  | PAL_SUCCESS                    |
+* | 2 | Create a periodic timer, which calls `palTimerFunc2` when triggered, using `pal_osTimerCreate`.  | PAL_SUCCESS                    |
+* | 3 | Get the kernel `sysTick` value.                                                                  | PAL_SUCCESS                    |
+* | 4 | Start the first timer using `pal_osTimerStart`.                                                  | PAL_SUCCESS                    |
+* | 5 | Get the kernel `sysTick` value.                                                                  | PAL_SUCCESS                    |
+* | 6 | Start the first timer using `pal_osTimerStart`.                                                  | PAL_SUCCESS                    |
+* | 7 | Sleep for a period.                                                                              | PAL_SUCCESS                    |
+* | 8 | Stop the second timer using `pal_osTimerStop`.                                                   | PAL_SUCCESS                    |
+* | 9 | Delete the first timer using `pal_osTimerDelete`.                                                | PAL_SUCCESS                    |
+* | 10 | Delete the second timer using `pal_osTimerDelete`.                                              | PAL_SUCCESS                    |
+* | 11 | Create a periodic timer, which calls `palTimerFunc3` when triggered, using `pal_osTimerCreate`. | PAL_SUCCESS                    |
+* | 12 | Create a periodic timer, which calls `palTimerFunc4` when triggered, using `pal_osTimerCreate`. | PAL_ERR_NO_HIGH_RES_TIMER_LEFT |
+* | 13 | Start the first timer using `pal_osTimerStart` as high res timer.                               | PAL_SUCCESS                    |
+* | 14 | Start the second timer using `pal_osTimerStart` as high res timer.                              | PAL_ERR_NO_HIGH_RES_TIMER_LEFT |
+* | 15 | Sleep for a period.                                                                             | PAL_SUCCESS                    |
+* | 16 | Stop the second timer using `pal_osTimerStop`.                                                  | PAL_SUCCESS                    |
+* | 17 | Start the second timer using `pal_osTimerStart` as high res timer                               | PAL_SUCCESS                    |
+* | 18 | Sleep for a period.                                                                             | PAL_SUCCESS                    |
+* | 19 | Delete the first timer using `pal_osTimerDelete`.                                               | PAL_SUCCESS                    |
+* | 20 | Delete the second timer using `pal_osTimerDelete`.                                              | PAL_SUCCESS                    |
+* | 21 | Create a periodic timer, which calls `palTimerFunc5` when triggered, using `pal_osTimerCreate`. | PAL_SUCCESS                    |
+* | 22 | Sleep for a period.                                                                             | PAL_SUCCESS                    |
+* | 23 | Delete the first timer using `pal_osTimerDelete`.                                               | PAL_SUCCESS                    |
+* | 24 | Stop the timer using `pal_osTimerStop`.  and check the number of callbacks is correct           | PAL_SUCCESS                    |
+* | 25 | Delete the timer using `pal_osTimerDelete`.                                                     | PAL_SUCCESS                    |
+* | 26 | Start the timer with zero millisec.                                                             | PAL_ERR_RTOS_VALUE             |
+* | 27 | Delete the timer using `pal_osTimerDelete`.                                                     | PAL_SUCCESS                    |
+*/
+TEST(pal_rtos, TimerUnityTest)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palTimerID_t timerID1 = NULLPTR;
+    palTimerID_t timerID2 = NULLPTR;
+    /*#1*/
+    status = pal_osTimerCreate(palTimerFunc1, NULL, palOsTimerOnce, &timerID1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_osTimerCreate(palTimerFunc2, NULL, palOsTimerPeriodic, &timerID2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#3*/
+    g_timerArgs.ticksBeforeTimer = pal_osKernelSysTick();
+    /*#4*/
+    status = pal_osTimerStart(timerID1, 1000);
+    PAL_PRINTF("ticks before Timer: 0 - %" PRIu32 "\n", g_timerArgs.ticksBeforeTimer);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#5*/
+    g_timerArgs.ticksBeforeTimer = pal_osKernelSysTick();
+    /*#6*/
+    status = pal_osTimerStart(timerID2, 1000);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#7*/
+    status = pal_osDelay(1500);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#8*/
+    status = pal_osTimerStop(timerID2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#9*/
+    status = pal_osTimerDelete(&timerID1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(NULLPTR, timerID1);
+    /*#10*/
+    status = pal_osTimerDelete(&timerID2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(NULLPTR, timerID2);
+
+	g_timerArgs.ticksBeforeTimer = 0;
+    g_timerArgs.ticksInFunc1 = 0;
+    g_timerArgs.ticksInFunc2 = 0;
+	
+    /*#11*/
+    status = pal_osTimerCreate(palTimerFunc3, NULL, palOsTimerPeriodic, &timerID1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    
+    /*#12*/
+    status = pal_osTimerCreate(palTimerFunc4, NULL, palOsTimerPeriodic, &timerID2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#13*/
+    status = pal_osTimerStart(timerID1, PAL_TEST_HIGH_RES_TIMER);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#14*/
+    status = pal_osTimerStart(timerID2, PAL_TEST_HIGH_RES_TIMER);
+    if (PAL_SUCCESS == status) // behavior is slightly different for Linux due to high res timer limitation there (only one at a time supported there)
+	{
+		status = pal_osTimerStop(timerID2);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	else  
+	{
+		TEST_ASSERT_EQUAL_HEX(PAL_ERR_NO_HIGH_RES_TIMER_LEFT, status);
+	}
+    /*#15*/
+    status = pal_osDelay(500);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#16*/
+    status = pal_osTimerStop(timerID1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#17*/
+    status = pal_osTimerStart(timerID2, PAL_TEST_HIGH_RES_TIMER2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#18*/
+    status = pal_osDelay(PAL_TIME_TO_WAIT_SHORT_MS);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osTimerStop(timerID2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	TEST_ASSERT_TRUE(g_timerArgs.ticksInFunc1 >= ((PAL_TIME_TO_WAIT_SHORT_MS / PAL_TEST_HIGH_RES_TIMER2)*PAL_TEST_PERCENTAGE_LOW)/ PAL_TEST_PERCENTAGE_HUNDRED); // check there is at least more than 95% of expected timer callbacks.
+	
+    /*#19*/
+    status = pal_osTimerDelete(&timerID1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(NULLPTR, timerID1);
+    
+    /*#20*/
+    status = pal_osTimerDelete(&timerID2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(NULLPTR, timerID2);
+
+    /*#21*/
+    g_timerArgs.ticksBeforeTimer = 0;
+    g_timerArgs.ticksInFunc1 = 0;
+    g_timerArgs.ticksInFunc2 = 0;
+
+    status = pal_osTimerCreate(palTimerFunc5, NULL, palOsTimerPeriodic, &timerID1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#22*/
+    status = pal_osTimerStart(timerID1, PAL_TEST_HIGH_RES_TIMER);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    
+    /*#23*/
+    status = pal_osDelay(PAL_TIME_TO_WAIT_MS);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#24*/
+    status = pal_osTimerStop(timerID1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    TEST_ASSERT_TRUE(g_timerArgs.ticksInFunc1 >= ((PAL_TIME_TO_WAIT_MS / PAL_TEST_HIGH_RES_TIMER) * PAL_TEST_PERCENTAGE_LOW) / PAL_TEST_PERCENTAGE_HUNDRED); // check there is at least more than 95% of expected timer callbacks.
+    TEST_ASSERT_TRUE(g_timerArgs.ticksInFunc1 <= ((PAL_TIME_TO_WAIT_MS / PAL_TEST_HIGH_RES_TIMER) * PAL_TEST_PERCENTAGE_HIGH) / PAL_TEST_PERCENTAGE_HUNDRED); // check there is at most less than 105% of expected timer callbacks.
+
+    /*#25*/
+    status = pal_osTimerDelete(&timerID1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(NULLPTR, timerID1);
+
+    /*#26*/
+    status = pal_osTimerCreate(palTimerFunc5, NULL, palOsTimerPeriodic, &timerID1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    status = pal_osTimerStart(timerID1, 0);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_VALUE, status);
+
+    /*#27*/
+    status = pal_osTimerDelete(&timerID1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+}
+
+/*! \brief Creates mutexes and semaphores and uses them to communicate between
+* the different threads it creates (as defined in `pal_rtos_test_utils.c`).
+* In this test, we check that thread communication is working as expected between the threads and in the designed order.
+* In one case, we expect the thread to fail to lock a mutex – (thread1).
+* Threads are created with different priorities (PAL enforces this attribute).
+* For each case, the thread function prints the expected result. The test code verifies this result as well.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a mutex using `pal_osMutexCreate`.                           | PAL_SUCCESS |
+* | 2 | Create a mutex using `pal_osMutexCreate`.                           | PAL_SUCCESS |
+* | 3 | Create a semaphore with count 1.                                  | PAL_SUCCESS |
+* | 4 | Run the PAL test threads using the `palRunThreads` test function.  | PAL_SUCCESS |
+* | 5 | Delete the semaphore using `pal_osSemaphoreDelete`.                     | PAL_SUCCESS |
+* | 6 | Delete the first mutex using `pal_osMutexDelete`.                       | PAL_SUCCESS |
+* | 7 | Delete the second mutex using `pal_osMutexDelete`.                       | PAL_SUCCESS |
+*/
+TEST(pal_rtos, PrimitivesUnityTest1)
+{
+    palStatus_t status = PAL_SUCCESS;
+    /*#1*/
+    status = pal_osMutexCreate(&mutex1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_osMutexCreate(&mutex2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#3*/
+    status = pal_osSemaphoreCreate(1 ,&semaphore1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#4*/
+    palRunThreads();
+    /*#5*/
+    status = pal_osSemaphoreDelete(&semaphore1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(NULLPTR, semaphore1);
+    /*#6*/
+    status = pal_osMutexDelete(&mutex1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(NULLPTR, mutex1);
+    /*#7*/
+    status = pal_osMutexDelete(&mutex2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(NULLPTR, mutex2);
+
+}
+
+/*! \brief Verifies that several RTOS primitives APIs can handle invalid
+* arguments. The test calls each API with invalid arguments and verifies the result.
+* It also verifies that the semaphore wait API can accept NULL as the third parameter.
+*
+* | # |    Step                                                                      |   Expected               |
+* |---|------------------------------------------------------------------------------|--------------------------|
+* | 1 | Test thread creation with invalid arguments (`pal_osThreadCreateWithAlloc`). | PAL_ERR_INVALID_ARGUMENT |
+* | 2 | Test thread creation with invalid arguments (`pal_osThreadCreateWithAlloc`). | PAL_ERR_INVALID_ARGUMENT |
+* | 3 | Test thread creation with invalid arguments (`pal_osThreadCreateWithAlloc`). | PAL_ERR_INVALID_ARGUMENT |
+* | 4 | Test semaphore creation with invalid arguments (`pal_osSemaphoreCreate`).    | PAL_ERR_INVALID_ARGUMENT |
+* | 5 | Test semaphore creation with invalid arguments (`pal_osSemaphoreCreate`).    | PAL_ERR_INVALID_ARGUMENT |
+* | 6 | Test semaphore creation with invalid arguments (`pal_osSemaphoreCreate`).    | PAL_ERR_INVALID_ARGUMENT |
+* | 7 | Test semaphore creation with invalid arguments (`pal_osSemaphoreCreate`).    | PAL_ERR_INVALID_ARGUMENT |
+* | 8 | Test legacy thread create api (pal_osThreadCreate).                          | PAL_SUCCESS              |
+* | 9 | Call pal_osThreadTerminate with NULL invalid parameter.                      | PAL_ERR_INVALID_ARGUMENT |
+*/
+TEST(pal_rtos, PrimitivesUnityTest2)
+{
+#ifdef DEBUG
+	palStatus_t status = PAL_SUCCESS;
+	palThreadID_t threadID = NULLPTR;
+    int32_t tmp = 0;
+    /*#1*/
+    //Check thread parameter validation
+    status = pal_osThreadCreateWithAlloc(palThreadFunc1, NULL, PAL_osPriorityError, 1024, NULL, &threadID);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    /*#2*/
+    status = pal_osThreadCreateWithAlloc(palThreadFunc1, NULL, PAL_osPriorityIdle, 0, NULL, &threadID);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    /*#3*/
+    status = pal_osThreadCreateWithAlloc(palThreadFunc1, NULL, PAL_osPriorityIdle, 1024, NULL, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+
+    /*#4*/
+    //Check semaphore parameter validation
+    status = pal_osSemaphoreCreate(1 ,NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    /*#5*/
+    status = pal_osSemaphoreDelete(NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    /*#6*/
+    status = pal_osSemaphoreWait(NULLPTR, 1000, &tmp);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    /*#7*/
+    status = pal_osSemaphoreRelease(NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    /*#9*/
+    status = pal_osThreadTerminate(NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+#endif
+}
+
+/*! \brief Creates a semaphore with count=1 and a thread to
+* test that it waits forever (the test waits 5 seconds). Then deletes the semaphore
+* and terminates the thread.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a semaphore with count = 1 using `pal_osSemaphoreCreate`.                          | PAL_SUCCESS |
+* | 2 | Wait for the semaphore using `pal_osSemaphoreWait` (should not block).                    | PAL_SUCCESS |
+* | 3 | Create a thread running `palThreadFuncWaitForEverTestusing` and `pal_osThreadCreateWithAlloc`. | PAL_SUCCESS |
+* | 4 | Set time using `pal_osSetTime`.                                                           | PAL_SUCCESS |
+* | 5 | Wait for the semaphore using `pal_osSemaphoreWait` (should block; released by thread).        | PAL_SUCCESS |
+* | 6 | Delete the semaphore using `pal_osSemaphoreDelete`.                                           | PAL_SUCCESS |
+* | 7 | Terminate the thread using `pal_osThreadTerminate`.                                           | PAL_SUCCESS |
+*/
+TEST(pal_rtos, SemaphoreWaitForever)
+{
+    int32_t count = 0;
+    uint64_t timeElapsed = PAL_MIN_SEC_FROM_EPOCH;
+    uint64_t timePassedInSec;
+    palStatus_t status = PAL_SUCCESS;
+    palThreadID_t threadID1 = PAL_INVALID_THREAD;
+
+    /*#1*/
+    status = pal_osSemaphoreCreate(1 ,&semaphore1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_osSemaphoreWait(semaphore1, PAL_RTOS_WAIT_FOREVER, &count);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#3*/
+    status = pal_osSetTime(timeElapsed);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); // More than current epoch time -> success    
+    status = pal_osThreadCreateWithAlloc(palThreadFuncWaitForEverTest, (void *)&semaphore1, PAL_osPriorityAboveNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#4*/
+    status = pal_osSemaphoreWait(semaphore1, PAL_RTOS_WAIT_FOREVER, &count);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#5*/
+    timePassedInSec = pal_osGetTime();
+    TEST_ASSERT_EQUAL_HEX(0, (timePassedInSec - timeElapsed) >= PAL_TIME_TO_WAIT_MS/2);
+    /*#6*/
+    status = pal_osSemaphoreDelete(&semaphore1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(0, semaphore1);
+    /*#7*/
+    status = pal_osThreadTerminate(&threadID1);
+    TEST_ASSERT_EQUAL(PAL_SUCCESS, status);
+}
+
+/*! \brief Creates a semaphore and waits on it to verify the
+* available count for it. Also verifies that the semaphore release API works correctly.
+* In addition, it checks the semaphore parameter validation scenarios.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a semaphore with count = 2 using `pal_osSemaphoreCreate`.                          | PAL_SUCCESS |
+* | 2 | Wait for the semaphore using `pal_osSemaphoreWait` (should not block), and check count.   | PAL_SUCCESS |
+* | 3 | Increase semaphore count by ten using `pal_osSemaphoreRelease` in a loop.             | PAL_SUCCESS |
+* | 4 | Delete semaphore using `pal_osSemaphoreDelete`.                                           | PAL_SUCCESS |
+* | 5 | Test semaphore creation with invalid arguments (`pal_osSemaphoreCreate`).                 | PAL_ERR_INVALID_ARGUMENT |
+* | 6 | Test semaphore deletion with invalid arguments (`pal_osSemaphoreDelete`).                 | PAL_ERR_INVALID_ARGUMENT |
+* | 7 | Test semaphore waiting with invalid arguments (`pal_osSemaphoreWait`).                    | PAL_ERR_INVALID_ARGUMENT |
+* | 8 | Test semaphore release with invalid arguments (`pal_osSemaphoreRelease`).                 | PAL_ERR_INVALID_ARGUMENT |
+*/
+TEST(pal_rtos, SemaphoreBasicTest)
+{
+
+    palStatus_t status = PAL_SUCCESS;
+    int counter = 0;
+    /*#1*/
+    status = pal_osSemaphoreCreate(2 ,&semaphore1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    int32_t count = -1;
+    status = pal_osSemaphoreWait(semaphore1, 1000, &count);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(1, count);
+
+    /*#3*/
+    for(counter = 0; counter < 10; counter++)
+    {
+        status=pal_osSemaphoreRelease(semaphore1);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#4*/
+    status=pal_osSemaphoreDelete(&semaphore1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(0, semaphore1);
+
+    
+#ifdef DEBUG
+    //Check semaphore parameter validation
+    int32_t tmp;
+    /*#5*/
+    status = pal_osSemaphoreCreate(1 ,NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    /*#6*/
+    status = pal_osSemaphoreDelete(NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    /*#7*/
+    status = pal_osSemaphoreWait(NULLPTR, 1000, &tmp);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+    /*#8*/
+    status = pal_osSemaphoreRelease(NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+#endif
+}
+
+
+
+/*! \brief Performs a single atomic increment call
+* to an integer value and verifies that the result is as expected.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Call atomic increment using `pal_osAtomicIncrement` and check that the value was incremented. | PAL_SUCCESS |
+*/
+TEST(pal_rtos, AtomicIncrementUnityTest)
+{
+    int32_t num1 = 0;
+    int32_t increment = 10;
+    int32_t tmp = 0;
+    int32_t original = num1;
+    /*#1*/
+    tmp = pal_osAtomicIncrement(&num1, increment);
+
+
+    TEST_ASSERT_EQUAL(original + increment, tmp);
+
+}
+
+struct randBuf
+{
+    uint8_t rand[6];
+};
+
+/*! \brief Check the random APIs. For each API, the test calls the random API in a loop
+* and stores the result. When the loop finishes, we verify that the count of the
+* duplication in the stored values is less than the defined random margin value for each API.
+*
+* | #  |    Step                                                                     |   Expected               |
+* |--- |-----------------------------------------------------------------------------|--------------------------|
+* | 1  | Fill array with random 32bit values using `pal_osRandom32bit` in a loop.    | PAL_SUCCESS              |
+* | 2  | Check array for matching values and make sure there are not too many.       | PAL_SUCCESS              |
+* | 3  | Fill array with random values using `pal_osRandomUniform` in a loop.        | PAL_SUCCESS              |
+* | 4  | Check array for matching values and make sure there are not too many.       | PAL_SUCCESS              |
+* | 5  | Fill array with random byte sequences using `pal_osRandomBuffer` in a loop. | PAL_SUCCESS              |
+* | 6  | Check array for matching values and make sure there are not too many.       | PAL_SUCCESS              |
+* | 7  | Call pal_osRandom32bit with NULL output parameter.                          | PAL_ERR_INVALID_ARGUMENT |
+* | 8  | Call pal_osRandomBuffer with NULL output parameter.                         | PAL_ERR_INVALID_ARGUMENT |
+* | 9  | Call pal_osRandomUniform with NULL output parameter.                        | PAL_ERR_INVALID_ARGUMENT |
+* | 10 | Call pal_osRandomBuffer while pal is not initialized.                       | PAL_ERR_NOT_INITIALIZED  |
+*/
+TEST(pal_rtos, RandomUnityTest)
+{
+    palStatus_t status = PAL_SUCCESS;
+    uint32_t randomArray[PAL_RANDOM_ARRAY_TEST_SIZE];
+    struct randBuf randomBufArray[PAL_RANDOM_BUFFER_ARRAY_TEST_SIZE];
+    uint32_t randomMargin = 0;
+
+    memset(randomArray, 0x0, sizeof(randomArray));
+    memset(randomBufArray, 0x0, sizeof(randomBufArray));
+    /*#1*/
+    for(int i = 0; i < PAL_RANDOM_ARRAY_TEST_SIZE ; ++i)
+    {
+        status = pal_osRandom32bit(&randomArray[i]);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#2*/
+    for(int k = 0; k < PAL_RANDOM_ARRAY_TEST_SIZE ; ++k)
+    {
+        for (int j = k+1 ; j < PAL_RANDOM_ARRAY_TEST_SIZE ; ++j)
+        {
+            if (randomArray[k] == randomArray[j])
+            {
+                ++randomMargin;
+            }
+        }
+        randomArray[k] = 0;
+    }
+    TEST_ASSERT_TRUE(20 >= randomMargin);
+    randomMargin = 0;
+    /*#5*/
+    for (int i = 0; i < PAL_RANDOM_BUFFER_ARRAY_TEST_SIZE ; ++i)
+    {
+        status = pal_osRandomBuffer(randomBufArray[i].rand, sizeof(randomBufArray[i].rand));
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#6*/
+    for(int k = 0; k < PAL_RANDOM_BUFFER_ARRAY_TEST_SIZE ; ++k)
+    {
+        for (int j = k+1 ; j < PAL_RANDOM_BUFFER_ARRAY_TEST_SIZE ; ++j)
+        {
+            if(0 == memcmp(randomBufArray[k].rand, randomBufArray[j].rand, sizeof(uint8_t)*6))
+            {
+                ++randomMargin;
+            }
+        }
+    }
+
+    TEST_ASSERT_TRUE(10 >= randomMargin);
+
+#ifdef DEBUG
+    /*#7*/
+    status = pal_osRandom32bit(NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+
+    /*#8*/
+    status = pal_osRandomBuffer(NULL, 0);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+
+
+#endif
+
+    /*#10*/
+    pal_destroy();
+    status = pal_osRandomBuffer(randomBufArray[0].rand, sizeof(randomBufArray[0].rand));
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_NOT_INITIALIZED, status);
+}
+
+
+/*! \brief call the random API in a PAL_RANDOM_TEST_LOOP loop.
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Call `pal_osRandomBuffer` in a PAL_RANDOM_TEST_LOOP loop .         PAL_SUCCESS |
+*/
+TEST(pal_rtos, loopRandomBigNumber)
+{
+	palStatus_t status = PAL_SUCCESS;
+	uint8_t loopRandomArray[PAL_RANDOM_ARRAY_TEST_SIZE];
+
+	for (int i = 0; i < PAL_RANDOM_TEST_LOOP; ++i)
+	{
+		status = pal_osRandomBuffer(loopRandomArray, sizeof(loopRandomArray));
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+}
+
+/*! \brief Verify that PAL can handle multiple calls for `pal_init()` and `pal_destroy()`.
+*
+* | # |    Step                                              |   Expected  |
+* |---|------------------------------------------------------|-------------|
+* | 1 | Call `pal_init`.                                     | PAL_SUCCESS |
+* | 2 | Call `pal_init`.                                     | PAL_SUCCESS |
+* | 3 | Call `pal_init`.                                     | PAL_SUCCESS |
+* | 4 | Call `pal_destroy` in a loop untill init count == 0. | PAL_SUCCESS |
+* | 5 | Call `pal_init`.                                     | PAL_SUCCESS |
+* | 6 | Call `pal_RTOSInitialize`.                           | PAL_SUCCESS |
+* | 7 | Call `pal_destroy`.                                  | PAL_SUCCESS |
+*/
+TEST(pal_rtos, pal_init_test)
+{
+    palStatus_t status = PAL_SUCCESS;
+    int32_t initCounter = 0;
+    /*#1*/
+    status = pal_init();
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_init();
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#3*/
+    status = pal_init();
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#4*/
+    do
+    {
+        initCounter = pal_destroy();
+        //TEST_ASSERT_EQUAL_HEX(0, initCounter);
+
+    }while(initCounter != 0);
+
+    /*#5*/
+    status = pal_init();
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_RTOSInitialize(NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#7*/
+    initCounter = pal_destroy();
+    TEST_ASSERT_EQUAL_HEX(0, initCounter);
+}
+
+/*! \brief Check derivation of keys from the platform's Root of Trust using the KDF algorithm.
+ *
+ * 
+ *
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Start a loop to perform the following steps.                                               |  |
+* | 2 | Derive a device key for encryption using `pal_osGetDeviceKey`.                   | PAL_SUCCESS |
+* | 3 | Derive a device key for signing using `pal_osGetDeviceKey`.                      | PAL_SUCCESS |
+* | 4 | Call `pal_osGetDeviceKey` with invalid arguments.                              | PAL_FAILURE |
+* | 5 | Call `pal_osGetDeviceKey` with invalid arguments.                              | PAL_FAILURE |
+* | 6 | Check that the derived signing and encryption keys are different.                     | PAL_SUCCESS |
+* | 7 | Check that all integrations of each type of derivation return the same value.       | PAL_SUCCESS |
+ */
+TEST(pal_rtos, GetDeviceKeyTest_CMAC)
+{
+    palStatus_t status = PAL_SUCCESS;
+    size_t keyLenBytes = 16;
+    uint8_t timesToDerive = 4;
+    unsigned char encKeyDerive[timesToDerive][keyLenBytes]; //16 bytes=128bit
+    unsigned char signKeyDerive[timesToDerive][keyLenBytes]; //16 bytes=128bit
+    /*#1*/
+    for (int i=0; i < timesToDerive; i++)
+    {
+        /*#2*/
+        status = pal_osGetDeviceKey(palOsStorageEncryptionKey128Bit, encKeyDerive[i], keyLenBytes);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        /*#3*/
+        status = pal_osGetDeviceKey(palOsStorageSignatureKey128Bit,  signKeyDerive[i], keyLenBytes);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        /*#4*/
+        status = pal_osGetDeviceKey(palOsStorageSignatureKey128Bit,  signKeyDerive[i], keyLenBytes-1);
+        TEST_ASSERT_NOT_EQUAL(PAL_SUCCESS, status);
+        /*#5*/
+        status = pal_osGetDeviceKey(palOsStorageSignatureKey128Bit,  NULL, keyLenBytes);
+        TEST_ASSERT_NOT_EQUAL(PAL_SUCCESS, status);
+        /*#6*/
+        status = memcmp(encKeyDerive[i], signKeyDerive[i], keyLenBytes);
+        TEST_ASSERT_NOT_EQUAL(status,0); //The keys MUST be different!
+        /*#7*/
+        if (i > 0) //Make sure key derivation is persistent every time
+        {
+            TEST_ASSERT_EQUAL_MEMORY(encKeyDerive[i-1], encKeyDerive[i], keyLenBytes);
+            TEST_ASSERT_EQUAL_MEMORY(signKeyDerive[i-1], signKeyDerive[i], keyLenBytes);
+
+        } //if
+
+    } //for
+
+}
+
+/*! \brief Check derivation of keys from the platform's Root of Trust using the KDF algorithm.
+ *
+ * 
+ *
+* | # |    Step                                                                        | Expected            |
+* |---|--------------------------------------------------------------------------------|---------------------|
+* | 1 | Start a loop to perform the following steps.                                   |                     |
+* | 2 | Derive a device key for encryption using `pal_osGetDeviceKey`.                 | PAL_SUCCESS         |
+* | 3 | Call `pal_osGetDeviceKey` with invalid arguments.                              | PAL_FAILURE         |
+* | 4 | Call `pal_osGetDeviceKey` with invalid arguments.                              | PAL_FAILURE         |
+* | 5 | Check that all integrations of each type of derivation return the same value.  | PAL_SUCCESS         |
+* | 6 | Call `pal_osGetDeviceKey` with invalid palDevKeyType_t.                        | PAL_ERR_GET_DEV_KEY |
+ */
+TEST(pal_rtos, GetDeviceKeyTest_HMAC_SHA256)
+{
+    palStatus_t status = PAL_SUCCESS;
+    size_t keyLenBytes = 32;
+    uint8_t timesToDerive = 4;
+    unsigned char encKeyDerive[timesToDerive][keyLenBytes]; //32 bytes=256bit
+    /*#1*/
+    for (int i=0; i < timesToDerive; i++)
+    {
+        /*#2*/
+        status = pal_osGetDeviceKey(palOsStorageHmacSha256, encKeyDerive[i], keyLenBytes);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#ifdef DEBUG
+        /*#3*/
+        status = pal_osGetDeviceKey(palOsStorageHmacSha256,  encKeyDerive[i], keyLenBytes-1);
+        TEST_ASSERT_NOT_EQUAL(PAL_SUCCESS, status);
+        /*#4*/
+        status = pal_osGetDeviceKey(palOsStorageHmacSha256,  NULL, keyLenBytes);
+        TEST_ASSERT_NOT_EQUAL(PAL_SUCCESS, status);
+#endif
+        /*#5*/
+        if (i > 0) //Make sure key derivation is persistent every time
+        {
+            TEST_ASSERT_EQUAL_MEMORY(encKeyDerive[i-1], encKeyDerive[i], keyLenBytes);
+        } //if
+
+    } //for
+
+#ifdef DEBUG
+      /*#6*/
+    status = pal_osGetDeviceKey((palDevKeyType_t)999, encKeyDerive[0], keyLenBytes);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+#endif
+}
+
+/*! \brief Check the APIs `pal_osSetTime()` and `pal_osGetTime()` with different scenarios
+* for valid and non-valid scenarios and epoch values.
+* The test also checks that the time increases.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Start a loop for the following steps.                                                | PAL_SUCCESS |
+* | 2 | Set time to invalid value using `pal_osSetTime`.                                 | PAL_ERR_INVALID_TIME |
+* | 3 | Get time using `pal_osGetTime`.                                                  | PAL_SUCCESS |
+* | 4 | Set time to valid value using `pal_osSetTime`.                                   | PAL_SUCCESS |
+* | 5 | Sleep.                                                                         | PAL_SUCCESS |
+* | 6 | Get time using `pal_osGetTime` and check that it equals set time + sleep time.   | PAL_SUCCESS |
+*/
+TEST(pal_rtos, RealTimeClockTest1)
+{
+    palStatus_t status;
+    uint64_t curTime = 0;
+    uint64_t lastTimeSeen = 0;
+    const uint64_t minSecSinceEpoch = PAL_MIN_SEC_FROM_EPOCH + 1; //At least 47 years passed from 1.1.1970 in seconds
+
+    /*#1*/
+    for (int i=0; i < 2; i++)
+    {
+    /*#2*/
+        status = pal_osSetTime(3);
+        TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_TIME, status); // Less than current epoch time -> error
+
+    /*#3*/
+        curTime = pal_osGetTime();
+        TEST_ASSERT_TRUE(lastTimeSeen <= curTime); //Time was not previously set; 0 is acceptable
+    /*#4*/
+        status = pal_osSetTime(minSecSinceEpoch);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); // More than current epoch time -> success
+    /*#5*/
+        int milliDelay = 1500;
+        pal_osDelay(milliDelay); //500 milliseconds
+    /*#6*/
+        curTime = pal_osGetTime();
+        TEST_ASSERT_TRUE(curTime > minSecSinceEpoch);
+        TEST_ASSERT_TRUE(curTime <= minSecSinceEpoch+(int)ceil((float)milliDelay/1000));
+        lastTimeSeen = curTime;
+    }
+}
+
+
+/*! \brief Check recursive mutex behavior.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a mutex using `pal_osMutexCreate`.                                             | PAL_SUCCESS |
+* | 2 | Create a semaphore using `pal_osSemaphoreCreate`.                                     | PAL_SUCCESS |
+* | 3 | Create a thread running `RecursiveLockThread` using `pal_osThreadCreateWithAlloc`.       | PAL_SUCCESS |
+* | 4 | Create a thread running `RecursiveLockThread` using `pal_osThreadCreateWithAlloc`.       | PAL_SUCCESS |
+* | 5 | Release the semaphore using `pal_osSemaphoreRelease`.                                    | PAL_SUCCESS |
+* | 6 | Release the semaphore using `pal_osSemaphoreRelease`.                                    | PAL_SUCCESS |
+* | 7 | Sleep for a short interval.                                                          | PAL_SUCCESS |
+* | 8 | Wait for the semaphore using `pal_osSemaphoreWait`.                                      | PAL_SUCCESS |
+* | 9 | Wait for the semaphore using `pal_osSemaphoreWait`.                                      | PAL_SUCCESS |
+* | 10 | Terminate the first thread using `pal_osThreadTerminate`.                               | PAL_SUCCESS |
+* | 11 | Terminate the second thread using `pal_osThreadTerminate`.                              | PAL_SUCCESS |
+* | 12 | Delete the mutex using `pal_osMutexDelete`.                                           | PAL_SUCCESS |
+* | 13 | Delete the semaphore using `pal_osSemaphoreDelete`.                                   | PAL_SUCCESS |
+*/
+TEST(pal_rtos, Recursive_Mutex_Test)
+{
+    palStatus_t status;
+    int32_t val = 0;
+
+    recursiveMutexData = malloc(sizeof(palRecursiveMutexParam_t));
+    TEST_ASSERT_NOT_NULL(recursiveMutexData);
+    memset(recursiveMutexData, 0, sizeof(palRecursiveMutexParam_t));
+    /*#1*/
+    status = pal_osMutexCreate(&(recursiveMutexData->mtx));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_osSemaphoreCreate(0, &(recursiveMutexData->sem));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#3*/
+    status = pal_osThreadCreateWithAlloc(RecursiveLockThread, (void*)recursiveMutexData, PAL_osPriorityHigh, PAL_TEST_THREAD_STACK_SIZE, NULL, &(recursiveMutexData->higherPriorityThread));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#4*/
+     status = pal_osThreadCreateWithAlloc(RecursiveLockThread, (void*)recursiveMutexData, PAL_osPriorityAboveNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &(recursiveMutexData->lowerPriorityThread));
+     TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#5*/
+    status = pal_osSemaphoreRelease(recursiveMutexData->sem);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#6*/
+    status = pal_osSemaphoreRelease(recursiveMutexData->sem);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#7*/
+    pal_osDelay(1000);
+    /*#8*/
+    status = pal_osSemaphoreWait(recursiveMutexData->sem, PAL_RTOS_WAIT_FOREVER, &val);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#9*/
+    status = pal_osSemaphoreWait(recursiveMutexData->sem, PAL_RTOS_WAIT_FOREVER, &val);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(0, val);
+    TEST_ASSERT_EQUAL_HEX(NULLPTR, recursiveMutexData->activeThread);
+    /*#10*/
+    status = pal_osThreadTerminate(&(recursiveMutexData->higherPriorityThread));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#11*/
+    status = pal_osThreadTerminate(&(recursiveMutexData->lowerPriorityThread));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#12*/
+    status = pal_osMutexDelete(&(recursiveMutexData->mtx));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#13*/
+    status = pal_osSemaphoreDelete(&recursiveMutexData->sem);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    TEST_ASSERT_EQUAL(400, recursiveMutexData->count);
+
+    free(recursiveMutexData);
+    recursiveMutexData = NULL;
+}
+
+
+
+/*! \brief Check Weak Set Time - Forword flow.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | checking RTC and SOTP flow - not set SOTP SAVED TIME  + LAST TIME BACK + RTC to new time          		      | PAL_SUCCESS |
+* | 2 | checking RTC and SOTP flow - not set SOTP SAVED TIME  + LAST TIME BACK to new time but set RTC to new time    | PAL_SUCCESS |
+* | 3 | checking RTC and SOTP flow - set SOTP SAVED TIME  + LAST TIME BACK + RTC to new time          		          | PAL_SUCCESS |
+*/
+TEST(pal_rtos, OsWeakSetTime_Forword)
+{
+    palStatus_t status;
+    sotp_result_e sotpStatus = SOTP_SUCCESS;
+    uint64_t setTimeInSeconds = 0;
+    uint64_t curentTimeInSeconds=0;
+    uint64_t pal_Time = 0;
+    uint64_t sotpGetTime = 0;
+    uint16_t actualLenBytes = 0;
+
+#if (PAL_USE_HW_RTC)
+    //This code is to preserve system time
+    uint64_t testStartTime = 0;
+    status = pal_plat_osGetRtcTime(&testStartTime);
+#endif
+
+
+    /*#1*/
+#if (PAL_USE_HW_RTC)
+    pal_plat_osSetRtcTime(PAL_MIN_RTC_SET_TIME);
+#endif
+    pal_osSetTime(PAL_MIN_SEC_FROM_EPOCH + PAL_SECONDS_PER_DAY * 100);
+    curentTimeInSeconds = pal_osGetTime();
+
+    sotpStatus = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&curentTimeInSeconds);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+    sotpStatus = sotp_set(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&curentTimeInSeconds);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+#if (PAL_USE_HW_RTC)
+    uint64_t rtcTime = 0;
+    status = pal_plat_osSetRtcTime(curentTimeInSeconds);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif//PAL_USE_HW_RTC
+
+    setTimeInSeconds = curentTimeInSeconds + (50 * PAL_ONE_SEC);
+    status = pal_osSetWeakTime(setTimeInSeconds);
+
+    pal_Time = pal_osGetTime();
+    if (pal_Time - setTimeInSeconds > 5)
+    {
+    	status = PAL_ERR_GENERAL_BASE;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#if PAL_USE_INTERNAL_FLASH
+    sotpStatus = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+    TEST_ASSERT_NOT_EQUAL(sotpGetTime, setTimeInSeconds);
+
+    sotpStatus = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+    TEST_ASSERT_NOT_EQUAL(sotpGetTime, setTimeInSeconds);
+#endif 
+
+#if (PAL_USE_HW_RTC)
+    status = pal_plat_osGetRtcTime(&rtcTime);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_NOT_EQUAL(rtcTime, setTimeInSeconds);
+#endif//PAL_USE_HW_RTC
+
+    /*#2*/
+    curentTimeInSeconds = pal_osGetTime();
+#if (PAL_USE_HW_RTC)
+    pal_plat_osSetRtcTime(curentTimeInSeconds);
+#endif//PAL_USE_HW_RTC
+    
+    setTimeInSeconds = curentTimeInSeconds+(200 * PAL_ONE_SEC);
+
+    status = pal_osSetWeakTime(setTimeInSeconds);
+    pal_Time = pal_osGetTime();
+    if (pal_Time - setTimeInSeconds > 5)
+    {
+    	status = PAL_ERR_GENERAL_BASE;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+#if PAL_USE_INTERNAL_FLASH
+    sotpStatus = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+	TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+	TEST_ASSERT_NOT_EQUAL(sotpGetTime, setTimeInSeconds);
+
+    sotpStatus = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+	TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+	TEST_ASSERT_NOT_EQUAL(sotpGetTime, setTimeInSeconds);
+#endif
+
+#if (PAL_USE_HW_RTC)
+    status = pal_plat_osGetRtcTime(&rtcTime);
+    TEST_ASSERT_EQUAL_UINT64(rtcTime, setTimeInSeconds);
+#endif//PAL_USE_HW_RTC
+
+    /*#3*/
+    curentTimeInSeconds = pal_osGetTime();
+    sotpStatus = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&curentTimeInSeconds);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+    sotpStatus = sotp_set(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&curentTimeInSeconds);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+#if (PAL_USE_HW_RTC)
+    status = pal_plat_osSetRtcTime(curentTimeInSeconds);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif//PAL_USE_HW_RTC
+
+    setTimeInSeconds = curentTimeInSeconds + PAL_MINIMUM_SOTP_FORWARD_LATENCY_SEC + (100 * PAL_ONE_SEC);
+    status = pal_osSetWeakTime(setTimeInSeconds);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+#if PAL_USE_INTERNAL_FLASH
+    sotpStatus = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+	TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+	TEST_ASSERT_EQUAL_UINT64(sotpGetTime, setTimeInSeconds);
+#endif
+
+#if (PAL_USE_HW_RTC)
+    status = pal_plat_osGetRtcTime(&rtcTime);
+    TEST_ASSERT_EQUAL_UINT64(rtcTime, setTimeInSeconds);
+#endif//PAL_USE_HW_RTC
+
+#if (PAL_USE_HW_RTC)
+    //restore System time
+    pal_plat_osSetRtcTime(testStartTime + PAL_RUNNING_TEST_TIME);
+#endif
+}
+
+/*! \brief Check Weak Set Time - Backword flow.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | checking SOTP flow - set SOTP SAVED TIME and LAST TIME BACK to new time	        | PAL_SUCCESS |
+* | 2 | checking SOTP flow - not set SOTP SAVED TIME and LAST TIME BACK to new time	    | PAL_SUCCESS |
+*/
+TEST(pal_rtos, OsWeakSetTime_Backword)
+{
+    uint64_t setTimeInSeconds = 0;
+    uint64_t curentTimeInSeconds = 0;
+    palStatus_t status;
+    sotp_result_e sotpStatus = SOTP_SUCCESS;
+    uint64_t getTimeValueBackword = 0;
+    uint64_t pal_Time = 0;
+#if (PAL_USE_HW_RTC)
+    //This code is to preserve system time
+    uint64_t testStartTime = 0;
+    status = pal_plat_osGetRtcTime(&testStartTime);
+#endif
+
+    /*#1*/
+#if (PAL_USE_HW_RTC)
+    pal_plat_osSetRtcTime(PAL_MIN_RTC_SET_TIME);
+    pal_osSetTime(PAL_MIN_SEC_FROM_EPOCH + PAL_SECONDS_PER_DAY * 100);
+#endif
+    curentTimeInSeconds = pal_osGetTime();
+
+    getTimeValueBackword = curentTimeInSeconds - (3 * PAL_MINIMUM_SOTP_FORWARD_LATENCY_SEC);
+    sotpStatus = sotp_set(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&getTimeValueBackword);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+
+    setTimeInSeconds = curentTimeInSeconds - (6 * PAL_SECONDS_PER_MIN);
+    status = pal_osSetWeakTime(setTimeInSeconds);
+
+    pal_Time = pal_osGetTime();
+    if (pal_Time - setTimeInSeconds > 5)
+    {
+    	status = PAL_ERR_GENERAL_BASE;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    uint64_t sotpGetTime = 0;
+    uint16_t actualLenBytes = 0;
+
+#if PAL_USE_INTERNAL_FLASH
+    sotpStatus = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+    TEST_ASSERT_EQUAL_UINT64(sotpGetTime, setTimeInSeconds);
+
+    sotpStatus = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+    TEST_ASSERT_EQUAL_UINT64(sotpGetTime, setTimeInSeconds);
+#endif
+
+    /*#2*/
+    curentTimeInSeconds = pal_osGetTime();
+    getTimeValueBackword = curentTimeInSeconds - (3 * PAL_MINIMUM_SOTP_FORWARD_LATENCY_SEC);
+    sotpStatus = sotp_set(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&getTimeValueBackword);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+    sotpStatus = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&getTimeValueBackword);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+    setTimeInSeconds = curentTimeInSeconds - (12 * PAL_SECONDS_PER_MIN);
+
+    status = pal_osSetWeakTime(setTimeInSeconds);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+#if PAL_USE_INTERNAL_FLASH
+    sotpStatus = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+    TEST_ASSERT_NOT_EQUAL(sotpGetTime, setTimeInSeconds);
+    sotpStatus = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+    TEST_ASSERT_NOT_EQUAL(sotpGetTime, setTimeInSeconds);
+#endif
+
+#if (PAL_USE_HW_RTC)
+    //restore System time
+    pal_plat_osSetRtcTime(testStartTime + PAL_RUNNING_TEST_TIME);
+#endif
+}
+
+/*! \brief Weak Strong Set Time- minimalStoredLag flow.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | checking SOTP flow- set SOTP SAVED TIME to new time	                		| PAL_SUCCESS |
+* | 2 | checking SOTP flow- not set SOTP SAVED TIME	to new time                     | PAL_SUCCESS |
+*/
+TEST(pal_rtos, OsWeakSetTime_minimalStoredLag)
+{
+    palStatus_t status;
+    sotp_result_e sotpStatus = SOTP_SUCCESS;
+    uint64_t setTimeInSeconds = 0;
+    uint64_t curentTimeInSeconds = 0;
+    uint64_t sotpGetTime = 0;
+    uint16_t actualLenBytes = 0;
+    uint64_t setSotpTimeValue = 0;
+    
+#if (PAL_USE_HW_RTC)
+    //This code is to preserve system time
+    uint64_t testStartTime = 0;
+    status = pal_plat_osGetRtcTime(&testStartTime);
+#endif
+
+    /*#1*/
+#if (PAL_USE_HW_RTC)
+    pal_plat_osSetRtcTime(PAL_MIN_RTC_SET_TIME);
+#endif
+    pal_osSetTime(PAL_MIN_SEC_FROM_EPOCH + PAL_SECONDS_PER_DAY * 100);
+    curentTimeInSeconds = pal_osGetTime();
+    setTimeInSeconds = curentTimeInSeconds;
+
+    setSotpTimeValue = curentTimeInSeconds - (PAL_MINIMUM_STORAGE_LATENCY_SEC + 50);
+    sotpStatus = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setSotpTimeValue);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+    status = pal_osSetWeakTime(setTimeInSeconds);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+#if PAL_USE_INTERNAL_FLASH
+    sotpStatus = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+    TEST_ASSERT_EQUAL_UINT64(sotpGetTime, setTimeInSeconds);
+#endif
+
+    /*#2*/
+    curentTimeInSeconds = pal_osGetTime();
+    setTimeInSeconds = curentTimeInSeconds - 50;
+
+    setSotpTimeValue = curentTimeInSeconds;
+    sotpStatus = sotp_set(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&setSotpTimeValue);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+    status = pal_osSetWeakTime(setTimeInSeconds);
+ 	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	
+#if PAL_USE_INTERNAL_FLASH
+    sotpStatus = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+    TEST_ASSERT_NOT_EQUAL(sotpGetTime, setTimeInSeconds);
+#endif
+
+#if (PAL_USE_HW_RTC)
+    //restore System time
+    pal_plat_osSetRtcTime(testStartTime + PAL_RUNNING_TEST_TIME);
+#endif
+}
+
+/*! \brief Check Strong Set Time.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | checking RTC flow - set new RTC time					                		| PAL_SUCCESS |
+* | 2 | checking RTC flow - not set RTC new time				                		| PAL_SUCCESS |
+* | 3 | checking SOTP flow - set SOTP SAVED TIME and LAST TIME BACK to new time	        | PAL_SUCCESS |
+* | 4 | checking SOTP flow - not set SOTP SAVED TIME and LAST TIME BACK to new time       | PAL_SUCCESS |
+*/
+TEST(pal_rtos, OsStrongSetTime)
+{
+    palStatus_t status;
+    sotp_result_e sotpStatus = SOTP_SUCCESS;
+    uint64_t setTimeInSeconds = 0;
+    uint64_t curentTimeInSeconds = 0;
+    uint64_t pal_Time = 0;
+    uint64_t sotpGetTime = 0;
+    uint16_t actualLenBytes = 0;
+    uint64_t setSotpTimeValue = 0;
+
+#if (PAL_USE_HW_RTC)
+    //This code is to preserve system time
+    uint64_t testStartTime = 0;
+    status = pal_plat_osGetRtcTime(&testStartTime);
+#endif
+
+    /*#1*/
+#if (PAL_USE_HW_RTC)
+    pal_plat_osSetRtcTime(PAL_MIN_RTC_SET_TIME);
+#endif
+    pal_osSetTime(PAL_MIN_SEC_FROM_EPOCH + PAL_SECONDS_PER_DAY * 100);
+    curentTimeInSeconds = pal_osGetTime();
+    setTimeInSeconds = curentTimeInSeconds;
+
+#if (PAL_USE_HW_RTC)
+    uint64_t rtcTime = 0;
+    rtcTime = curentTimeInSeconds - (50 + PAL_MINIMUM_RTC_LATENCY_SEC);
+    status = pal_plat_osSetRtcTime(rtcTime);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif//PAL_USE_HW_RTC
+
+    status = pal_osSetStrongTime(setTimeInSeconds);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+#if (PAL_USE_HW_RTC)
+    status = pal_plat_osGetRtcTime(&rtcTime);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL_UINT64(rtcTime, setTimeInSeconds);
+#endif//PAL_USE_HW_RTC
+
+    pal_Time = pal_osGetTime();
+    if (pal_Time - setTimeInSeconds > 5)
+    {
+    	status = PAL_ERR_GENERAL_BASE;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#2*/
+    curentTimeInSeconds = pal_osGetTime();
+    setTimeInSeconds = curentTimeInSeconds;
+
+#if (PAL_USE_HW_RTC)
+    rtcTime = curentTimeInSeconds;
+    status = pal_plat_osSetRtcTime(rtcTime - 50);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif//PAL_USE_HW_RTC
+
+    status = pal_osSetStrongTime(setTimeInSeconds);
+
+#if (PAL_USE_HW_RTC)
+    status = pal_plat_osGetRtcTime(&rtcTime);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_NOT_EQUAL(rtcTime, setTimeInSeconds);
+#endif//PAL_USE_HW_RTC
+
+    pal_Time = pal_osGetTime();
+    if (pal_Time - setTimeInSeconds > 5){
+    	status = PAL_ERR_GENERAL_BASE;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#3*/
+    curentTimeInSeconds = pal_osGetTime();
+    setTimeInSeconds = curentTimeInSeconds;
+    setSotpTimeValue = curentTimeInSeconds - (PAL_MINIMUM_SOTP_FORWARD_LATENCY_SEC + 1*PAL_ONE_SEC);
+    sotpStatus = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setSotpTimeValue);
+	TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+    status = pal_osSetStrongTime(setTimeInSeconds);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+#if PAL_USE_INTERNAL_FLASH
+    sotpStatus = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+    TEST_ASSERT_EQUAL_UINT64(sotpGetTime, setTimeInSeconds);
+
+    sotpStatus = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+    TEST_ASSERT_EQUAL_UINT64(sotpGetTime, setTimeInSeconds);
+#endif
+
+    pal_Time = pal_osGetTime();
+    if (pal_Time - setTimeInSeconds > 5)
+    {
+    	status = PAL_ERR_GENERAL_BASE;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#4*/
+    curentTimeInSeconds = pal_osGetTime();
+    setTimeInSeconds = curentTimeInSeconds;
+
+    setSotpTimeValue = curentTimeInSeconds - 5;
+    sotpStatus = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&setSotpTimeValue);
+	TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+    sotpStatus = sotp_set(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t *)&setSotpTimeValue);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+    status = pal_osSetStrongTime(setTimeInSeconds);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+#if PAL_USE_INTERNAL_FLASH
+    sotpStatus = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+    TEST_ASSERT_NOT_EQUAL(sotpGetTime, setTimeInSeconds);
+
+    sotpStatus = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(uint64_t), (uint32_t*)&sotpGetTime, &actualLenBytes);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+    TEST_ASSERT_NOT_EQUAL(sotpGetTime, setTimeInSeconds);
+#endif
+
+    pal_Time = pal_osGetTime();
+    if (pal_Time - setTimeInSeconds > 5)
+    {
+    	status = PAL_ERR_GENERAL_BASE;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+#if (PAL_USE_HW_RTC)
+    //restore System time
+    pal_plat_osSetRtcTime(testStartTime + PAL_RUNNING_TEST_TIME);
+#endif
+}
+
+
+/*! \brief This test verify the functionality of the RTC
+ *
+ * | # |    Step                        |   Expected  |
+ * |---|--------------------------------|-------------|
+ * | 1 | Get system RTC                           | PAL_SUCCESS |
+ * | 2 | set new RTC                              | PAL_SUCCESS |
+ * | 3 | delay for 2 seconds                      | PAL_SUCCESS |
+ * | 4 | get RTC & compare to RTC from (2)        | PAL_SUCCESS |
+ * | 5 | restore system time from (1)             | PAL_SUCCESS |
+ */
+TEST(pal_rtos, pal_rtc)
+{
+#if (PAL_USE_HW_RTC)
+    palStatus_t status = PAL_SUCCESS;
+    uint64_t time1 = 0, sysTime = 0;
+
+    /*#1*/
+    status = pal_plat_osGetRtcTime(&sysTime);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#2*/
+    status = pal_plat_osSetRtcTime(PAL_MIN_RTC_SET_TIME);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#3*/
+    status = pal_osDelay(2000);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#4*/
+    status = pal_plat_osGetRtcTime(&time1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_TRUE(time1 - PAL_MIN_RTC_SET_TIME >=  1 * PAL_ONE_SEC);
+
+    /*#5*/
+    pal_plat_osSetRtcTime(sysTime + time1 - PAL_MIN_RTC_SET_TIME  + 1); //add lost time from delay
+
+
+#endif
+}
+
+// the following functions are not part of PAL's external API hence extern
+extern palStatus_t pal_noiseWriteValue(const int32_t* data, uint8_t startBit, uint8_t lenBits, uint8_t* bitsWritten);
+extern palStatus_t pal_noiseWriteBuffer(int32_t* buffer, uint16_t lenBits, uint16_t* bitsWritten);
+extern palStatus_t pal_noiseRead(int32_t buffer[PAL_NOISE_BUFFER_LEN], bool partial, uint16_t* bitsRead);
+
+/*! \brief This test verifies the functionality of noise collection
+*
+* | # |    Step                                                                                    |   Expected  |
+* |---|--------------------------------------------------------------------------------------------|-------------|
+* | 1 | Reset the noise buffer by reading watever is available                                     | PAL_SUCCESS |
+* | 2 | Write an entire int32_t (all bits) and verify writes and that full read not possible       | PAL_SUCCESS |
+* | 3 | Write only some bits of the int32_t and verify writes and that full read not possible      | PAL_SUCCESS |
+* | 4 | Write only some bits of the int32_t, implicitly causing splitting the value into 2 indexes | PAL_SUCCESS |
+* | 5 | Read whatever was collected thus far (partial read) and verify output                      | PAL_SUCCESS |
+* | 6 | Try to read again and verify buffer is empty                                               | PAL_SUCCESS |
+* | 7 | Write a buffer excluding the last 7 bits of the last index and verify results              | PAL_SUCCESS |
+* | 8 | Fill the buffer and try to write some more data into it                                    | PAL_SUCCESS |
+*/
+TEST(pal_rtos, pal_noise)
+{
+    palStatus_t status;
+    int32_t outBuffer[PAL_NOISE_BUFFER_LEN] = { 0 };
+    int32_t inBuffer[] = { 0xB76EC265, 0xD16ACE6E, 0xF56AAD6A };
+    uint16_t bitsWritten = 0;
+    uint16_t bitsRead = 0;
+    int32_t writeValue;
+    uint8_t i;
+
+    /*#1*/
+    pal_noiseRead(outBuffer, true, &bitsRead);
+    memset(outBuffer, 0, PAL_NOISE_SIZE_BYTES);
+
+    /*#2*/
+    writeValue = 0xCB76102A;
+    status = pal_noiseWriteValue(&writeValue, 0, 32, (uint8_t*)&bitsWritten); // write all bits
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(32, bitsWritten);
+    status = pal_noiseRead(outBuffer, false, &bitsRead);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_NOISE_BUFFER_NOT_FULL, status);
+    TEST_ASSERT_EQUAL(0, bitsRead);
+
+    /*#3*/
+    status = pal_noiseWriteValue(&writeValue, 3, 20, (uint8_t*)&bitsWritten); // write some of the bits, starting at bit index 3
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(20, bitsWritten);
+    status = pal_noiseRead(outBuffer, false, &bitsRead);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_NOISE_BUFFER_NOT_FULL, status);
+    TEST_ASSERT_EQUAL(0, bitsRead);
+
+    /*#4*/
+    status = pal_noiseWriteValue(&writeValue, 16, 16, (uint8_t*)&bitsWritten); // write some of the bits, starting at bit index 16, this functionality tests splitting the bits into 2 different indexes
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(16, bitsWritten);
+    status = pal_noiseRead(outBuffer, false, &bitsRead);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_NOISE_BUFFER_NOT_FULL, status);
+    TEST_ASSERT_EQUAL(0, bitsRead);
+
+    /*#5*/
+    status = pal_noiseRead(outBuffer, true, &bitsRead); // read whatever collected (resets buffer)
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(64, bitsRead); // even though we wrote 68 bits by now, output should be 64 since the last byte is not full so we should not receive it back
+    TEST_ASSERT_EQUAL_HEX(0xCB76102A, outBuffer[0]);
+    TEST_ASSERT_EQUAL_HEX(0xB76EC205, outBuffer[1]);
+    TEST_ASSERT_EQUAL_HEX(0, outBuffer[2]);
+    memset(outBuffer, 0, PAL_NOISE_SIZE_BYTES);
+
+    /*#6*/
+    status = pal_noiseRead(outBuffer, false, &bitsRead);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_NOISE_BUFFER_EMPTY, status);
+    TEST_ASSERT_EQUAL(0, bitsRead);
+
+    /*#7*/
+    status = pal_noiseWriteBuffer(inBuffer, ((sizeof(inBuffer) * CHAR_BIT) - 7), &bitsWritten); // write all except for the last 7 bits of index 2
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_EQUAL(((sizeof(inBuffer) * CHAR_BIT) - 7), bitsWritten);
+    status = pal_noiseRead(outBuffer, false, &bitsRead);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_NOISE_BUFFER_NOT_FULL, status);
+    TEST_ASSERT_EQUAL(0, bitsRead);
+    status = pal_noiseRead(outBuffer, true, &bitsRead); // read whatever collected (resets buffer)
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_NOT_EQUAL(0, bitsRead);
+    TEST_ASSERT_EQUAL_HEX(inBuffer[0], outBuffer[0]);
+    TEST_ASSERT_EQUAL_HEX(inBuffer[1], outBuffer[1]);
+    TEST_ASSERT_EQUAL_HEX(0x6AAD6A, outBuffer[2]);
+
+    /*#8*/
+    for (i = 0; i <= (sizeof(inBuffer) / sizeof(int32_t)); ++i)
+    {
+        status = pal_noiseWriteBuffer(inBuffer, (sizeof(inBuffer) * CHAR_BIT), &bitsWritten);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        TEST_ASSERT_EQUAL_HEX((sizeof(inBuffer) * CHAR_BIT), bitsWritten);
+    }
+    status = pal_noiseWriteBuffer(inBuffer, (sizeof(inBuffer) * CHAR_BIT), &bitsWritten);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_NOISE_BUFFER_FULL, status);
+    TEST_ASSERT_EQUAL_HEX(0, bitsWritten);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/RTOS/pal_rtos_test_runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "unity.h"
+#include "unity_fixture.h"
+#include "pal.h"
+#if 0 // MUST GO TO PLATFORM SPECIFIC FILE
+#include "fsl_device_registers.h"
+#include "fsl_debug_console.h"
+#include "board.h"
+
+#include "pin_mux.h"
+#include "clock_config.h"
+
+#endif // MUST GO TO PLATFORM SPECIFIC FILE
+
+TEST_GROUP_RUNNER(pal_rtos)
+{
+	RUN_TEST_CASE(pal_rtos, RealTimeClockTest1);
+	RUN_TEST_CASE(pal_rtos, SemaphoreWaitForever);
+	RUN_TEST_CASE(pal_rtos, pal_osKernelSysTick_Unity);
+	RUN_TEST_CASE(pal_rtos, pal_osKernelSysTick64_Unity);
+	RUN_TEST_CASE(pal_rtos, pal_osKernelSysTickMicroSec_Unity);
+	RUN_TEST_CASE(pal_rtos, pal_osKernelSysMilliSecTick_Unity);
+	RUN_TEST_CASE(pal_rtos, pal_osKernelSysTickFrequency_Unity);
+	RUN_TEST_CASE(pal_rtos, pal_osDelay_Unity);
+	RUN_TEST_CASE(pal_rtos, BasicTimeScenario);
+	RUN_TEST_CASE(pal_rtos, TimerUnityTest);
+	RUN_TEST_CASE(pal_rtos, AtomicIncrementUnityTest);
+	RUN_TEST_CASE(pal_rtos, GetDeviceKeyTest_CMAC);
+	RUN_TEST_CASE(pal_rtos, GetDeviceKeyTest_HMAC_SHA256);
+	RUN_TEST_CASE(pal_rtos, PrimitivesUnityTest1);
+	RUN_TEST_CASE(pal_rtos, PrimitivesUnityTest2);
+	RUN_TEST_CASE(pal_rtos, SemaphoreBasicTest);
+	RUN_TEST_CASE(pal_rtos, RandomUnityTest);
+	RUN_TEST_CASE(pal_rtos, loopRandomBigNumber);
+	RUN_TEST_CASE(pal_rtos, pal_init_test);
+	RUN_TEST_CASE(pal_rtos, Recursive_Mutex_Test);
+#if ((PAL_INT_FLASH_NUM_SECTIONS == 2) && PAL_USE_INTERNAL_FLASH)
+	RUN_TEST_CASE(pal_rtos, OsWeakSetTime_Forword);
+	RUN_TEST_CASE(pal_rtos, OsWeakSetTime_Backword);
+	RUN_TEST_CASE(pal_rtos, OsWeakSetTime_minimalStoredLag);
+	RUN_TEST_CASE(pal_rtos, OsStrongSetTime);
+#endif	
+	RUN_TEST_CASE(pal_rtos, pal_rtc);
+    RUN_TEST_CASE(pal_rtos, pal_noise);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/RTOS/pal_rtos_test_utils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,343 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include <stdio.h>
+#include "pal.h"
+#include "pal_rtos_test_utils.h"
+
+#include "pal_BSP.h"
+#include "unity_fixture.h"
+
+#include "pal.h"
+
+
+extern threadsArgument_t g_threadsArg;
+timerArgument_t timerArgs;
+
+void palThreadFunc1(void const *argument)
+{
+    volatile palThreadID_t threadID;
+	threadsArgument_t *tmp = (threadsArgument_t*)argument;
+#ifdef MUTEX_UNITY_TEST
+    palStatus_t status = PAL_SUCCESS;
+    PAL_PRINTF("palThreadFunc1::before mutex\n");
+    status = pal_osMutexWait(mutex1, 100);
+    PAL_PRINTF("palThreadFunc1::after mutex: 0x%08x\n", status);
+    PAL_PRINTF("palThreadFunc1::after mutex (expected): 0x%08x\n", PAL_ERR_RTOS_TIMEOUT);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_TIMEOUT, status);
+    return; // for Mutex scenario, this should end here
+#endif //MUTEX_UNITY_TEST
+
+	tmp->arg1 = 10;
+    threadID = pal_osThreadGetId();
+    TEST_ASSERT_NOT_EQUAL(threadID, NULLPTR);    
+    PAL_PRINTF("palThreadFunc1::Thread ID is %"PRIuPTR " \n", threadID);    
+#ifdef MUTEX_UNITY_TEST
+	status = pal_osMutexRelease(mutex1);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif //MUTEX_UNITY_TEST
+    PAL_PRINTF("palThreadFunc1::STAAAAM\n");
+}
+
+void palThreadFunc2(void const *argument)
+{
+    volatile palThreadID_t threadID;
+	threadsArgument_t *tmp = (threadsArgument_t*)argument;
+#ifdef MUTEX_UNITY_TEST
+    palStatus_t status = PAL_SUCCESS;
+    PAL_PRINTF("palThreadFunc2::before mutex\n");
+    status = pal_osMutexWait(mutex2, 300);
+    PAL_PRINTF("palThreadFunc2::after mutex: 0x%08x\n", status);
+    PAL_PRINTF("palThreadFunc2::after mutex (expected): 0x%08x\n", PAL_SUCCESS);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif //MUTEX_UNITY_TEST
+
+	tmp->arg2 = 20;
+    threadID = pal_osThreadGetId();
+    TEST_ASSERT_NOT_EQUAL(threadID, NULLPTR);    
+    PAL_PRINTF("palThreadFunc2::Thread ID is %"PRIuPTR "\n", threadID);
+#ifdef MUTEX_UNITY_TEST
+	status = pal_osMutexRelease(mutex2);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif //MUTEX_UNITY_TEST
+    PAL_PRINTF("palThreadFunc2::STAAAAM\n");
+}
+
+void palThreadFunc3(void const *argument)
+{
+    volatile palThreadID_t threadID;
+	threadsArgument_t *tmp = (threadsArgument_t*)argument;
+
+#ifdef SEMAPHORE_UNITY_TEST
+    palStatus_t status = PAL_SUCCESS;
+    uint32_t semaphoresAvailable = 10;
+    status = pal_osSemaphoreWait(semaphore1, 200, &semaphoresAvailable);
+    
+    if (PAL_SUCCESS == status)
+    {
+        PAL_PRINTF("palThreadFunc3::semaphoresAvailable: %d\n", semaphoresAvailable);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    else if(PAL_ERR_RTOS_TIMEOUT == status)
+    {
+        PAL_PRINTF("palThreadFunc3::semaphoresAvailable: %d\n", semaphoresAvailable);
+        PAL_PRINTF("palThreadFunc3::status: 0x%08x\n", status);
+        PAL_PRINTF("palThreadFunc3::failed to get Semaphore as expected\n", status);
+        TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_TIMEOUT, status);
+        return;
+    }
+    pal_osDelay(6000);
+#endif //SEMAPHORE_UNITY_TEST
+    tmp->arg3 = 30;
+    threadID = pal_osThreadGetId();
+    TEST_ASSERT_NOT_EQUAL(threadID, NULLPTR);    
+    PAL_PRINTF("palThreadFunc3::Thread ID is %"PRIuPTR "\n", threadID);
+
+#ifdef SEMAPHORE_UNITY_TEST
+    status = pal_osSemaphoreRelease(semaphore1);
+    PAL_PRINTF("palThreadFunc3::pal_osSemaphoreRelease res: 0x%08x\n", status);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif //SEMAPHORE_UNITY_TEST
+    PAL_PRINTF("palThreadFunc3::STAAAAM\n");
+}
+
+void palThreadFunc4(void const *argument)
+{
+    volatile palThreadID_t threadID;
+	threadsArgument_t *tmp = (threadsArgument_t*)argument;
+#ifdef MUTEX_UNITY_TEST
+    palStatus_t status = PAL_SUCCESS;
+    PAL_PRINTF("palThreadFunc4::before mutex\n");
+    status = pal_osMutexWait(mutex1, 200);
+    PAL_PRINTF("palThreadFunc4::after mutex: 0x%08x\n", status);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    pal_osDelay(3500);  //wait 3.5 seconds to make sure that the next thread arrive to this point
+#endif //MUTEX_UNITY_TEST
+
+	tmp->arg4 = 40;
+    threadID = pal_osThreadGetId();
+    TEST_ASSERT_NOT_EQUAL(threadID, NULLPTR);    
+    PAL_PRINTF("Thread ID is %"PRIuPTR "\n", threadID);
+
+#ifdef MUTEX_UNITY_TEST
+    status = pal_osMutexRelease(mutex1);
+    PAL_PRINTF("palThreadFunc4::after release mutex: 0x%08x\n", status);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif //MUTEX_UNITY_TEST
+    PAL_PRINTF("palThreadFunc4::STAAAAM\n");
+}
+
+void palThreadFunc5(void const *argument)
+{
+    volatile palThreadID_t threadID;
+	threadsArgument_t *tmp = (threadsArgument_t*)argument;
+#ifdef MUTEX_UNITY_TEST
+    palStatus_t status = PAL_SUCCESS;
+    PAL_PRINTF("palThreadFunc5::before mutex\n");
+    status = pal_osMutexWait(mutex1, 4500);
+    PAL_PRINTF("palThreadFunc5::after mutex: 0x%08x\n", status);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif //MUTEX_UNITY_TEST
+	tmp->arg5 = 50;
+    threadID = pal_osThreadGetId();
+    TEST_ASSERT_NOT_EQUAL(threadID, NULLPTR);    
+    PAL_PRINTF("Thread ID is %"PRIuPTR "\n", threadID);
+#ifdef MUTEX_UNITY_TEST
+    status = pal_osMutexRelease(mutex1);
+    PAL_PRINTF("palThreadFunc5::after release mutex: 0x%08x\n", status);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif //MUTEX_UNITY_TEST
+    PAL_PRINTF("palThreadFunc5::STAAAAM\n");
+}
+
+void palThreadFunc6(void const *argument)
+{
+	volatile palThreadID_t threadID;
+	threadsArgument_t *tmp = (threadsArgument_t*)argument;
+#ifdef SEMAPHORE_UNITY_TEST
+    palStatus_t status = PAL_SUCCESS;
+    uint32_t semaphoresAvailable = 10;
+    status = pal_osSemaphoreWait(123456, 200, &semaphoresAvailable);  //MUST fail, since there is no semaphore with ID=3
+    PAL_PRINTF("palThreadFunc6::semaphoresAvailable: %d\n", semaphoresAvailable);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_PARAMETER, status);
+    return;
+#endif //SEMAPHORE_UNITY_TEST
+	tmp->arg6 = 60;
+    threadID = pal_osThreadGetId();
+    TEST_ASSERT_NOT_EQUAL(threadID, NULLPTR);
+    PAL_PRINTF("Thread ID is %"PRIuPTR "\n", threadID);
+#ifdef SEMAPHORE_UNITY_TEST
+    status = pal_osSemaphoreRelease(123456);
+    PAL_PRINTF("palThreadFunc6::pal_osSemaphoreRelease res: 0x%08x\n", status);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_RTOS_PARAMETER, status);
+#endif //SEMAPHORE_UNITY_TEST
+    PAL_PRINTF("palThreadFunc6::STAAAAM\n");
+}
+
+
+void palTimerFunc1(void const *argument)
+{
+    g_timerArgs.ticksInFunc1 = pal_osKernelSysTick();
+    PAL_PRINTF("ticks in palTimerFunc1: 0 - %" PRIu32 "\n", g_timerArgs.ticksInFunc1);
+    PAL_PRINTF("Once Timer function was called\n");
+}
+
+void palTimerFunc2(void const *argument)
+{
+    g_timerArgs.ticksInFunc2 = pal_osKernelSysTick();
+    PAL_PRINTF("ticks in palTimerFunc2: 0 - %" PRIu32 "\n", g_timerArgs.ticksInFunc2);
+    PAL_PRINTF("Periodic Timer function was called\n");
+}
+
+void palTimerFunc3(void const *argument)
+{
+    static int counter =0;
+    counter++;
+}
+
+void palTimerFunc4(void const *argument)
+{ 
+    static int counter =0;
+    counter++;
+	g_timerArgs.ticksInFunc1 = counter;
+}
+
+void palTimerFunc5(void const *argument) // function to count calls + wait alternatin short and long periods for timer drift test
+{
+    static int counter = 0;
+    counter++;
+    g_timerArgs.ticksInFunc1 = counter;
+    if (counter % 2 == 0)
+    {
+        pal_osDelay(PAL_TIMER_TEST_TIME_TO_WAIT_MS_LONG);
+    }
+    else
+    {
+        pal_osDelay(PAL_TIMER_TEST_TIME_TO_WAIT_MS_SHORT);
+    }
+}
+
+
+void palThreadFuncWaitForEverTest(void const *argument)
+{
+	pal_osDelay(PAL_TIME_TO_WAIT_MS/2);
+	pal_osSemaphoreRelease(*((palSemaphoreID_t*)(argument)));
+}
+
+void palRunThreads()
+{
+	palStatus_t status = PAL_SUCCESS;
+	palThreadID_t threadID1 = NULLPTR;
+	palThreadID_t threadID2 = NULLPTR;
+	palThreadID_t threadID3 = NULLPTR;
+	palThreadID_t threadID4 = NULLPTR;
+	palThreadID_t threadID5 = NULLPTR;
+	palThreadID_t threadID6 = NULLPTR;
+
+	status = pal_osThreadCreateWithAlloc(palThreadFunc1, &g_threadsArg, PAL_osPriorityIdle, PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID1);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadCreateWithAlloc(palThreadFunc2, &g_threadsArg, PAL_osPriorityLow, PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID2);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadCreateWithAlloc(palThreadFunc3, &g_threadsArg, PAL_osPriorityNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID3);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadCreateWithAlloc(palThreadFunc4, &g_threadsArg, PAL_osPriorityBelowNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID4);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osDelay(PAL_RTOS_THREAD_CLEANUP_TIMER_MILISEC * 2); // dealy to work around mbedOS timer issue (starting more than 6 timers at once will cause a hang)
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadCreateWithAlloc(palThreadFunc5, &g_threadsArg, PAL_osPriorityAboveNormal, PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID5);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadCreateWithAlloc(palThreadFunc6, &g_threadsArg, PAL_osPriorityHigh, PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID6);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	pal_osDelay(PAL_TIME_TO_WAIT_MS/5);
+
+	status = pal_osThreadTerminate(&threadID1);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadTerminate(&threadID2);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadTerminate(&threadID3);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadTerminate(&threadID4);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadTerminate(&threadID5);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadTerminate(&threadID6);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+}
+
+void RecursiveLockThread(void const *param)
+{
+	size_t i = 0;
+	palStatus_t status;
+	palRecursiveMutexParam_t *actualParams = (palRecursiveMutexParam_t*)param;
+    size_t countbeforeStart = 0;
+    volatile palThreadID_t threadID = 10;
+	
+    status = pal_osSemaphoreWait(actualParams->sem, PAL_RTOS_WAIT_FOREVER, NULL);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    for (i = 0; i < 100; ++i)
+	{
+		status = pal_osMutexWait(actualParams->mtx, PAL_RTOS_WAIT_FOREVER);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        if (i == 0)
+        {
+            countbeforeStart = actualParams->count;
+            TEST_ASSERT_EQUAL_HEX(NULLPTR, actualParams->activeThread);
+            actualParams->activeThread = pal_osThreadGetId();
+        }
+        actualParams->count++;
+        threadID = pal_osThreadGetId();
+        TEST_ASSERT_NOT_EQUAL(NULLPTR, threadID);
+        TEST_ASSERT_EQUAL(actualParams->activeThread, threadID);
+        pal_osDelay(1);
+	}
+
+    threadID = 10;
+    pal_osDelay(50);
+    TEST_ASSERT_EQUAL(100, actualParams->count - countbeforeStart);
+	for (i = 0; i < 100; ++i)
+	{
+        threadID = pal_osThreadGetId();
+        TEST_ASSERT_NOT_EQUAL(NULLPTR, threadID);
+        TEST_ASSERT_EQUAL(actualParams->activeThread, threadID);
+		actualParams->count++;
+		if (i == 99)
+        {
+            TEST_ASSERT_EQUAL(200, actualParams->count - countbeforeStart);
+            actualParams->activeThread = NULLPTR;
+        }
+
+        status = pal_osMutexRelease(actualParams->mtx);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        pal_osDelay(1);
+	}
+  
+    status = pal_osSemaphoreRelease(actualParams->sem);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/RTOS/pal_rtos_test_utils.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef _PAL_RTOS_TEST_UTILS_H
+#define _PAL_RTOS_TEST_UTILS_H
+
+#include "pal.h"
+#include "pal_BSP.h"
+#if 0    //MUST MOVE TO PLATFORM SPECIFIC HEADER
+#include "fsl_device_registers.h"
+#include "fsl_debug_console.h"
+#include "board.h"
+
+#include "pin_mux.h"
+#include "clock_config.h"
+
+
+#define MUTEX_UNITY_TEST 1
+#define SEMAPHORE_UNITY_TEST 1
+#endif   // MUST MOVE TO PLATFORM SPECIFIC HEADER
+#define PAL_RANDOM_TEST_LOOP 100000
+#define PAL_RANDOM_ARRAY_TEST_SIZE 100
+#define PAL_RANDOM_BUFFER_ARRAY_TEST_SIZE 60
+#define PAL_TIME_TO_WAIT_MS	5000 //in [ms]
+#define PAL_TIME_TO_WAIT_SHORT_MS	300 //in [ms]
+#define PAL_TIMER_TEST_TIME_TO_WAIT_MS_SHORT 40 //in [ms]
+#define PAL_TIMER_TEST_TIME_TO_WAIT_MS_LONG 130 //in [ms]
+
+typedef struct threadsArgument{
+    uint32_t arg1;
+    uint32_t arg2;
+    uint32_t arg3;
+    uint32_t arg4;
+    uint32_t arg5;
+    uint32_t arg6;
+    uint32_t arg7;
+	uint8_t threadCounter;
+}threadsArgument_t;
+
+
+extern threadsArgument_t g_threadsArg;
+
+void palThreadFunc1(void const *argument);
+void palThreadFunc2(void const *argument);
+void palThreadFunc3(void const *argument);
+void palThreadFunc4(void const *argument);
+void palThreadFunc5(void const *argument);
+void palThreadFunc6(void const *argument);
+
+
+typedef struct timerArgument{
+    uint32_t ticksBeforeTimer;
+    uint32_t ticksInFunc1;
+    uint32_t ticksInFunc2;
+}timerArgument_t;
+
+extern timerArgument_t g_timerArgs;
+
+void palTimerFunc1(void const *argument);
+void palTimerFunc2(void const *argument);
+void palTimerFunc3(void const *argument);
+void palTimerFunc4(void const *argument);
+void palTimerFunc5(void const *argument);
+
+
+void palThreadFuncWaitForEverTest(void const *argument);
+
+void RecursiveLockThread(void const *param);
+typedef struct palRecursiveMutexParam{
+	palMutexID_t mtx;
+	palSemaphoreID_t sem;
+	size_t count;
+    palThreadID_t higherPriorityThread;
+    palThreadID_t lowerPriorityThread;
+    palThreadID_t activeThread;
+} palRecursiveMutexParam_t;
+
+#define MEMORY_POOL1_BLOCK_SIZE 32
+#define MEMORY_POOL1_BLOCK_COUNT 5
+#define MEMORY_POOL2_BLOCK_SIZE 12
+#define MEMORY_POOL2_BLOCK_COUNT 4
+
+extern palMutexID_t mutex1;
+extern palMutexID_t mutex2;
+
+extern palSemaphoreID_t semaphore1;
+
+#endif //_PAL_RTOS_TEST_UTILS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/SOTP/pal_SOTP_test.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,399 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal.h"
+#include "sotp.h"
+#include "unity.h"
+#include "unity_fixture.h"
+#include "test_runners.h"
+
+
+#define SOTP_DIR "/sotp"
+#define ROT_KEY_SIZE 16
+
+//add 5 years to minimum time
+#define PAL_TEST_START_TIME (PAL_MIN_SEC_FROM_EPOCH + ((PAL_SECONDS_PER_DAY * PAL_DAYS_IN_A_YEAR) * 5))
+#define ACCEPTABLE_DELAY_IN_SEC (5)
+#define PAL_SOTP_TEST_DELAY_IN_SEC (5 * 1000)
+
+
+extern palTestsStatusData_t palTestStatus;
+
+TEST_GROUP(pal_SOTP);
+
+#if (PAL_USE_HW_RTC)
+    static uint64_t systemRealRTC = 0;
+    static uint64_t systemStartTickCount = 0;
+#endif
+
+PAL_PRIVATE palCtrDrbgCtxHandle_t g_drbgCtx = NULLPTR;
+
+TEST_SETUP(pal_SOTP)
+{
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_init();
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#if (PAL_USE_HW_RTC == 1)
+    uint64_t sysTicks = 0;    
+    status = pal_plat_osGetRtcTime(&systemRealRTC);
+    if (systemRealRTC < (uint64_t)PAL_MIN_RTC_SET_TIME)
+    {
+        systemRealRTC = PAL_MIN_RTC_SET_TIME;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    systemStartTickCount = pal_osKernelSysTick();
+#endif
+}
+
+TEST_TEAR_DOWN(pal_SOTP)
+{
+    palStatus_t status = PAL_SUCCESS;
+#if (PAL_USE_HW_RTC == 1)
+    uint64_t sysTicks = 0;
+    uint64_t endTickCount = 0;
+    uint64_t timeToAddInSec = 0;
+    uint64_t timeToAddInMiliSec = 0;
+    endTickCount = pal_osKernelSysTick();
+    timeToAddInMiliSec = pal_osKernelSysMilliSecTick(endTickCount - systemStartTickCount); //switch from mili to seconds
+    timeToAddInSec = PAL_MILISEC_TO_SEC(timeToAddInMiliSec);
+    status = pal_plat_osSetRtcTime(systemRealRTC + timeToAddInSec);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif
+    if (g_drbgCtx)
+    {
+        pal_CtrDRBGFree(&g_drbgCtx);
+    }
+    status = pal_destroy();
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+}
+
+static palStatus_t writeDataInFS(uint8_t* data, size_t dataSize, char* dataName)
+{
+    palStatus_t status = PAL_SUCCESS, status2 = PAL_SUCCESS;
+    char filePath[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    palFileDescriptor_t fd = 0;
+    size_t dataSizeWritten = 0;
+
+    status = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, filePath);
+    strncat(filePath,SOTP_DIR,PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
+    if (PAL_SUCCESS == status) 
+    {
+         status = pal_fsMkDir(filePath);
+         if ((PAL_SUCCESS == status) || (PAL_ERR_FS_NAME_ALREADY_EXIST == status)) 
+         {
+             strncat(filePath,"/",PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
+             strncat(filePath,dataName,PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
+             status = pal_fsFopen(filePath,PAL_FS_FLAG_READWRITETRUNC,&fd);
+             if (PAL_SUCCESS == status)
+             {
+                 status =  pal_fsFwrite(&fd, (void *)data, dataSize, &dataSizeWritten);
+                 status2 = pal_fsFclose(&fd);
+                 if (PAL_SUCCESS != status2) 
+                 {
+                     PAL_LOG(ERR,"Failed to close data file of sotp pal testing after write");
+                 }
+             }
+         }
+
+    }
+    return status;
+}
+
+static palStatus_t readDataFromFS(uint8_t* data, size_t dataSize, char* dataName)
+{
+    palStatus_t status= PAL_SUCCESS, status2 = PAL_SUCCESS;
+    char filePath[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    palFileDescriptor_t fd = 0;
+    size_t dataSizeWritten = 0;
+
+    status = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, filePath);
+    strncat(filePath,SOTP_DIR,PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
+    if (PAL_SUCCESS == status) 
+    {
+         strncat(filePath,"/",PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
+         strncat(filePath,dataName,PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
+         status = pal_fsFopen(filePath, PAL_FS_FLAG_READONLY, &fd);
+         if (PAL_SUCCESS == status)
+         {
+             status =  pal_fsFread(&fd, (void *)data, dataSize, &dataSizeWritten);
+             status2 = pal_fsFclose(&fd);
+             if (PAL_SUCCESS != status2) 
+             {
+                 PAL_LOG(ERR,"Failed to close data file of sotp pal testing after read");
+             }
+             status2 = pal_fsUnlink(filePath);
+             if (PAL_SUCCESS != status2) 
+             {
+                 PAL_LOG(ERR,"Failed to delete data file of sotp pal testing after read");
+             }
+         }
+
+    }
+    return status;
+}
+
+TEST(pal_SOTP, SW_HW_RoT)
+{
+        uint32_t rotLength = ROT_KEY_SIZE;
+        palDevKeyType_t ketType = palOsStorageEncryptionKey128Bit;
+        uint8_t rotA[ROT_KEY_SIZE] = {0};
+        uint8_t rotB[ROT_KEY_SIZE] = {0};
+        sotp_result_e sotpStatus = SOTP_SUCCESS;
+        palStatus_t status = PAL_SUCCESS;
+        (void)sotpStatus;
+        if (palTestStatus.inner == -1) {
+            status = pal_osGetDeviceKey(ketType, rotA, rotLength);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        #if(PAL_USE_HW_ROT == 0) // test SW RoT
+            status = pal_osGetDeviceKey(ketType, rotB, rotLength);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+            TEST_ASSERT_TRUE(0 == memcmp(rotA,rotB,rotLength))
+
+            sotpStatus = sotp_delete(SOTP_TYPE_ROT);
+            TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpStatus);
+
+            memset(rotA,0,sizeof(rotA));
+
+            status = pal_osGetDeviceKey(ketType, rotA, rotLength);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+            /** 
+             * if there is no HW RoT, The Rot is generated from random. 
+             * So, if deleted and re generated there is no chance that the 
+             * ols RoT and the New will bw the same
+             **/ 
+            TEST_ASSERT_TRUE(0 != memcmp(rotA,rotB,rotLength))
+         #endif
+            status = writeDataInFS(rotA, rotLength,"RoT");
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            status = palTestReboot(PAL_TEST_MODULE_SOTP, PAL_TEST_SOTP_TEST_SW_HW_ROT);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        }//start here after the reboot
+        else 
+        {
+		updatePalTestStatusAfterReboot();
+
+            memset(rotA,0,sizeof(rotA));
+            memset(rotB,0,sizeof(rotB));
+
+            status = pal_osGetDeviceKey(ketType, rotA, rotLength);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+            status = readDataFromFS(rotB, rotLength, "RoT");
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+            TEST_ASSERT_TRUE(0 == memcmp(rotA,rotB,rotLength))
+        }
+}
+
+TEST(pal_SOTP, timeInit)
+{
+    // call pal destroy as this test need to start before pal_init()
+    
+    
+    palStatus_t status = PAL_SUCCESS;
+
+    status = pal_destroy();
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /** 
+     this is is splited to 2 different parts because of the ifdefs
+     if the end of this if is inside the #if (PAL_USE_HW_RTC == 1) 
+     in any other case, if this was a single if this had casue  
+     compilation error 
+     **/ 
+
+    
+    if (palTestStatus.inner == -1) 
+    {
+        #if ((PAL_USE_HW_RTC == 1) && (PAL_USE_INTERNAL_FLASH == 1) && (PAL_INT_FLASH_NUM_SECTION ==2))
+         {
+            uint64_t currentTime = 0;
+            sotpStatus = sotp_delete(SOTP_TYPE_SAVED_TIME);
+            TEST_ASSERT_TRUE((SOTP_SUCCESS == sotpStatus) || (SOTP_NOT_FOUND == sotpStatus))
+            status = pal_plat_osSetRtcTime((uint64_t)PAL_TEST_START_TIME);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            status = pal_init();
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            currentTime = pal_osGetTime();
+            TEST_ASSERT_TRUE((currentTime - ACCEPTABLE_DELAY_IN_SEC) <= PAL_TEST_START_TIME);
+            status = pal_destroy();
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            status = pal_plat_osSetRtcTime((uint64_t)0);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            status = pal_init();
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            status = pal_osDelay(PAL_SOTP_TEST_DELAY_IN_SEC);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            currentTime = pal_osGetTime();
+            TEST_ASSERT_EQUAL_HEX(0, currentTime);
+            status = pal_destroy();
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            currentTime = PAL_TEST_START_TIME;
+            sotpStatus = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&currentTime);
+            TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, status);
+            currentTime -= (PAL_SECONDS_PER_DAY * PAL_DAYS_IN_A_YEAR); // remove an year
+            status = pal_plat_osSetRtcTime(currentTime);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            status = pal_init();
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            currentTime = pal_osGetTime();
+            TEST_ASSERT_TRUE((PAL_TEST_START_TIME - ACCEPTABLE_DELAY_IN_SEC) <= currentTime);
+            status = pal_destroy();
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            currentTime = PAL_TEST_START_TIME;
+            status = pal_plat_osSetRtcTime(currentTime);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            currentTime -= (PAL_SECONDS_PER_DAY * PAL_DAYS_IN_A_YEAR); // remove an year
+            sotpStatus = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&currentTime);
+            TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, status);
+            status = pal_init();
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            currentTime = pal_osGetTime();
+            TEST_ASSERT_TRUE((currentTime - ACCEPTABLE_DELAY_IN_SEC) <= PAL_TEST_START_TIME);
+        #endif
+
+
+        #if ((PAL_USE_HW_RTC == 0) && (PAL_USE_INTERNAL_FLASH == 1) && (PAL_INT_FLASH_NUM_SECTION ==2))
+        {
+            uint64_t currentTime = 0;
+            currentTime = PAL_TEST_START_TIME; // remove an year
+            sotpStatus = sotp_set(SOTP_TYPE_SAVED_TIME, sizeof(uint64_t), (uint32_t *)&currentTime);
+            TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, status);
+            status = pal_init();
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+            currentTime = pal_osGetTime();
+            TEST_ASSERT_TRUE((PAL_TEST_START_TIME - ACCEPTABLE_DELAY_IN_SEC) <= currentTime);
+            status = pal_destroy();
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 
+        }
+        #endif
+    }
+    #if (PAL_USE_HW_RTC == 1)
+    {
+        uint64_t currentTime = 0;
+        if (palTestStatus.inner == -1) 
+         {
+            currentTime = PAL_TEST_START_TIME; // remove an year
+            status = pal_plat_osSetRtcTime(currentTime);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+            status = palTestReboot(PAL_TEST_MODULE_SOTP, PAL_TEST_SOTP_TEST_TIME_INIT);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+         }//start here after reboot
+         else
+         {
+        	updatePalTestStatusAfterReboot();
+            status = pal_plat_osGetRtcTime(&currentTime);
+            TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+            TEST_ASSERT_TRUE((currentTime - ACCEPTABLE_DELAY_IN_SEC) <= PAL_TEST_START_TIME);
+         }
+    }
+    #endif
+}
+
+// the following function is not part of PAL's external API hence extern
+extern palStatus_t pal_noiseRead(int32_t buffer[PAL_NOISE_BUFFER_LEN], bool partial, uint16_t* bitsRead);
+
+/*! \brief Test random buffer generation with sotp
+*
+* | # |    Step                                                        |  Expected   |
+* |---|----------------------------------------------------------------|-------------|
+* | 1 | Save a fixed seed to sotp or read current value is exists.     | PAL_SUCCESS |
+* | 2 | Generate short & long term seed.                               | PAL_SUCCESS |
+* | 3 | Generate expected random.                                      | PAL_SUCCESS |
+* | 4 | Call pal_osRandomBuffer and compare expected to actual random. | PAL_SUCCESS |
+* | 5 | Validate counter and next (boot) long term seed.               | PAL_SUCCESS |
+*/
+TEST(pal_SOTP, random)
+{
+    palStatus_t status;
+    sotp_result_e res;
+    uint16_t bytesRead = 0;
+    uint32_t counter = 0;
+    uint32_t counterCopy = 0;
+    uint8_t buf[(PAL_INITIAL_RANDOM_SIZE * 2 + sizeof(counter))] PAL_PTR_ADDR_ALIGN_UINT8_TO_UINT32 = { 0 };
+    bool sotpRandomExists = false;
+
+#if !PAL_USE_HW_TRNG
+    uint16_t bitsRead = 0;
+    int32_t noiseBuffer[PAL_NOISE_BUFFER_LEN] = { 0 };
+    pal_noiseRead(noiseBuffer, true, &bitsRead);
+#endif // !PAL_USE_HW_TRNG
+
+    /*#1*/
+    res = sotp_get(SOTP_TYPE_RANDOM_SEED, (PAL_INITIAL_RANDOM_SIZE + sizeof(counter)), (uint32_t*)buf, &bytesRead); // read 48 drbg bytes + 4 counter bytes
+    TEST_ASSERT_TRUE(SOTP_SUCCESS == res || SOTP_NOT_FOUND == res);
+    if (SOTP_SUCCESS == res)
+    {
+        memcpy((void*)&counter, (void*)&buf[PAL_INITIAL_RANDOM_SIZE], sizeof(counter));
+        sotpRandomExists = true;
+    }
+    else if (SOTP_NOT_FOUND == res)
+    {
+        memset((void*)buf, 7, PAL_INITIAL_RANDOM_SIZE); // fixed dummy seed
+        res = sotp_set(SOTP_TYPE_RANDOM_SEED, PAL_INITIAL_RANDOM_SIZE, (uint32_t*)buf);
+        TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, res);
+    }
+
+    /*#2*/
+    status = pal_CtrDRBGInit(&g_drbgCtx, (void*)buf, PAL_INITIAL_RANDOM_SIZE);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    memset((void*)buf, 0, sizeof(buf));
+    status = pal_CtrDRBGGenerate(g_drbgCtx, (unsigned char*)buf, PAL_INITIAL_RANDOM_SIZE * 2); // generate 48 bytes long term & 48 bytes short term seed
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    status = pal_CtrDRBGFree(&g_drbgCtx);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    g_drbgCtx = NULLPTR;
+
+    /*#3*/
+    status = pal_CtrDRBGInit(&g_drbgCtx, (void*)buf, PAL_INITIAL_RANDOM_SIZE);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    memset((void*)buf, 0, PAL_INITIAL_RANDOM_SIZE);
+    status = pal_CtrDRBGGenerate(g_drbgCtx, (unsigned char*)buf, PAL_INITIAL_RANDOM_SIZE); // generate expected random buffer
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    status = pal_CtrDRBGFree(&g_drbgCtx);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    g_drbgCtx = NULLPTR;
+
+    /*#4*/
+    uint8_t random[PAL_INITIAL_RANDOM_SIZE] = { 0 };
+    status = pal_osRandomBuffer(random, PAL_INITIAL_RANDOM_SIZE); // get the actual random buffer
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#if !PAL_USE_HW_TRNG
+    TEST_ASSERT_EQUAL_MEMORY(buf, random, PAL_INITIAL_RANDOM_SIZE);
+#endif // !PAL_USE_HW_TRNG
+
+    /*#5*/
+    memmove(&buf[(PAL_INITIAL_RANDOM_SIZE + sizeof(counter))], &buf[PAL_INITIAL_RANDOM_SIZE], PAL_INITIAL_RANDOM_SIZE); // make space for the counter while preserving next seed bytes
+    memset((void*)buf, 0, (PAL_INITIAL_RANDOM_SIZE + sizeof(counter)));
+    counterCopy = counter;
+    res = sotp_get(SOTP_TYPE_RANDOM_SEED, (PAL_INITIAL_RANDOM_SIZE + sizeof(counter)), (uint32_t*)buf, &bytesRead);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, res);
+    TEST_ASSERT_EQUAL((PAL_INITIAL_RANDOM_SIZE + sizeof(counter)), bytesRead);
+    memcpy((void*)&counter, (void*)&buf[PAL_INITIAL_RANDOM_SIZE], sizeof(counter)); // read the counter from sotp data
+    TEST_ASSERT_EQUAL(counterCopy + 1, counter);
+#if !PAL_USE_HW_TRNG
+    TEST_ASSERT_EQUAL_MEMORY(&buf[(PAL_INITIAL_RANDOM_SIZE + sizeof(counter))], buf, PAL_INITIAL_RANDOM_SIZE);
+#endif // !PAL_USE_HW_TRNG
+
+    if (false == sotpRandomExists)
+    {
+        res = sotp_delete(SOTP_TYPE_RANDOM_SEED);
+        TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, res);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/SOTP/pal_SOTP_test_runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "unity.h"
+#include "unity_fixture.h"
+#include "test_runners.h"
+
+extern palTestsStatusData_t palTestStatus;
+
+TEST_GROUP_RUNNER(pal_SOTP)
+{
+    switch (palTestStatus.test) 
+    {
+    case -1:
+    case PAL_TEST_SOTP_TEST_SW_HW_ROT:
+        RUN_TEST_CASE(pal_SOTP, SW_HW_RoT);
+    case PAL_TEST_SOTP_TEST_TIME_INIT:
+        RUN_TEST_CASE(pal_SOTP, timeInit);
+    case PAL_TEST_SOTP_TEST_RANDOM:
+        RUN_TEST_CASE(pal_SOTP, random);
+        break;
+    default:
+        PAL_PRINTF("This should not happen\r\n");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Sanity/pal_sanity_test.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#include "unity.h"
+#include "unity_fixture.h"
+#include "pal.h"
+
+
+TEST_GROUP(pal_sanity);
+
+TEST_SETUP(pal_sanity)
+{
+
+}
+
+TEST_TEAR_DOWN(pal_sanity)
+{
+
+}
+
+
+TEST(pal_sanity, bringupPassed)
+{
+    PAL_LOG(INFO, "device bringup passed\r\n");
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Sanity/pal_sanity_test_runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "unity.h"
+#include "unity_fixture.h"
+#include "pal.h"
+
+
+TEST_GROUP_RUNNER(pal_sanity)
+{
+    RUN_TEST_CASE(pal_sanity, bringupPassed);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Storage/pal_internalFlash_test.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,316 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal.h"
+#include "unity.h"
+#include "unity_fixture.h"
+
+#if PAL_USE_INTERNAL_FLASH
+
+TEST_GROUP(pal_internalFlash);
+#define LITTLE_BUFFER_SIZE					120
+#define PRIME_NUMBER_FOR_TESTING			11 //must be 4 times lower then LITTLE_BUFFER_SIZE
+#define MAX_BUFFER_SIZE                     0x1000
+
+palSotpAreaData_t areaOneData;
+palSotpAreaData_t areaTwoData;
+uint32_t *ReadBuffer = NULL;
+uint32_t *compareBuffer = NULL;
+uint32_t biggestSectorSize = 0;
+
+
+palStatus_t InternalFlashWriteTest(uint32_t address_offset);
+palStatus_t InternalFlashReadTest(uint32_t address_offset);
+
+TEST_SETUP(pal_internalFlash)
+{
+	palStatus_t status = PAL_SUCCESS;
+	status = pal_internalFlashGetAreaInfo(0, &areaOneData);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+	status = pal_internalFlashGetAreaInfo(1, &areaTwoData);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+	biggestSectorSize = (PAL_MAX(areaTwoData.size, areaOneData.size));
+	biggestSectorSize = (PAL_MIN(biggestSectorSize, MAX_BUFFER_SIZE)); //there are sector size 128KB so this limit the buffer to 4KB
+	ReadBuffer = (uint32_t *)malloc(biggestSectorSize);
+	TEST_ASSERT_NOT_NULL(ReadBuffer);
+	compareBuffer = (uint32_t *)malloc(biggestSectorSize);
+	TEST_ASSERT_NOT_NULL(compareBuffer);
+    pal_init();
+}
+
+TEST_TEAR_DOWN(pal_internalFlash)
+{
+	if (compareBuffer != NULL)
+	{
+		free(compareBuffer);
+		compareBuffer = NULL;
+	}
+
+	if (ReadBuffer != NULL)
+	{
+		free(ReadBuffer);
+		ReadBuffer = NULL;
+	}
+    pal_destroy();
+}
+
+/*! \brief This function checks if the flash needed to be deleted by checking if all bytes in sector are 0xFF */
+void SectorDeleteValidity(uint32_t address, size_t size)
+{
+	palStatus_t status = PAL_SUCCESS;
+	uint32_t index = 0;
+	memset(ReadBuffer, 0, biggestSectorSize);
+
+	status = pal_internalFlashRead(biggestSectorSize, address, ReadBuffer);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+	for(index = 0; index < biggestSectorSize; index++)
+	{
+		if(*((uint8_t*)ReadBuffer + index) != 0xFF)
+		{
+		    status = pal_internalFlashErase(address, size);
+		    TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+		    break;
+		}
+
+	}
+}
+
+/*! \brief Basic read write & erase tests
+ *
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Check if Sector A and B are erased                               | 			   |
+* | 2 | Read sector A & B and compare them to 0xFF (erased sector)       | PAL_SUCCESS |
+* | 3 | Run Write tests See function for more details                    | PAL_SUCCESS |
+* | 4 | Run Read tests See function for more details                     | PAL_SUCCESS |
+* | 5 | fill sector B with provided Data (full sector write)             | PAL_SUCCESS |
+* | 6 | Read full sector and compare                                     | PAL_SUCCESS |
+* | 7 | Delete Sector one                                                | PAL_SUCCESS |
+* | 8 | Read and verify that sector two in not changed                   | PAL_SUCCESS |
+* | 9 | Delete Sector two                                                | PAL_SUCCESS |
+* | 10 | read compare both sectors to 0xff (verify erased)               | PAL_SUCCESS |
+*/
+TEST(pal_internalFlash, BasicTest)
+{
+	palStatus_t status = PAL_SUCCESS;
+	/*1*/
+    SectorDeleteValidity(areaOneData.address, areaOneData.size);
+    SectorDeleteValidity(areaTwoData.address, areaTwoData.size);
+
+	memset(compareBuffer, 0xFF, biggestSectorSize);
+	memset(ReadBuffer, 0, biggestSectorSize);
+
+	/*2*/
+    DEBUG_PRINT("Read both sectors and compare to 0xFF \n\r");
+	status = pal_internalFlashRead(biggestSectorSize, areaOneData.address, ReadBuffer);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+	TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t *)ReadBuffer, (uint8_t *)compareBuffer, biggestSectorSize);
+
+	status = pal_internalFlashRead(biggestSectorSize, areaTwoData.address, ReadBuffer);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+	TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t *)ReadBuffer, (uint8_t *)compareBuffer, biggestSectorSize);
+
+	/*3*/
+	status = InternalFlashWriteTest(areaOneData.address);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+	/*4*/
+	status = InternalFlashReadTest(areaOneData.address + 2 * LITTLE_BUFFER_SIZE);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+
+
+	DEBUG_PRINT("---------FULL SECTOR TEST---------\n\r");
+    for (uint32_t i = 0; i < biggestSectorSize; i++)
+    {
+    	((uint8_t *)compareBuffer)[biggestSectorSize - i - 1] = (uint8_t)(i % 256);
+    }
+    DEBUG_PRINT("Write data to second sector\n\r");
+    /*5*/
+	status = pal_internalFlashWrite(biggestSectorSize, areaTwoData.address, compareBuffer);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+
+	/*6*/
+	memset(ReadBuffer, 0, biggestSectorSize);
+	DEBUG_PRINT("Read and compare from second sector\n\r");
+	status = pal_internalFlashRead(biggestSectorSize, areaTwoData.address, ReadBuffer);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+	TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t *)ReadBuffer, (uint8_t *)compareBuffer, biggestSectorSize);
+
+	/*7*/
+	DEBUG_PRINT("Delete sector one\n\r");
+   status = pal_internalFlashErase(areaOneData.address, areaOneData.size);
+   TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+
+   /*8*/
+	DEBUG_PRINT("Verify that sector 2 was not changed in sector one erasing\n\r");
+	status = pal_internalFlashRead(biggestSectorSize, areaTwoData.address, ReadBuffer);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+	TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t *)ReadBuffer, (uint8_t *)compareBuffer, biggestSectorSize);
+
+	/*9*/
+	DEBUG_PRINT("Delete sector two\n\r");
+   status = pal_internalFlashErase(areaTwoData.address, areaTwoData.size);
+   TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+
+   /*10*/
+   memset(compareBuffer, 0xFF, biggestSectorSize);
+   DEBUG_PRINT("Read both sectors and compare to 0xFF (verify that erase is done)\n\r");
+	status = pal_internalFlashRead(biggestSectorSize, areaOneData.address, ReadBuffer);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+	TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t *)ReadBuffer, (uint8_t *)compareBuffer, biggestSectorSize);
+
+	status = pal_internalFlashRead(biggestSectorSize, areaTwoData.address, ReadBuffer);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+	TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t *)ReadBuffer, (uint8_t *)compareBuffer, biggestSectorSize);
+}
+
+
+
+/*! \brief Write tests to internal Flash with different sizes
+*
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Write Data to sector from align address and up to prime number, prime number will never divide in page size     | PAL_SUCCESS |
+* | 2 | Read & compare Data up to prime number												       						| PAL_SUCCESS |
+* | 3 | Write Data from  next align address from the prime number up to buffer size                  					| PAL_SUCCESS |
+* | 4 | Read & compare Data from prime number and up to end of buffer						       						| PAL_SUCCESS |
+*/
+
+
+palStatus_t InternalFlashWriteTest(uint32_t address_offset)
+{
+	palStatus_t status = PAL_SUCCESS;
+	uint32_t alignPage = pal_internalFlashGetPageSize();
+
+	TEST_ASSERT_NOT_EQUAL(alignPage, 0);
+
+	DEBUG_PRINT("---------WRITE TEST---------r\n\r");
+	memset(compareBuffer, 0xFF, biggestSectorSize);
+	memset(ReadBuffer, 0, biggestSectorSize);
+
+    for (uint32_t i = 0; i < PRIME_NUMBER_FOR_TESTING; i++)
+    {
+    	compareBuffer[i] = (uint8_t)(i % 256);
+    }
+    /*1*/
+    DEBUG_PRINT("Write data to First Sector up to PRIME_NUMBER_FOR_TESTINGr\n\r");
+	status = pal_internalFlashWrite(PRIME_NUMBER_FOR_TESTING, address_offset, compareBuffer);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+
+	/*2*/
+	DEBUG_PRINT("Read and compare from first sector\n\r");
+	status = pal_internalFlashRead(PRIME_NUMBER_FOR_TESTING, address_offset, ReadBuffer);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+	TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t *)ReadBuffer, (uint8_t *)compareBuffer, PRIME_NUMBER_FOR_TESTING);
+
+    for (uint32_t i = PRIME_NUMBER_FOR_TESTING; i < LITTLE_BUFFER_SIZE / 4 ; i++)
+    {
+    	compareBuffer[i] = (uint32_t)(i % 256);
+    }
+
+    /*3*/
+    uint32_t offset = PRIME_NUMBER_FOR_TESTING - (PRIME_NUMBER_FOR_TESTING % alignPage) + alignPage;
+    DEBUG_PRINT("Write data to First Sector from PRIME_NUMBER_FOR_TESTING up to LITTLE_BUFFER_SIZE\n\r");
+	status = pal_internalFlashWrite(LITTLE_BUFFER_SIZE - offset, address_offset + offset, compareBuffer + offset / 4);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+
+	/*4*/
+	DEBUG_PRINT("Read and compare from first sector\n\r");
+	status = pal_internalFlashRead(LITTLE_BUFFER_SIZE - offset, address_offset + offset, ReadBuffer + offset / 4);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+	TEST_ASSERT_EQUAL_UINT8_ARRAY((uint8_t *)ReadBuffer + offset, (uint8_t *)compareBuffer + offset, LITTLE_BUFFER_SIZE - offset);
+	return PAL_SUCCESS;
+}
+
+
+/*! \brief read tests with different sizes
+ * *
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Write data to sector                                | PAL_SUCCESS |
+* | 2 | Read data in chunks of bytes and compare            | PAL_SUCCESS |
+*/
+
+palStatus_t InternalFlashReadTest(uint32_t address_offset)
+{
+	palStatus_t status = PAL_SUCCESS;
+	DEBUG_PRINT("---------READ TEST---------r\n\r");
+	memset(compareBuffer, 0xFF, biggestSectorSize);
+	memset(ReadBuffer, 0, biggestSectorSize);
+    for (uint32_t i = 0; i < LITTLE_BUFFER_SIZE / 4; i++)
+    {
+    	ReadBuffer[i] = (uint32_t)(i % 256);
+    }
+    /*1*/
+    DEBUG_PRINT("Write data to Sector up to LITTLE_BUFFER_SIZE\n\r");
+	status = pal_internalFlashWrite(LITTLE_BUFFER_SIZE, address_offset, ReadBuffer);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+
+	/*2*/
+	DEBUG_PRINT("Read and compare\n\r");
+    for (uint32_t i = 0; i < LITTLE_BUFFER_SIZE / 4; i++)
+    {
+    	uint32_t value = 0;
+    	status = pal_internalFlashRead(1, address_offset + i, &value);
+    	TEST_ASSERT_EQUAL_HEX(status, PAL_SUCCESS);
+    	TEST_ASSERT_EQUAL_HEX(*((uint8_t *)ReadBuffer + i), (uint8_t)value);
+    }
+    return PAL_SUCCESS;
+}
+
+/*! \brief Negative tests to verify validations and errors
+ *
+** \test
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Delete sector with unaligned address                                | PAL_ERR_INTERNAL_FLASH_SECTOR_NOT_ALIGNED |
+* | 2 | Write with null ptr has buffer					                    | PAL_ERR_INTERNAL_FLASH_CROSSING_SECTORS |
+* | 3 | write with address not align to page size               		    | PAL_ERR_INTERNAL_FLASH_ADDRESS_NOT_ALIGNED |
+* | 4 | write to unaligned buffer  								            | PAL_ERR_INTERNAL_FLASH_BUFFER_ADDRESS_NOT_ALIGNED |
+*/
+
+TEST(pal_internalFlash, NegativeTest)
+{
+#ifdef DEBUG
+	palStatus_t status = PAL_SUCCESS;
+	uint8_t alignPage = pal_internalFlashGetPageSize();
+	uint32_t * ReadBuffer1 = NULL;
+	TEST_ASSERT_NOT_EQUAL(alignPage, 0);
+
+	/*1*/
+    status = pal_internalFlashErase(areaOneData.address + 4, areaOneData.size);
+    TEST_ASSERT_EQUAL_HEX(status, PAL_ERR_INTERNAL_FLASH_SECTOR_NOT_ALIGNED);
+
+	/*2*/
+	status = pal_internalFlashWrite(areaOneData.size * 2, areaOneData.address, ReadBuffer1);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_ERR_INTERNAL_FLASH_NULL_PTR_RECEIVED);
+
+	/*3*/
+	if( pal_internalFlashGetPageSize() > 1)
+	{//This test only valid if page size is bigger then 1
+	    status = pal_internalFlashWrite(8, (uint32_t)4, (uint32_t*)&ReadBuffer1);
+	    TEST_ASSERT_EQUAL_HEX(status, PAL_ERR_INTERNAL_FLASH_ADDRESS_NOT_ALIGNED);
+	}
+
+	/*4*/
+	status = pal_internalFlashWrite(8 , areaOneData.address + alignPage + 1, (uint32_t*)0x11);
+	TEST_ASSERT_EQUAL_HEX(status, PAL_ERR_INTERNAL_FLASH_BUFFER_ADDRESS_NOT_ALIGNED);
+#endif
+}
+
+#endif //PAL_USE_INTERNAL_FLASH
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Storage/pal_internalFlash_test_runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "unity.h"
+#include "unity_fixture.h"
+#include "test_runners.h"
+
+
+TEST_GROUP_RUNNER(pal_internalFlash)
+{
+    #if PAL_USE_INTERNAL_FLASH
+    	RUN_TEST_CASE(pal_internalFlash, BasicTest);
+    	RUN_TEST_CASE(pal_internalFlash, NegativeTest);
+    #endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2189 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "unity.h"
+#include "unity_fixture.h"
+#include "pal.h"
+#include "pal_tls_utils.h"
+#include "pal_network.h"
+#include "stdlib.h"
+#include "sotp.h"
+#include "test_runners.h"
+
+#define TRACE_GROUP "TLS_TESTS"
+#define PAL_TEST_PSK_IDENTITY "Client_identity"
+
+#define PAL_TEST_PSK {0x12,0x34,0x45,0x67,0x89,0x10}
+#define PAL_WAIT_TIME	3
+
+PAL_PRIVATE palSocket_t g_socket = 0;
+extern void * g_palTestTLSInterfaceCTX; // this is set by the palTestMain funciton
+PAL_PRIVATE uint32_t g_interfaceCTXIndex = 0;
+
+#if ((PAL_USE_SECURE_TIME == 1) && (PAL_USE_INTERNAL_FLASH == 1))
+    PAL_PRIVATE uint8_t g_trustedServerID[PAL_CERT_ID_SIZE] __attribute__((aligned(4))) = { 0 };
+    PAL_PRIVATE size_t g_actualServerIDSize = 0;
+#endif 
+
+PAL_PRIVATE palMutexID_t g_mutex1 = NULLPTR;
+#if (PAL_ENABLE_X509 == 1)
+	PAL_PRIVATE palMutexID_t g_mutex2 = NULLPTR;
+#endif
+PAL_PRIVATE palMutexID_t g_mutexHandShake1 = NULLPTR;
+PAL_PRIVATE bool g_retryHandshake = false;
+PAL_PRIVATE const uint8_t g_coapHelloWorldRequest[16] = { 0x50,0x01,0x57,0x3e,0xff,0x2f,0x68,0x65,0x6c,0x6c,0x6f,0x57,0x6f,0x72,0x6c,0x64 };
+
+#define PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(a, b) \
+    if (a != b) \
+    {\
+        PAL_LOG(ERR,"Expected: %" PRId32 " , Actual: %" PRId32 " , Line: %d\n", (int32_t)a, (int32_t)b, __LINE__);\
+        goto finish;\
+    }
+
+
+//! This structre is for tests only and MUST be the same structure as in the pal_TLS.c file
+//! For any change done in the original structure, please make sure to change this structure too.
+typedef struct palTLSService
+{
+	bool retryHandShake;
+	uint64_t serverTime;
+	palTLSHandle_t platTlsHandle;
+}palTLSTest_t;
+
+TEST_GROUP(pal_tls);
+
+TEST_SETUP(pal_tls)
+{
+    palStatus_t status = PAL_SUCCESS;
+    uint64_t currentTime = 1504893346; //GMT: Friday, September 8, 2017 5:55:46 PM
+
+    pal_init();
+
+    if (g_palTestTLSInterfaceCTX == NULL)
+    {
+        PAL_LOG(ERR, "error: net interface not configutred correctly");
+    }
+    else
+    {
+        status = pal_registerNetworkInterface(g_palTestTLSInterfaceCTX, &g_interfaceCTXIndex);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+
+    g_socket = 0;
+
+    status = pal_osSetTime(currentTime);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+}
+
+TEST_TEAR_DOWN(pal_tls)
+{
+    sotp_result_e sotpRes = SOTP_SUCCESS;
+    if (0 != g_socket)
+    {
+        pal_close(&g_socket);
+    }
+
+	sotpRes = sotp_delete(SOTP_TYPE_TRUSTED_TIME_SRV_ID);
+	TEST_ASSERT_TRUE((SOTP_SUCCESS == sotpRes) || (SOTP_NOT_FOUND == sotpRes));
+    
+    pal_destroy();
+}
+
+/**
+* @brief Test TLS cofiguration initialization and uninitialization.
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize TLS configuration using `pal_initTLSConfiguration`.       | PAL_SUCCESS |
+* | 2 | Uninitialize TLS configuration using `pal_tlsConfigurationFree`.     | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsConfiguration)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palTLSConfHandle_t palTLSConf = NULLPTR;
+    palTLSTransportMode_t transportationMode =     PAL_TLS_MODE;
+    /*#1*/
+    status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_TRUE(NULLPTR != palTLSConf);
+    /*#2*/
+    status = pal_tlsConfigurationFree(&palTLSConf);
+    TEST_ASSERT_EQUAL_HEX(NULLPTR, palTLSConf);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+}
+
+int palTestEntropySource(void *data, unsigned char *output, size_t len, size_t *olen)
+{
+    palStatus_t status = PAL_SUCCESS;
+    (void)data;
+
+    status = pal_osRandomBuffer(output, len);
+    if (PAL_SUCCESS == status)
+    {
+        *olen = len;
+    }
+    else
+    {
+        return -1;
+    }
+    return 0;
+}
+
+static void handshakeUDP(bool socketNonBlocking)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palTLSConfHandle_t palTLSConf = NULLPTR;
+    palTLSHandle_t palTLSHandle = NULLPTR;
+    palTLSTransportMode_t transportationMode =     PAL_DTLS_MODE;
+    palSocketAddress_t socketAddr = {0};
+    palSocketLength_t addressLength = 0;
+    char serverResponse[PAL_TLS_MESSAGE_SIZE] = {0};
+    uint32_t actualLen = 0;
+    uint32_t written = 0;
+    #if (PAL_ENABLE_X509 == 1)
+        palX509_t pubKey = {(const void*)g_pubKey,sizeof(g_pubKey)};
+        palPrivateKey_t prvKey = {(const void*)g_prvKey,sizeof(g_prvKey)};
+        palX509_t caCert = { (const void*)pal_test_cas,sizeof(pal_test_cas) };
+    #elif (PAL_ENABLE_PSK == 1)
+        const char* identity = PAL_TEST_PSK_IDENTITY;
+        const char psk[]= PAL_TEST_PSK;
+    #endif
+    palTLSSocket_t tlsSocket = {g_socket, &socketAddr, 0, transportationMode};
+    int32_t verifyResult = 0;
+
+    /*#1*/
+    status = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM, socketNonBlocking, 0, &g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_getAddressInfo(PAL_TLS_TEST_SERVER_ADDRESS, &socketAddr, &addressLength);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == status) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == status))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration or error)");
+        status = pal_close(&g_socket);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        return;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    tlsSocket.addressLength = addressLength;
+    tlsSocket.socket = g_socket;
+    /*#3*/
+    status = pal_setSockAddrPort(&socketAddr, DTLS_SERVER_PORT);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#4*/
+    status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#5*/
+    status = pal_initTLS(palTLSConf, &palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    // This code commented out to prevent massive prints from mbedTLS, if you want to see logs from client side, just uncomment them.
+    //status = pal_sslSetDebugging(palTLSConf, true);
+    //TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    #if (PAL_ENABLE_X509 == 1)
+        /*#6*/
+        status = pal_setOwnCertAndPrivateKey(palTLSConf, &pubKey, &prvKey);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        /*#7*/
+        status = pal_setCAChain(palTLSConf, &caCert, NULL);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    #elif (PAL_ENABLE_PSK == 1)
+        /*#6 + #7*/
+        status = pal_setPSK(palTLSConf, (const unsigned char*)identity, strlen(identity), (const unsigned char*)psk, sizeof(psk));
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    #endif
+    /*#8*/
+    status = pal_tlsSetSocket(palTLSConf, &tlsSocket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#9*/
+
+	status = pal_setHandShakeTimeOut(palTLSConf, 30000);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#10*/
+
+    do
+    {
+        status = pal_handShake(palTLSHandle, palTLSConf);
+    }
+    while (PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#11*/
+    status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#12*/
+	status = pal_sslWrite(palTLSHandle, g_coapHelloWorldRequest, sizeof(g_coapHelloWorldRequest), &written);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#13*/
+    pal_osDelay(5000);
+    /*#14*/
+    do
+    {
+        status = pal_sslRead(palTLSHandle, serverResponse, PAL_TLS_MESSAGE_SIZE, &actualLen);
+    }while (PAL_ERR_TLS_WANT_READ == status);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#15*/
+    status = pal_freeTLS(&palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#16*/
+    status = pal_tlsConfigurationFree(&palTLSConf);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#17*/
+    status = pal_close(&g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+}
+
+
+static void handshakeTCP(bool socketNonBlocking)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palTLSConfHandle_t palTLSConf = NULLPTR;
+    palTLSHandle_t palTLSHandle = NULLPTR;
+    palTLSTransportMode_t transportationMode =     PAL_TLS_MODE;
+    palSocketAddress_t socketAddr = {0};
+    palSocketLength_t addressLength = 0;
+    char serverResponse[PAL_TLS_MESSAGE_SIZE] = {0};
+    uint32_t actualLen = 0;
+    uint32_t written = 0;
+    #if (PAL_ENABLE_X509 == 1)
+        palX509_t pubKey = {(const void*)g_pubKey,sizeof(g_pubKey)};
+        palPrivateKey_t prvKey = {(const void*)g_prvKey,sizeof(g_prvKey)};
+        palX509_t caCert = { (const void*)pal_test_cas,sizeof(pal_test_cas) };
+    #elif (PAL_ENABLE_PSK == 1)
+        const char* identity = PAL_TEST_PSK_IDENTITY;
+        const char psk[]= PAL_TEST_PSK;
+    #endif
+    palTLSSocket_t tlsSocket = { g_socket, &socketAddr, 0, transportationMode };    
+    uint64_t curTimeInSec, timePassedInSec;
+    const uint64_t minSecSinceEpoch = PAL_MIN_SEC_FROM_EPOCH + 1; //At least 47 years passed from 1.1.1970 in seconds
+    int32_t verifyResult = 0;
+    
+
+    /*#1*/
+    status = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, socketNonBlocking, 0, &g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_getAddressInfo(PAL_TLS_TEST_SERVER_ADDRESS, &socketAddr, &addressLength);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == status) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == status))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration or error)");
+        status = pal_close(&g_socket);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        return;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    tlsSocket.addressLength = addressLength;
+    tlsSocket.socket = g_socket;
+    /*#3*/
+    if (true == socketNonBlocking)
+    {
+        status = pal_setSockAddrPort(&socketAddr, TLS_SERVER_PORT_NB);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    else //blocking
+    {
+        status = pal_setSockAddrPort(&socketAddr, TLS_SERVER_PORT);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+
+    /*#4*/
+    status = pal_connect(g_socket, &socketAddr, addressLength);
+    if (PAL_ERR_SOCKET_IN_PROGRES == status)
+    {
+        pal_osDelay(400);
+    }
+    else
+    {
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#5*/
+    status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    TEST_ASSERT_NOT_EQUAL(palTLSConf, NULLPTR);
+    /*#6*/
+    status = pal_initTLS(palTLSConf, &palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    // This code commented out to prevent massive prints from mbedTLS, if you want to see logs from client side, just uncomment them.
+    //status = pal_sslSetDebugging(palTLSConf, true);
+    //TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    #if (PAL_ENABLE_X509 == 1)
+        /*#7*/    
+        status = pal_setOwnCertAndPrivateKey(palTLSConf, &pubKey, &prvKey);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        /*#8*/
+        status = pal_setCAChain(palTLSConf, &caCert, NULL);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    #elif (PAL_ENABLE_PSK == 1)
+        /*#7 + 8*/
+        status = pal_setPSK(palTLSConf, (const unsigned char*)identity, strlen(identity), (const unsigned char*)psk, sizeof(psk));
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    #endif
+    /*#9*/
+    status = pal_tlsSetSocket(palTLSConf, &tlsSocket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#10*/
+    if (true == socketNonBlocking)
+    {
+        status = pal_osSetTime(minSecSinceEpoch);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); // More than current epoch time -> success
+        do
+        {
+            curTimeInSec = pal_osGetTime();
+            TEST_ASSERT_TRUE(curTimeInSec >= minSecSinceEpoch);        
+            timePassedInSec = curTimeInSec - minSecSinceEpoch;
+            status = pal_handShake(palTLSHandle, palTLSConf);
+        }
+        while ( (PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status) &&
+                (timePassedInSec < PAL_SECONDS_PER_MIN)); //2 minutes to wait for handshake
+    }
+    else //blocking
+    {
+        status = pal_handShake(palTLSHandle, palTLSConf);
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#11*/
+    status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#12*/
+    status = pal_sslWrite(palTLSHandle, TLS_GET_REQUEST, sizeof(TLS_GET_REQUEST), &written);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#13*/
+    pal_osDelay(5000);
+    /*#14*/
+    status = pal_sslRead(palTLSHandle, serverResponse, PAL_TLS_MESSAGE_SIZE, &actualLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#15*/
+    status = pal_freeTLS(&palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#16*/
+    status = pal_tlsConfigurationFree(&palTLSConf);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#17*/
+    status = pal_close(&g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+}
+
+/**
+* @brief Test TLS initialization and uninitialization.
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize TLS configuration using `pal_initTLSConfiguration`.       | PAL_SUCCESS |
+* | 2 | Initialize TLS context using `pal_initTLS`.                          | PAL_SUCCESS |
+* | 3 | Add a NULL entropy source using `pal_addEntropySource`.             | PAL_ERR_INVALID_ARGUMENT |
+* | 4 | Add a valid entropy source using `pal_addEntropySource`.             | PAL_SUCCESS |
+* | 5 | Uninitialize TLS context using `pal_freeTLS`.                        | PAL_SUCCESS |
+* | 6 | Uninitialize TLS configuration using `pal_tlsConfigurationFree`.     | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsInitTLS)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palTLSConfHandle_t palTLSConf = NULLPTR;
+    palTLSHandle_t palTLSHandle = NULLPTR;
+    palTLSTransportMode_t transportationMode =     PAL_TLS_MODE;
+    /*#1*/
+    status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_initTLS(palTLSConf, &palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#ifdef DEBUG
+    /*#3*/
+    status = pal_addEntropySource(NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_INVALID_ARGUMENT, status);
+#endif
+    /*#4*/
+    status = pal_addEntropySource(palTestEntropySource);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#5*/
+    status = pal_freeTLS(&palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#6*/
+    status = pal_tlsConfigurationFree(&palTLSConf);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+}
+
+
+/**
+* @brief Test TLS initialization and uninitialization with additional keys.
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize TLS configuration using `pal_initTLSConfiguration`.       | PAL_SUCCESS |
+* | 2 | Add keys to the configuration using `pal_setOwnCertAndPrivateKey`.           | PAL_SUCCESS |
+* | 3 | Initialize TLS context using `pal_initTLS`.                          | PAL_SUCCESS |
+* | 4 | Uninitialize TLS context using `pal_freeTLS`.                        | PAL_SUCCESS |
+* | 5 | Uninitialize TLS configuration using `pal_tlsConfigurationFree`.     | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsPrivateAndPublicKeys)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    palTLSConfHandle_t palTLSConf = NULLPTR;
+    palTLSHandle_t palTLSHandle = NULLPTR;
+    palTLSTransportMode_t transportationMode = PAL_TLS_MODE;
+    palX509_t pubKey = { (const void*)g_pubKey,sizeof(g_pubKey) };
+    palPrivateKey_t prvKey = { (const void*)g_prvKey,sizeof(g_prvKey) };
+
+    /*#1*/
+    status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+    TEST_ASSERT_NOT_EQUAL(palTLSConf, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_setOwnCertAndPrivateKey(palTLSConf, &pubKey, &prvKey);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#3*/
+    status = pal_initTLS(palTLSConf, &palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#4*/
+    status = pal_freeTLS(&palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#5*/
+    status = pal_tlsConfigurationFree(&palTLSConf);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif
+}
+
+
+/**
+* @brief Test TLS initialization and uninitialization with additional certificate and pre-shared keys.
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize TLS configuration using `pal_initTLSConfiguration`.       | PAL_SUCCESS |
+* | 2 | Set pre-shared keys to the configuration using `pal_setPSK`.         | PAL_SUCCESS |
+* | 3 | Initialize TLS context using `pal_initTLS`.                         | PAL_SUCCESS
+* | 4 | Uninitialize TLS context using `pal_freeTLS`.              			 |PAL_SUCCESS |
+* | 5 | Uninitialize TLS configuration using `pal_tlsConfigurationFree`.     | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsCACertandPSK)
+{
+#if (PAL_ENABLE_PSK == 1)
+    palStatus_t status = PAL_SUCCESS;
+    palTLSConfHandle_t palTLSConf = NULLPTR;
+    palTLSHandle_t palTLSHandle = NULLPTR;
+    palTLSTransportMode_t transportationMode = PAL_TLS_MODE;
+    /*#1*/
+    status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+    TEST_ASSERT_NOT_EQUAL(palTLSConf, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_setPSK(palTLSConf, g_psk_id, sizeof(g_psk_id) - 1, g_psk, sizeof(g_psk));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#3*/
+    status = pal_initTLS(palTLSConf, &palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#4*/
+    status = pal_freeTLS(&palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#5*/
+    status = pal_tlsConfigurationFree(&palTLSConf);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif
+}
+
+
+/**
+* @brief Test TLS handshake (TCP blocking).
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a TCP (blocking) socket.                                        | PAL_SUCCESS |
+* | 2 | Perform a DNS lookup on the server address.                                | PAL_SUCCESS |
+* | 3 | Set the server port.                                                     | PAL_SUCCESS |
+* | 4 | Connect the TCP socket to the server.                                        | PAL_SUCCESS |
+* | 5 | Initialize the TLS configuration using `pal_initTLSConfiguration`.         | PAL_SUCCESS |
+* | 6 | Initialize the TLS context using `pal_initTLS`.                            | PAL_SUCCESS |
+* | 7 | Set the certificate and keys to the configuration using `pal_setOwnCertAndPrivateKey`.| PAL_SUCCESS |
+* | 8 | Set the certificate chain to the configuration using `pal_setCAChain`.        | PAL_SUCCESS |
+* | 9 | Set the socket chain to the configuration using `pal_tlsSetSocket`.           | PAL_SUCCESS |
+* | 10 | Perform a TLS handshake with the server using `pal_handShaket`.           | PAL_SUCCESS |
+* | 11 | Verify the handshake result using `pal_sslGetVerifyResult`.               | PAL_SUCCESS |
+* | 12 | Write data over open TLS connection using `pal_sslWrite`.            | PAL_SUCCESS |
+* | 13 | Wait for the response.                                                  | PAL_SUCCESS |
+* | 14 | Read data from the open TLS connection using `pal_sslRead`.               | PAL_SUCCESS |
+* | 15 | Uninitialize the TLS context using `pal_freeTLS`.                         | PAL_SUCCESS |
+* | 16 | Uninitialize the TLS configuration using `pal_tlsConfigurationFree`.      | PAL_SUCCESS |
+* | 17 | Close the TCP socket.                                                   | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsHandshakeTCP)
+{
+    handshakeTCP(false);
+}
+
+/**
+* @brief Test TLS handshake (TCP non-blocking).
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a TCP (non-blocking) socket.                                    | PAL_SUCCESS |
+* | 2 | Perform a DNS lookup on the server address.                                | PAL_SUCCESS |
+* | 3 | Set the server port.                                                     | PAL_SUCCESS |
+* | 4 | Connect the TCP socket to the server.                                        | PAL_SUCCESS |
+* | 5 | Initialize the TLS configuration using `pal_initTLSConfiguration`.         | PAL_SUCCESS |
+* | 6 | Initialize the TLS context using `pal_initTLS`.                            | PAL_SUCCESS |
+* | 7 | Set the certificate and keys to the configuration using `pal_setOwnCertAndPrivateKey`.| PAL_SUCCESS |
+* | 8 | Set the certificate chain to the configuration using `pal_setCAChain`.        | PAL_SUCCESS |
+* | 9 | Set the socket chain to the configuration using `pal_tlsSetSocket`.           | PAL_SUCCESS |
+* | 10 | Perform a TLS handshake with the server using `pal_handShaket` in a loop. | PAL_SUCCESS |
+* | 11 | Verify the handshake result using `pal_sslGetVerifyResult`.               | PAL_SUCCESS |
+* | 12 | Write data over the open TLS connection using `pal_sslWrite`.            | PAL_SUCCESS |
+* | 13 | Wait for the response.                                                  | PAL_SUCCESS |
+* | 14 | Read data from the open TLS connection using `pal_sslRead`.               | PAL_SUCCESS |
+* | 15 | Uninitialize the TLS context using `pal_freeTLS`.                         | PAL_SUCCESS |
+* | 16 | Uninitialize the TLS configuration using `pal_tlsConfigurationFree`.      | PAL_SUCCESS |
+* | 17 | Close the TCP socket.                                                   | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsHandshakeTCP_nonBlocking)
+{
+    handshakeTCP(true);
+}
+
+/**
+* @brief Test (D)TLS handshake (UDP -blocking).
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a UDP (blocking) socket.                                        | PAL_SUCCESS |
+* | 2 | Perform a DNS lookup on the server address.                                | PAL_SUCCESS |
+* | 3 | Set the server port.                                                     | PAL_SUCCESS |
+* | 4 | Initialize the TLS configuration using `pal_initTLSConfiguration`.         | PAL_SUCCESS |
+* | 5 | Initialize the TLS context using `pal_initTLS`.                            | PAL_SUCCESS |
+* | 6 | Set the certificate and keys to the configuration using `pal_setOwnCertAndPrivateKey`.| PAL_SUCCESS |
+* | 7 | Set the certificate chain to the configuration using `pal_setCAChain`.        | PAL_SUCCESS |
+* | 8 | Set the socket chain to the configuration using `pal_tlsSetSocket`.           | PAL_SUCCESS |
+* | 9 | Set the timeout for the handshake using `pal_setHandShakeTimeOut`.         | PAL_SUCCESS |
+* | 10 | Perform a TLS handshake with the server using `pal_handShaket` in a loop. | PAL_SUCCESS |
+* | 11 | Verify the handshake result using `pal_sslGetVerifyResult`.               | PAL_SUCCESS |
+* | 12 | Write data over the open TLS connection using `pal_sslWrite`.            | PAL_SUCCESS |
+* | 13 | Wait for the response.                                                  | PAL_SUCCESS |
+* | 14 | Read data from the open TLS connection using `pal_sslRead`.               | PAL_SUCCESS |
+* | 15 | Uninitialize the TLS context using `pal_freeTLS`.                         | PAL_SUCCESS |
+* | 16 | Uninitialize the TLS configuration using `pal_tlsConfigurationFree`.      | PAL_SUCCESS |
+* | 17 | Close the UDP socket.                                                   | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsHandshakeUDP)
+{
+    handshakeUDP(false);
+}
+
+/**
+* @brief Test (D)TLS handshake (UDP -NonBlocking).
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a UDP (blocking) socket.                                        | PAL_SUCCESS |
+* | 2 | Perform a DNS lookup on the server address.                                | PAL_SUCCESS |
+* | 3 | Set the server port.                                                     | PAL_SUCCESS |
+* | 4 | Initialize the TLS configuration using `pal_initTLSConfiguration`.         | PAL_SUCCESS |
+* | 5 | Initialize the TLS context using `pal_initTLS`.                            | PAL_SUCCESS |
+* | 6 | Set the certificate and keys to the configuration using `pal_setOwnCertAndPrivateKey`.| PAL_SUCCESS |
+* | 7 | Set the certificate chain to the configuration using `pal_setCAChain`.        | PAL_SUCCESS |
+* | 8 | Set the socket chain to the configuration using `pal_tlsSetSocket`.           | PAL_SUCCESS |
+* | 9 | Set the timeout for the handshake using `pal_setHandShakeTimeOut`.         | PAL_SUCCESS |
+* | 10 | Perform a TLS handshake with the server using `pal_handShaket` in a loop. | PAL_SUCCESS |
+* | 11 | Verify the handshake result using `pal_sslGetVerifyResult`.               | PAL_SUCCESS |
+* | 12 | Write data over the open TLS connection using `pal_sslWrite`.            | PAL_SUCCESS |
+* | 13 | Wait for the response.                                                  | PAL_SUCCESS |
+* | 14 | Read data from the open TLS connection using `pal_sslRead`.               | PAL_SUCCESS |
+* | 15 | Uninitialize the TLS context using `pal_freeTLS`.                         | PAL_SUCCESS |
+* | 16 | Uninitialize the TLS configuration using `pal_tlsConfigurationFree`.      | PAL_SUCCESS |
+* | 17 | Close the UDP socket.                                                   | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsHandshakeUDP_NonBlocking)
+{
+    handshakeUDP(true);
+}
+
+/**
+* @brief Test (D)TLS handshake (UDP non-blocking) with a very short timeout to see if you get a timeout.
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a UDP (blocking) socket.                                        | PAL_SUCCESS |
+* | 2 | Perform a DNS lookup on server adderss.                                | PAL_SUCCESS |
+* | 3 | Set the server port.                                                     | PAL_SUCCESS |
+* | 4 | Initialize the TLS configuration using `pal_initTLSConfiguration`.         | PAL_SUCCESS |
+* | 5 | Initialize the TLS context using `pal_initTLS`.                            | PAL_SUCCESS |
+* | 6 | Set the certificate and keys to the configuration using `pal_setOwnCertAndPrivateKey`.| PAL_SUCCESS |
+* | 7 | Set the certificate chain to the configuration using `pal_setCAChain`.        | PAL_SUCCESS |
+* | 8 | Set the socket chain to the configuration using `pal_tlsSetSocket`.           | PAL_SUCCESS |
+* | 9 | Set a short timeout for the handshake using `pal_setHandShakeTimeOut`.   | PAL_SUCCESS |
+* | 10 | Perform a TLS handshake with the server using `pal_handShaket` in a loop. | PAL_ERR_TIMEOUT_EXPIRED |
+* | 11 | Uninitialize the TLS context using `pal_freeTLS`.                         | PAL_SUCCESS |
+* | 12 | Uninitialize the TLS configuration using `pal_tlsConfigurationFree`.      | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsHandshakeUDPTimeOut)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palTLSConfHandle_t palTLSConf = NULLPTR;
+    palTLSHandle_t palTLSHandle = NULLPTR;
+    palTLSTransportMode_t transportationMode = PAL_DTLS_MODE;
+    palSocketAddress_t socketAddr = { 0 };
+    palSocketLength_t addressLength = 0;
+    #if (PAL_ENABLE_X509 == 1)
+        palX509_t pubKey = { (const void*)g_pubKey,sizeof(g_pubKey) };
+        palPrivateKey_t prvKey = { (const void*)g_prvKey,sizeof(g_prvKey) };
+        palX509_t caCert = { (const void*)pal_test_cas,sizeof(pal_test_cas) };
+    #elif (PAL_ENABLE_PSK == 1)
+        const char* identity = PAL_TEST_PSK_IDENTITY;
+        const char psk[]= PAL_TEST_PSK;
+    #endif 
+    palTLSSocket_t tlsSocket = { g_socket, &socketAddr, 0, transportationMode };
+    
+    uint64_t curTimeInSec;
+    const uint64_t minSecSinceEpoch = PAL_MIN_SEC_FROM_EPOCH + 1; //At least 47 years passed from 1.1.1970 in seconds      
+    
+    /*#1*/
+    status = pal_socket(PAL_AF_INET, PAL_SOCK_DGRAM, false, 0, &g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_getAddressInfo(PAL_TLS_TEST_SERVER_ADDRESS, &socketAddr, &addressLength);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == status) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == status))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration or error)");
+        status = pal_close(&g_socket);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        return;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    tlsSocket.addressLength = addressLength;
+    tlsSocket.socket = g_socket;
+    /*#3*/
+    status = pal_setSockAddrPort(&socketAddr, DTLS_SERVER_PORT_TIMEOUT);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#4*/
+    status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#5*/
+    status = pal_initTLS(palTLSConf, &palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    // This code commented out to prevent massive prints from mbedTLS, if you want to see logs from client side, just uncomment them.
+    //status = pal_sslSetDebugging(palTLSConf, true);
+    //TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    #if (PAL_ENABLE_X509 == 1)
+        /*#6*/
+        status = pal_setOwnCertAndPrivateKey(palTLSConf, &pubKey, &prvKey);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        /*#7*/
+        status = pal_setCAChain(palTLSConf, &caCert, NULL);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    #elif (PAL_ENABLE_PSK == 1)
+        /*#6 + #7*/
+        status = pal_setPSK(palTLSConf, (const unsigned char*)identity, strlen(identity), (const unsigned char*)psk, sizeof(psk));
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    #endif
+    /*#8*/
+    status = pal_tlsSetSocket(palTLSConf, &tlsSocket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#9*/
+    status = pal_setHandShakeTimeOut(palTLSConf, 100);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osSetTime(minSecSinceEpoch);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); // More than current epoch time -> success    
+    /*#10*/
+    do
+    {
+        status = pal_handShake(palTLSHandle, palTLSConf);
+    }
+    while (PAL_ERR_TLS_WANT_READ == status || PAL_ERR_TLS_WANT_WRITE == status);
+
+    curTimeInSec = pal_osGetTime();
+    TEST_ASSERT_EQUAL_HEX(PAL_ERR_TIMEOUT_EXPIRED, status);
+    TEST_ASSERT_TRUE(curTimeInSec - minSecSinceEpoch <= PAL_WAIT_TIME); //less than PAL_WAIT_TIME seconds
+    /*#11*/
+    status = pal_freeTLS(&palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#12*/
+    status = pal_tlsConfigurationFree(&palTLSConf);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    status = pal_close(&g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+}
+
+#if PAL_USE_INTERNAL_FLASH
+/**
+* @brief Test TLS handshake (TCP blocking).
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a TCP (blocking) socket.                                          | PAL_SUCCESS |
+* | 2 | Perform a DNS lookup on the server address.                              | PAL_SUCCESS |
+* | 3 | Set the server port.                                                     | PAL_SUCCESS |
+* | 4 | Connect the TCP socket to the server.                                        | PAL_SUCCESS |
+* | 5 | Initialize the TLS configuration using `pal_initTLSConfiguration`.         | PAL_SUCCESS |
+* | 6 | Initialize the TLS context using `pal_initTLS`.                            | PAL_SUCCESS |
+* | 7 | Set the certificate and keys to the configuration using `pal_setOwnCertAndPrivateKey`.| PAL_SUCCESS |
+* | 8 | Set the certificate chain to the configuration using `pal_setCAChain`.        | PAL_SUCCESS |
+* | 9 | Set the socket chain to the configuration using `pal_tlsSetSocket`.           | PAL_SUCCESS |
+* | 10 | Set device time to be in future.                                          | PAL_SUCCESS |
+* | 11 | Perform a TLS handshake with the server using `pal_handShaket`.           | PAL_SUCCESS |
+* | 12 | Verify the handshake result using `pal_sslGetVerifyResult`.               | PAL_SUCCESS |
+* | 13 | Write data over open TLS connection using `pal_sslWrite`.            | PAL_SUCCESS |
+* | 14 | Uninitialize the TLS context using `pal_freeTLS`.                         | PAL_SUCCESS |
+* | 15 | Uninitialize the TLS configuration using `pal_tlsConfigurationFree`.      | PAL_SUCCESS |
+* | 16 | Close the TCP socket.                                                   | PAL_SUCCESS |
+* | 17 | Check that time is updated.                                               | PAL_SUCCESS |
+* | 18 | Verify that the SOTP time value was updated.                          | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsHandshakeTCP_FutureLWM2M)
+{
+    #if ((PAL_USE_SECURE_TIME == 1) && (PAL_USE_INTERNAL_FLASH == 1))
+    palStatus_t status = PAL_SUCCESS;
+    palTLSConfHandle_t palTLSConf = NULLPTR;
+    palTLSHandle_t palTLSHandle = NULLPTR;
+    palTLSTransportMode_t transportationMode =     PAL_TLS_MODE;
+    palSocketAddress_t socketAddr = {0};
+    palSocketLength_t addressLength = 0;
+    uint32_t written = 0;
+    palX509_t pubKey = {(const void*)g_pubKey,sizeof(g_pubKey)};
+    palPrivateKey_t prvKey = {(const void*)g_prvKey,sizeof(g_prvKey)};
+    palX509_t caCert = { (const void*)pal_test_cas,sizeof(pal_test_cas) };
+    palTLSSocket_t tlsSocket = { g_socket, &socketAddr, 0, transportationMode };
+    
+    char serverResponse[PAL_TLS_MESSAGE_SIZE] = {0};
+    uint32_t actualLen = 0;
+    uint64_t deviceTime = pal_osGetTime(); //get device time to update it in case of failure
+	uint64_t currentTime = 0;
+    uint16_t actualSavedTimeSize = 0;
+    uint64_t initialSOTPTime = 0;
+    sotp_result_e sotpRes = SOTP_SUCCESS;
+    int32_t verifyResult = 0;
+
+
+    /*#1*/
+    status = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+
+    /*#2*/
+    status = pal_getAddressInfo(PAL_TLS_TEST_SERVER_ADDRESS, &socketAddr, &addressLength);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == status) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == status))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration or error)");
+        status = pal_close(&g_socket);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        return;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    tlsSocket.addressLength = addressLength;
+    tlsSocket.socket = g_socket;
+    /*#3*/
+    status = pal_setSockAddrPort(&socketAddr, TLS_RENEGOTIATE_SERVER_PORT);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#4*/
+    status = pal_connect(g_socket, &socketAddr, addressLength);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#5*/
+    status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#6*/
+    status = pal_initTLS(palTLSConf, &palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#7*/
+    status = pal_setOwnCertAndPrivateKey(palTLSConf, &pubKey, &prvKey);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#8*/
+    status = pal_setCAChain(palTLSConf, &caCert, NULL);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status); 
+    /*#9*/
+    status = pal_tlsSetSocket(palTLSConf, &tlsSocket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#10*/
+
+    sotpRes = sotp_set(SOTP_TYPE_SAVED_TIME, (uint16_t)sizeof(initialSOTPTime), (uint32_t*)&initialSOTPTime);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+    status = pal_osSetTime(0);//back in the past to set time to the future during handhsake
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#11*/
+    status = pal_handShake(palTLSHandle, palTLSConf);
+    if (PAL_SUCCESS != status)
+    {
+        pal_osSetTime(deviceTime);
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#12*/
+    status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#13*/
+    status = pal_sslWrite(palTLSHandle, TLS_GET_REQUEST, sizeof(TLS_GET_REQUEST), &written);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    pal_osDelay(5000);
+    /*#14*/
+    status = pal_sslRead(palTLSHandle, serverResponse, PAL_TLS_MESSAGE_SIZE, &actualLen);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#14*/
+    status = pal_freeTLS(&palTLSHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#15*/
+    status = pal_tlsConfigurationFree(&palTLSConf);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#16*/
+    status = pal_close(&g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#17*/
+    deviceTime = pal_osGetTime();
+    TEST_ASSERT_TRUE(0 != deviceTime);
+    /*#18*/
+    sotpRes = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(currentTime), (uint32_t*)&currentTime, &actualSavedTimeSize);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+    TEST_ASSERT_TRUE(0 != currentTime);
+    #endif 
+}
+
+/**
+* @brief Test TLS handshake (TCP blocking) with near future time and validate that the handshake didn't update the device time (due to set time rules)
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Get saved time from SOTP, move backward half day and set time to RAM    | PAL_SUCCESS |
+* | 2 | Update `SOTP_TYPE_SAVED_TIME` directly in SOTP to the new time from #1  | PAL_SUCCESS |
+* | 3 | Create a TCP (blocking) socket.                                         | PAL_SUCCESS |
+* | 4 | Perform a DNS lookup on the server address.                             | PAL_SUCCESS |
+* | 5 | Set the server port.                                                    | PAL_SUCCESS |
+* | 6 | Connect the TCP socket to the server.                                        | PAL_SUCCESS |
+* | 7 | Initialize the TLS configuration using `pal_initTLSConfiguration`.         | PAL_SUCCESS |
+* | 8 | Initialize the TLS context using `pal_initTLS`.                            | PAL_SUCCESS |
+* | 9 | Set the certificate and keys to the configuration using `pal_setOwnCertAndPrivateKey`.| PAL_SUCCESS |
+* | 10 | Set the certificate chain to the configuration using `pal_setCAChain`.        | PAL_SUCCESS |
+* | 11 | Set the socket to the configuration using `pal_tlsSetSocket`.           | PAL_SUCCESS |
+* | 12 | Perform a TLS handshake with the server using `pal_handShake`.           | PAL_SUCCESS |
+* | 13 | Verify the handshake result using `pal_sslGetVerifyResult`.               | PAL_SUCCESS |
+* | 14 | Write data over open TLS connection using `pal_sslWrite`.            | PAL_SUCCESS |
+* | 15 | Uninitialize the TLS context using `pal_freeTLS`.                         | PAL_SUCCESS |
+* | 16 | Uninitialize the TLS configuration using `pal_tlsConfigurationFree`.      | PAL_SUCCESS |
+* | 17 | Verify that the time was NOT updated during the handshake.                        | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsHandshakeTCP_FutureLWM2M_NoTimeUpdate)
+{
+    #if ((PAL_USE_SECURE_TIME == 1) && (PAL_USE_INTERNAL_FLASH == 1))
+    palStatus_t status = PAL_SUCCESS;
+    palTLSConfHandle_t palTLSConf = NULLPTR;
+    palTLSHandle_t palTLSHandle = NULLPTR;
+    palTLSTransportMode_t transportationMode = PAL_TLS_MODE;
+    palSocketAddress_t socketAddr = { 0 };
+    palSocketLength_t addressLength = 0;
+    uint32_t written = 0;
+    char serverResponse[PAL_TLS_MESSAGE_SIZE] = {0};
+    uint32_t actualLen = 0;
+    palX509_t pubKey = { (const void*)g_pubKey,sizeof(g_pubKey) };
+    palPrivateKey_t prvKey = { (const void*)g_prvKey,sizeof(g_prvKey) };
+    palTLSSocket_t tlsSocket = { g_socket, &socketAddr, 0, transportationMode };
+    palX509_t caCert = { (const void*)pal_test_cas,sizeof(pal_test_cas) };
+    sotp_result_e sotpRes = SOTP_SUCCESS;
+    uint64_t currentTime = 0;
+    uint64_t tmpTime = 0;
+    uint64_t updatedTime = 0;
+    uint16_t actualSavedTimeSize = 0;
+    int32_t verifyResult = 0;
+
+    /*#1*/
+    sotpRes = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(tmpTime), (uint32_t*)&tmpTime, &actualSavedTimeSize);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+
+    currentTime = tmpTime - (PAL_SECONDS_PER_DAY / 2); //going back half day to simulate future server by half day (in order to prevent time update)
+    status = pal_osSetTime(currentTime);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    sotpRes = sotp_set(SOTP_TYPE_SAVED_TIME, (uint16_t)sizeof(currentTime), (uint32_t*)&currentTime);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+
+	/*#3*/
+	status = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_socket);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	/*#4*/
+	status = pal_getAddressInfo(PAL_TLS_TEST_SERVER_ADDRESS, &socketAddr, &addressLength);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == status) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == status))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration or error)");
+        status = pal_close(&g_socket);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        return;
+    }
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#5*/
+    status = pal_setSockAddrPort(&socketAddr, TLS_RENEGOTIATE_SERVER_PORT);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	tlsSocket.addressLength = addressLength;
+	tlsSocket.socket = g_socket;
+    
+	/*#6*/
+	status = pal_connect(g_socket, &socketAddr, addressLength);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	/*#7*/
+	status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	/*#8*/
+	status = pal_initTLS(palTLSConf, &palTLSHandle);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+
+	/*#9*/
+	status = pal_setOwnCertAndPrivateKey(palTLSConf, &pubKey, &prvKey);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#10*/
+	status = pal_setCAChain(palTLSConf, &caCert, NULL);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#11*/
+	status = pal_tlsSetSocket(palTLSConf, &tlsSocket);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#12*/
+	status = pal_handShake(palTLSHandle, palTLSConf);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#13*/
+	status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		TEST_ASSERT_TRUE(PAL_ERR_X509_BADCERT_EXPIRED & verifyResult);
+	}
+    /*#14*/
+    status = pal_sslWrite(palTLSHandle, TLS_GET_REQUEST, sizeof(TLS_GET_REQUEST), &written);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+
+    pal_osDelay(5000);
+    /*#14*/
+    status = pal_sslRead(palTLSHandle, serverResponse, PAL_TLS_MESSAGE_SIZE, &actualLen);
+    if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+
+	/*#15*/
+	status = pal_freeTLS(&palTLSHandle);
+	if (PAL_SUCCESS != status)
+	{
+		pal_tlsConfigurationFree(&palTLSConf);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#16*/
+	status = pal_tlsConfigurationFree(&palTLSConf);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_close(&g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	/*#17*/ 
+    sotpRes = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(updatedTime), (uint32_t*)&updatedTime, &actualSavedTimeSize);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+    TEST_ASSERT_EQUAL_HEX(currentTime, updatedTime);
+    #endif
+}
+
+
+/**
+* @brief Test TLS handshake (TCP blocking) with future time to make handshake to fail due to bad cert time from server.
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a TCP (blocking) socket.                                        | PAL_SUCCESS |
+* | 2 | Perform a DNS lookup on the server address.                                | PAL_SUCCESS |
+* | 3 | Set the server port.                                                     | PAL_SUCCESS |
+* | 4 | Connect the TCP socket to the server.                                        | PAL_SUCCESS |
+* | 5 | Initialize the TLS configuration using `pal_initTLSConfiguration`.         | PAL_SUCCESS |
+* | 6 | Initialize the TLS context using `pal_initTLS`.                            | PAL_SUCCESS |
+* | 7 | Set the certificate and keys to the configuration using `pal_setOwnCertAndPrivateKey`.| PAL_SUCCESS |
+* | 8 | Set the certificate chain to the configuration using `pal_setCAChain`.        | PAL_SUCCESS |
+* | 9 | Set the socket chain to the configuration using `pal_tlsSetSocket`.           | PAL_SUCCESS |
+* | 10 | Setsystem time to be far in the future `pal_osSetTime`.                   | PAL_SUCCESS |
+* | 11 | Perform a TLS handshake with the server using `pal_handShake`.           | PAL_ERR_X509_CERT_VERIFY_FAILED |
+* | 12 | Verify the handshake result using `pal_sslGetVerifyResult`.               | PAL_ERR_X509_BADCERT_EXPIRED |
+* | 13 | Set tme back to the original time before the test.                        | PAL_SUCCESS |
+* | 14 | Uninitialize the TLS context using `pal_freeTLS`.                         | PAL_SUCCESS |
+* | 15 | Uninitialize the TLS configuration using `pal_tlsConfigurationFree`.      | PAL_SUCCESS |
+* | 16 | Verify that the SOTP time value was not changed.                          | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsHandshakeTCP_ExpiredLWM2MCert)
+{
+    #if ((PAL_USE_SECURE_TIME == 1) && (PAL_USE_INTERNAL_FLASH == 1))
+    palStatus_t status = PAL_SUCCESS;
+    palTLSConfHandle_t palTLSConf = NULLPTR;
+    palTLSHandle_t palTLSHandle = NULLPTR;
+    palTLSTransportMode_t transportationMode = PAL_TLS_MODE;
+    palSocketAddress_t socketAddr = {0};
+    palSocketLength_t addressLength = 0;
+    palX509_t pubKey = {(const void*)g_pubKey,sizeof(g_pubKey)};
+    palPrivateKey_t prvKey = {(const void*)g_prvKey,sizeof(g_prvKey)};
+    palTLSSocket_t tlsSocket = { g_socket, &socketAddr, 0, transportationMode };
+    palX509_t caCert = { (const void*)pal_test_cas,sizeof(pal_test_cas) };
+    uint64_t futureTime = 2145542642; //Wed, 27 Dec 2037 16:04:02 GMT
+    uint64_t currentTime = 0;
+    uint64_t currentSOTPTime = 0;
+    uint16_t actualSavedTimeSize = 0;
+	sotp_result_e sotpRes = SOTP_SUCCESS;
+    int32_t verifyResult = 0;
+
+
+    /*#1*/
+    status = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_getAddressInfo(PAL_TLS_TEST_SERVER_ADDRESS, &socketAddr, &addressLength);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == status) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == status))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration or error)");
+        status = pal_close(&g_socket);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        return;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    tlsSocket.addressLength = addressLength;
+    tlsSocket.socket = g_socket;
+    /*#3*/
+    status = pal_setSockAddrPort(&socketAddr, TLS_RENEGOTIATE_SERVER_PORT);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#4*/
+    status = pal_connect(g_socket, &socketAddr, addressLength);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#5*/
+    status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#6*/
+    status = pal_initTLS(palTLSConf, &palTLSHandle);
+    if (PAL_SUCCESS != status)
+    {
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    
+    /*#7*/
+    status = pal_setOwnCertAndPrivateKey(palTLSConf, &pubKey, &prvKey);
+    if (PAL_SUCCESS != status)
+    {
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#8*/
+    status = pal_setCAChain(palTLSConf, &caCert, NULL);
+    if (PAL_SUCCESS != status)
+    {
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#9*/
+    status = pal_tlsSetSocket(palTLSConf, &tlsSocket);
+    if (PAL_SUCCESS != status)
+    {
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#10*/
+    sotpRes = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(currentTime), (uint32_t*)&currentTime, &actualSavedTimeSize);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+    status = pal_osSetTime(futureTime);
+    if (PAL_SUCCESS != status)
+    {
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#11*/
+    status = pal_handShake(palTLSHandle, palTLSConf);
+    if (PAL_ERR_X509_CERT_VERIFY_FAILED != status)
+    {
+        pal_osSetTime(currentTime);
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        TEST_ASSERT_EQUAL_HEX(PAL_ERR_X509_CERT_VERIFY_FAILED, status);
+    }
+    /*#12*/
+    status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult);
+    if ((PAL_ERR_X509_CERT_VERIFY_FAILED != status) || (0 == (PAL_ERR_X509_BADCERT_EXPIRED & verifyResult)))
+    {
+        pal_osSetTime(currentTime);
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        TEST_ASSERT_TRUE(PAL_ERR_X509_BADCERT_EXPIRED & verifyResult);
+    }
+    /*#13*/
+    status = pal_osSetTime(currentTime);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#14*/
+    status = pal_freeTLS(&palTLSHandle);
+    if (PAL_SUCCESS != status)
+    {
+        pal_tlsConfigurationFree(&palTLSConf);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#15*/
+    status = pal_tlsConfigurationFree(&palTLSConf);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_close(&g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    /*#16*/
+    sotpRes = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(currentSOTPTime), (uint32_t*)&currentSOTPTime, &actualSavedTimeSize);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+	TEST_ASSERT_TRUE(futureTime <= currentSOTPTime);
+    #endif 
+}
+
+/**
+* @brief Test TLS handshake (TCP blocking) with future time to make handshake update the device time according to the server time.
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create a TCP (blocking) socket.                                        | PAL_SUCCESS |
+* | 2 | Perform a DNS lookup on the server address.                                | PAL_SUCCESS |
+* | 3 | Set the server port.                                                     | PAL_SUCCESS |
+* | 4 | Parse the CA cert.                                                     | PAL_SUCCESS |
+* | 5 | Get the CA cert ID.                                                     | PAL_SUCCESS |
+* | 6 | Set the CA cert ID into the SOTP.                                            | PAL_SUCCESS |
+* | 7 | Connect the TCP socket to the server.                                        | PAL_SUCCESS |
+* | 8 | Initialize the TLS configuration using `pal_initTLSConfiguration`.         | PAL_SUCCESS |
+* | 9 | Initialize the TLS context using `pal_initTLS`.                            | PAL_SUCCESS |
+* | 10 | Set the certificate and keys to the configuration using `pal_setOwnCertAndPrivateKey`.| PAL_SUCCESS |
+* | 11 | Set the certificate chain to the configuration using `pal_setCAChain`.        | PAL_SUCCESS |
+* | 12 | Set the socket to the configuration using `pal_tlsSetSocket`.           | PAL_SUCCESS |
+* | 13 | Set system time to be far in the future `pal_osSetTime`.                   | PAL_SUCCESS |
+* | 14 | Perform a TLS handshake with the server using `pal_handShake`.           | PAL_SUCCESS |
+* | 15 | Verify the handshake result using `pal_sslGetVerifyResult`.               | PAL_SUCCESS |
+* | 16 | Write data over open TLS connection using `pal_sslWrite`.            | PAL_SUCCESS |
+* | 17 | Uninitialize the TLS context using `pal_freeTLS`.                         | PAL_SUCCESS |
+* | 18 | Uninitialize the TLS configuration using `pal_tlsConfigurationFree`.      | PAL_SUCCESS |
+* | 19 | Free X509 handle.                                                   | PAL_SUCCESS |
+* | 20 | Verify that the time updated during the handshake.                        | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsHandshakeTCP_ExpiredServerCert_Trusted)
+{
+    #if ((PAL_USE_SECURE_TIME == 1) && (PAL_USE_INTERNAL_FLASH == 1))
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConfHandle_t palTLSConf = NULLPTR;
+	palTLSHandle_t palTLSHandle = NULLPTR;
+	palTLSTransportMode_t transportationMode = PAL_TLS_MODE;
+	palSocketAddress_t socketAddr = { 0 };
+	palSocketLength_t addressLength = 0;
+    char serverResponse[PAL_TLS_MESSAGE_SIZE] = {0};
+    uint32_t actualLen = 0;
+    uint32_t written = 0;
+	palX509_t pubKey = { (const void*)g_pubKey,sizeof(g_pubKey) };
+	palPrivateKey_t prvKey = { (const void*)g_prvKey,sizeof(g_prvKey) };
+	palTLSSocket_t tlsSocket = { g_socket, &socketAddr, 0, transportationMode };
+	palX509_t caCert = { (const void*)pal_test_cas,sizeof(pal_test_cas) };
+	uint64_t futureTime = 2145542642; //Wed, 27 Dec 2037 16:04:02 GMT
+    uint64_t updatedTime = 0;
+    uint16_t actualSavedTimeSize = 0;
+	palX509Handle_t trustedServerCA = NULLPTR;
+    sotp_result_e sotpRes = SOTP_SUCCESS;
+    int32_t verifyResult = 0;
+
+	/*#1*/
+	status = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_socket);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	/*#2*/
+	status = pal_getAddressInfo(PAL_TLS_TEST_SERVER_ADDRESS, &socketAddr, &addressLength);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == status) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == status))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration or error)");
+        status = pal_close(&g_socket);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        return;
+    }
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#3*/
+    status = pal_setSockAddrPort(&socketAddr, TLS_RENEGOTIATE_SERVER_PORT);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    
+	tlsSocket.addressLength = addressLength;
+	tlsSocket.socket = g_socket;
+    /*#4*/
+	status = pal_x509Initiate(&trustedServerCA);
+	TEST_ASSERT_NOT_EQUAL(trustedServerCA, NULLPTR);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_x509CertParse(trustedServerCA, (const unsigned char *)pal_test_cas, sizeof(pal_test_cas));
+    if (PAL_SUCCESS != status)
+	{
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+    /*#5*/
+	status = pal_x509CertGetAttribute(trustedServerCA, PAL_X509_CERT_ID_ATTR, g_trustedServerID, sizeof(g_trustedServerID), &g_actualServerIDSize);
+    if (PAL_SUCCESS != status)
+	{
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+    /*#6*/
+    sotpRes = sotp_set(SOTP_TYPE_TRUSTED_TIME_SRV_ID, g_actualServerIDSize, (uint32_t*)g_trustedServerID);
+    if (SOTP_SUCCESS != sotpRes)
+	{
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+	}
+
+	/*#7*/
+	status = pal_connect(g_socket, &socketAddr, addressLength);
+	if (PAL_SUCCESS != status)
+	{
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#8*/
+	status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	/*#9*/
+	status = pal_initTLS(palTLSConf, &palTLSHandle);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+
+	/*#10*/
+	status = pal_setOwnCertAndPrivateKey(palTLSConf, &pubKey, &prvKey);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#11*/
+	status = pal_setCAChain(palTLSConf, &caCert, NULL);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#12*/
+	status = pal_tlsSetSocket(palTLSConf, &tlsSocket);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#13*/
+	status = pal_osSetStrongTime(futureTime);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#14*/
+	status = pal_handShake(palTLSHandle, palTLSConf);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#15*/
+	status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_TRUE(PAL_ERR_X509_BADCERT_EXPIRED & verifyResult);
+	}
+    /*#16*/
+    status = pal_sslWrite(palTLSHandle, TLS_GET_REQUEST, sizeof(TLS_GET_REQUEST), &written);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_ERR_X509_BADCERT_EXPIRED, status);
+	}
+
+    pal_osDelay(5000);
+    /*#14*/
+    status = pal_sslRead(palTLSHandle, serverResponse, PAL_TLS_MESSAGE_SIZE, &actualLen);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_ERR_X509_BADCERT_EXPIRED, status);
+	}
+
+	/*#17*/
+	status = pal_freeTLS(&palTLSHandle);
+	if (PAL_SUCCESS != status)
+	{
+        pal_x509Free(&trustedServerCA);
+		pal_tlsConfigurationFree(&palTLSConf);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#18*/
+	status = pal_tlsConfigurationFree(&palTLSConf);
+	if (PAL_SUCCESS != status)
+	{
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#19*/
+	status = pal_x509Free(&trustedServerCA);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	/*#20*/
+    updatedTime = pal_osGetTime();
+    TEST_ASSERT_TRUE(updatedTime < futureTime);
+
+    status = pal_close(&g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    
+    sotpRes = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(updatedTime), (uint32_t*)&updatedTime, &actualSavedTimeSize);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+    TEST_ASSERT_TRUE(updatedTime <= futureTime);
+
+    sotpRes = sotp_get(SOTP_TYPE_LAST_TIME_BACK, sizeof(updatedTime), (uint32_t*)&updatedTime, &actualSavedTimeSize);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+    TEST_ASSERT_TRUE(updatedTime <= futureTime);
+    #endif 
+}
+
+/**
+* @brief Test TLS handshake (TCP blocking) with near future time and validate that the handshake didn't update the device time (due to set time rules)
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Get saved time from SOTP, move backward half day and set time to RAM    | PAL_SUCCESS |
+* | 2 | Create a TCP (blocking) socket.                                        | PAL_SUCCESS |
+* | 3 | Perform a DNS lookup on the server address.                                | PAL_SUCCESS |
+* | 4 | Set the server port.                                                     | PAL_SUCCESS |
+* | 5 | Parse the CA cert.                                                     | PAL_SUCCESS |
+* | 6 | Get the CA cert ID.                                                     | PAL_SUCCESS |
+* | 7 | Set the CA cert ID into the SOTP.                                            | PAL_SUCCESS |
+* | 8 | Connect the TCP socket to the server.                                        | PAL_SUCCESS |
+* | 9 | Initialize the TLS configuration using `pal_initTLSConfiguration`.         | PAL_SUCCESS |
+* | 10 | Initialize the TLS context using `pal_initTLS`.                            | PAL_SUCCESS |
+* | 11 | Set the certificate and keys to the configuration using `pal_setOwnCertAndPrivateKey`.| PAL_SUCCESS |
+* | 12 | Set the certificate chain to the configuration using `pal_setCAChain`.        | PAL_SUCCESS |
+* | 13 | Set the socket to the configuration using `pal_tlsSetSocket`.           | PAL_SUCCESS |
+* | 14 | Perform a TLS handshake with the server using `pal_handShake`.           | PAL_SUCCESS |
+* | 15 | Verify the handshake result using `pal_sslGetVerifyResult`.               | PAL_SUCCESS |
+* | 16 | Write data over open TLS connection using `pal_sslWrite`.            | PAL_SUCCESS |
+* | 17 | Uninitialize the TLS context using `pal_freeTLS`.                         | PAL_SUCCESS |
+* | 18 | Uninitialize the TLS configuration using `pal_tlsConfigurationFree`.      | PAL_SUCCESS |
+* | 19 | Free X509 Handle.                                                   | PAL_SUCCESS |
+* | 20 | Verify that the time was NOT updated during the handshake.                | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsHandshakeTCP_FutureTrustedServer_NoTimeUpdate)
+{
+    #if ((PAL_USE_SECURE_TIME == 1) && (PAL_USE_INTERNAL_FLASH == 1))
+	palStatus_t status = PAL_SUCCESS;
+	palTLSConfHandle_t palTLSConf = NULLPTR;
+	palTLSHandle_t palTLSHandle = NULLPTR;
+	palTLSTransportMode_t transportationMode = PAL_TLS_MODE;
+	palSocketAddress_t socketAddr = { 0 };
+	palSocketLength_t addressLength = 0;
+    char serverResponse[PAL_TLS_MESSAGE_SIZE] = {0};
+    uint32_t actualLen = 0;
+    uint32_t written = 0;
+	palX509_t pubKey = { (const void*)g_pubKey,sizeof(g_pubKey) };
+	palPrivateKey_t prvKey = { (const void*)g_prvKey,sizeof(g_prvKey) };
+	palTLSSocket_t tlsSocket = { g_socket, &socketAddr, 0, transportationMode };
+	palX509_t caCert = { (const void*)pal_test_cas,sizeof(pal_test_cas) };
+    sotp_result_e sotpRes = SOTP_SUCCESS;
+	uint64_t currentTime = 0;
+    uint64_t updatedTime = 0;
+    uint16_t actualSavedTimeSize = 0;
+    palX509Handle_t trustedServerCA = NULLPTR;
+    int32_t verifyResult = 0;
+
+    /*#1*/
+    sotpRes = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(currentTime), (uint32_t*)&currentTime, &actualSavedTimeSize);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+    TEST_ASSERT_TRUE(0 != currentTime);
+
+    status = pal_osSetTime(currentTime - (PAL_SECONDS_PER_DAY / 2));//going back half day to simulate future server by half day (in order to prevent time update)
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	/*#2*/
+	status = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_socket);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	/*#3*/
+	status = pal_getAddressInfo(PAL_TLS_TEST_SERVER_ADDRESS, &socketAddr, &addressLength);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == status) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == status))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration or error)");
+        status = pal_close(&g_socket);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        return;
+    }
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#4*/
+    status = pal_setSockAddrPort(&socketAddr, TLS_RENEGOTIATE_SERVER_PORT);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	tlsSocket.addressLength = addressLength;
+	tlsSocket.socket = g_socket;
+    
+    /*#5*/
+	status = pal_x509Initiate(&trustedServerCA);
+	TEST_ASSERT_NOT_EQUAL(trustedServerCA, NULLPTR);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_x509CertParse(trustedServerCA, (const unsigned char *)pal_test_cas, sizeof(pal_test_cas));
+    if (PAL_SUCCESS != status)
+	{
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+    /*#6*/
+	status = pal_x509CertGetAttribute(trustedServerCA, PAL_X509_CERT_ID_ATTR, g_trustedServerID, sizeof(g_trustedServerID), &g_actualServerIDSize);
+    if (PAL_SUCCESS != status)
+	{
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+    /*#7*/
+    sotpRes = sotp_set(SOTP_TYPE_TRUSTED_TIME_SRV_ID, g_actualServerIDSize, (uint32_t*)g_trustedServerID);
+    if (SOTP_SUCCESS != sotpRes)
+	{
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+	}
+
+	/*#8*/
+	status = pal_connect(g_socket, &socketAddr, addressLength);
+	if (PAL_SUCCESS != status)
+	{
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#9*/
+	status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+	if (PAL_SUCCESS != status)
+	{
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#10*/
+	status = pal_initTLS(palTLSConf, &palTLSHandle);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+
+	/*#11*/
+	status = pal_setOwnCertAndPrivateKey(palTLSConf, &pubKey, &prvKey);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#12*/
+	status = pal_setCAChain(palTLSConf, &caCert, NULL);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#13*/
+	status = pal_tlsSetSocket(palTLSConf, &tlsSocket);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#14*/
+	status = pal_handShake(palTLSHandle, palTLSConf);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#15*/
+	status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_TRUE(PAL_ERR_X509_BADCERT_EXPIRED & verifyResult);
+	}
+    /*#16*/
+    status = pal_sslWrite(palTLSHandle, TLS_GET_REQUEST, sizeof(TLS_GET_REQUEST), &written);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+
+    pal_osDelay(5000);
+    /*#14*/
+    status = pal_sslRead(palTLSHandle, serverResponse, PAL_TLS_MESSAGE_SIZE, &actualLen);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+
+	/*#17*/
+	status = pal_freeTLS(&palTLSHandle);
+	if (PAL_SUCCESS != status)
+	{
+		pal_tlsConfigurationFree(&palTLSConf);
+        pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#18*/
+	status = pal_tlsConfigurationFree(&palTLSConf);
+	if (PAL_SUCCESS != status)
+	{
+		pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#19*/
+	status = pal_x509Free(&trustedServerCA);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_close(&g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	/*#20*/ 
+    sotpRes = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(updatedTime), (uint32_t*)&updatedTime, &actualSavedTimeSize);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+    TEST_ASSERT_EQUAL_HEX(currentTime, updatedTime);
+    #endif 
+
+}
+
+/**
+* @brief Test TLS handshake (TCP blocking) with near past time and validate that the handshake didn't update the device time (due to set time rules)
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Get saved time from SOTP, move forward half day and set time to RAM    | PAL_SUCCESS |
+* | 2 | Create a TCP (blocking) socket.                                        | PAL_SUCCESS |
+* | 3 | Perform a DNS lookup on the server address.                                | PAL_SUCCESS |
+* | 4 | Set the server port.                                                     | PAL_SUCCESS |
+* | 5 | Parse the CA cert.                                                     | PAL_SUCCESS |
+* | 6 | Get the CA cert ID.                                                     | PAL_SUCCESS |
+* | 7 | Set the CA cert ID into the SOTP.                                            | PAL_SUCCESS |
+* | 8 | Connect the TCP socket to the server.                                        | PAL_SUCCESS |
+* | 9 | Initialize the TLS configuration using `pal_initTLSConfiguration`.         | PAL_SUCCESS |
+* | 10 | Initialize the TLS context using `pal_initTLS`.                            | PAL_SUCCESS |
+* | 11 | Set the certificate and keys to the configuration using `pal_setOwnCertAndPrivateKey`.| PAL_SUCCESS |
+* | 12 | Set the certificate chain to the configuration using `pal_setCAChain`.        | PAL_SUCCESS |
+* | 13 | Set the socket to the configuration using `pal_tlsSetSocket`.           | PAL_SUCCESS |
+* | 14 | Perform a TLS handshake with the server using `pal_handShake`.           | PAL_SUCCESS |
+* | 15 | Verify the handshake result using `pal_sslGetVerifyResult`.               | PAL_SUCCESS |
+* | 16 | Write data over open TLS connection using `pal_sslWrite`.            | PAL_SUCCESS |
+* | 17 | Uninitialize the TLS context using `pal_freeTLS`.                         | PAL_SUCCESS |
+* | 18 | Uninitialize the TLS configuration using `pal_tlsConfigurationFree`.      | PAL_SUCCESS |
+* | 19 | Free X509 handle.                                                     | PAL_SUCCESS |
+* | 20 | Verify that the time was NOT updated during the handshake.                | PAL_SUCCESS |
+*/
+TEST(pal_tls, tlsHandshakeTCP_NearPastTrustedServer_NoTimeUpdate)
+{
+    #if ((PAL_USE_SECURE_TIME == 1) && (PAL_USE_INTERNAL_FLASH == 1))
+    palStatus_t status = PAL_SUCCESS;
+    palTLSConfHandle_t palTLSConf = NULLPTR;
+    palTLSHandle_t palTLSHandle = NULLPTR;
+    palTLSTransportMode_t transportationMode = PAL_TLS_MODE;
+    palSocketAddress_t socketAddr = { 0 };
+    palSocketLength_t addressLength = 0;
+    char serverResponse[PAL_TLS_MESSAGE_SIZE] = {0};
+    uint32_t actualLen = 0;
+    uint32_t written = 0;
+    palX509_t pubKey = { (const void*)g_pubKey,sizeof(g_pubKey) };
+    palPrivateKey_t prvKey = { (const void*)g_prvKey,sizeof(g_prvKey) };
+    palTLSSocket_t tlsSocket = { g_socket, &socketAddr, 0, transportationMode };
+    palX509_t caCert = { (const void*)pal_test_cas,sizeof(pal_test_cas) };
+    sotp_result_e sotpRes = SOTP_SUCCESS;
+    uint64_t currentTime = 0;
+    uint64_t updatedTime = 0;
+    uint16_t actualSavedTimeSize = 0;
+    palX509Handle_t trustedServerCA = NULLPTR;
+    int32_t verifyResult = 0;
+
+    /*#1*/
+    sotpRes = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(currentTime), (uint32_t*)&currentTime, &actualSavedTimeSize);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+    TEST_ASSERT_TRUE(0 != currentTime);
+
+    status = pal_osSetTime(currentTime + (PAL_SECONDS_PER_DAY / 2));//going back half day to simulate future server by half day (in order to prevent time update)
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, false, 0, &g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#3*/
+    status = pal_getAddressInfo(PAL_TLS_TEST_SERVER_ADDRESS, &socketAddr, &addressLength);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == status) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == status))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration or error)");
+        status = pal_close(&g_socket);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+        return;
+    }
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#4*/
+    status = pal_setSockAddrPort(&socketAddr, TLS_RENEGOTIATE_SERVER_PORT);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    tlsSocket.addressLength = addressLength;
+    tlsSocket.socket = g_socket;
+
+    /*#5*/
+    status = pal_x509Initiate(&trustedServerCA);
+    TEST_ASSERT_NOT_EQUAL(trustedServerCA, NULLPTR);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_x509CertParse(trustedServerCA, (const unsigned char *)pal_test_cas, sizeof(pal_test_cas));
+    if (PAL_SUCCESS != status)
+    {
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#6*/
+    status = pal_x509CertGetAttribute(trustedServerCA, PAL_X509_CERT_ID_ATTR, g_trustedServerID, sizeof(g_trustedServerID), &g_actualServerIDSize);
+    if (PAL_SUCCESS != status)
+    {
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#7*/
+    sotpRes = sotp_set(SOTP_TYPE_TRUSTED_TIME_SRV_ID, g_actualServerIDSize, (uint32_t*)g_trustedServerID);
+    if (SOTP_SUCCESS != sotpRes)
+    {
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+    }
+
+    /*#8*/
+    status = pal_connect(g_socket, &socketAddr, addressLength);
+    if (PAL_SUCCESS != status)
+    {
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#9*/
+    status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+    if (PAL_SUCCESS != status)
+    {
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#10*/
+    status = pal_initTLS(palTLSConf, &palTLSHandle);
+    if (PAL_SUCCESS != status)
+    {
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+
+    /*#11*/
+    status = pal_setOwnCertAndPrivateKey(palTLSConf, &pubKey, &prvKey);
+    if (PAL_SUCCESS != status)
+    {
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#12*/
+    status = pal_setCAChain(palTLSConf, &caCert, NULL);
+    if (PAL_SUCCESS != status)
+    {
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#13*/
+    status = pal_tlsSetSocket(palTLSConf, &tlsSocket);
+    if (PAL_SUCCESS != status)
+    {
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#14*/
+    status = pal_handShake(palTLSHandle, palTLSConf);
+    if (PAL_SUCCESS != status)
+    {
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	}
+	/*#15*/
+	status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult);
+	if (PAL_SUCCESS != status)
+	{
+		pal_freeTLS(&palTLSHandle);
+		pal_tlsConfigurationFree(&palTLSConf);
+        pal_x509Free(&trustedServerCA);
+		TEST_ASSERT_TRUE(PAL_ERR_X509_BADCERT_EXPIRED & verifyResult);
+	}
+    /*#16*/
+    status = pal_sslWrite(palTLSHandle, TLS_GET_REQUEST, sizeof(TLS_GET_REQUEST), &written);
+    if (PAL_SUCCESS != status)
+    {
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+
+    pal_osDelay(5000);
+    /*#14*/
+    status = pal_sslRead(palTLSHandle, serverResponse, PAL_TLS_MESSAGE_SIZE, &actualLen);
+    if (PAL_SUCCESS != status)
+    {
+        pal_freeTLS(&palTLSHandle);
+        pal_tlsConfigurationFree(&palTLSConf);
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+
+    /*#17*/
+    status = pal_freeTLS(&palTLSHandle);
+    if (PAL_SUCCESS != status)
+    {
+        pal_tlsConfigurationFree(&palTLSConf);
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#18*/
+    status = pal_tlsConfigurationFree(&palTLSConf);
+    if (PAL_SUCCESS != status)
+    {
+        pal_x509Free(&trustedServerCA);
+        TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    }
+    /*#19*/
+    status = pal_x509Free(&trustedServerCA);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_close(&g_socket);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+	/*#20*/ 
+    sotpRes = sotp_get(SOTP_TYPE_SAVED_TIME, sizeof(updatedTime), (uint32_t*)&updatedTime, &actualSavedTimeSize);
+    TEST_ASSERT_EQUAL_HEX(SOTP_SUCCESS, sotpRes);
+    TEST_ASSERT_EQUAL_HEX(currentTime, updatedTime);
+    #endif
+}
+
+#endif //PAL_USE_INTERNAL_FLASH
+
+static palStatus_t ThreadHandshakeTCP(bool socketNonBlocking)
+{
+    palStatus_t status = PAL_SUCCESS;
+    palStatus_t tmpStatus = PAL_SUCCESS;
+    palTLSConfHandle_t palTLSConf = NULLPTR;
+    palTLSHandle_t palTLSHandle = NULLPTR;
+    palTLSTransportMode_t transportationMode = PAL_TLS_MODE;
+    palSocketAddress_t socketAddr = {0};
+    palSocketLength_t addressLength = 0;
+    char serverResponse[PAL_TLS_MESSAGE_SIZE] = {0};
+    uint32_t actualLen = 0;
+    uint32_t written = 0;
+    palSocket_t socketTCP = 0;
+    palX509_t pubKey = {(const void*)g_pubKey,sizeof(g_pubKey)};
+    palPrivateKey_t prvKey = {(const void*)g_prvKey,sizeof(g_prvKey)};
+    palTLSSocket_t tlsSocket = { socketTCP, &socketAddr, 0, transportationMode };
+    palX509_t caCert = { (const void*)pal_test_cas,sizeof(pal_test_cas) };
+    palTLSTest_t *testTLSCtx = NULL;
+    palStatus_t mutexStatus = PAL_SUCCESS;
+    bool mutexWait = false;
+    int32_t verifyResult = 0;
+
+	mutexWait = true;
+    /*#1*/
+    status = pal_socket(PAL_AF_INET, PAL_SOCK_STREAM, socketNonBlocking, 0, &socketTCP);
+    PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+    /*#2*/
+    status = pal_getAddressInfo(PAL_TLS_TEST_SERVER_ADDRESS, &socketAddr, &addressLength);
+    PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+
+    tlsSocket.addressLength = addressLength;
+    tlsSocket.socket = socketTCP;
+    /*#3*/
+    if (true == socketNonBlocking)
+    {
+        status = pal_setSockAddrPort(&socketAddr, TLS_SERVER_PORT_NB);
+        PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+    }
+    else //blocking
+    {
+        status = pal_setSockAddrPort(&socketAddr, TLS_SERVER_PORT);
+        PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+    }
+
+    /*#4*/
+    status = pal_connect(socketTCP, &socketAddr, addressLength);
+    if (PAL_ERR_SOCKET_IN_PROGRES == status)
+    {
+        pal_osDelay(500);
+    }
+    else
+    {
+        PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+    }
+    /*#5*/
+    status = pal_initTLSConfiguration(&palTLSConf, transportationMode);
+    PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+    TEST_ASSERT_NOT_EQUAL(palTLSConf, NULLPTR);
+    /*#6*/
+    status = pal_initTLS(palTLSConf, &palTLSHandle);
+    PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+
+    // This code commented out to prevent massive prints from mbedTLS, if you want to see logs from client side, just uncomment them.
+    //status = pal_sslSetDebugging(palTLSConf, true);
+    //TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+    /*#7*/
+    status = pal_setOwnCertAndPrivateKey(palTLSConf, &pubKey, &prvKey);
+    PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+    /*#8*/
+    status = pal_setCAChain(palTLSConf, &caCert, NULL);
+    PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+    /*#9*/
+    status = pal_tlsSetSocket(palTLSConf, &tlsSocket);
+    PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+    /*#10*/
+    testTLSCtx = (palTLSTest_t*)palTLSHandle; //This casting is done to sign that we are in retry situation.
+    if (true == socketNonBlocking)
+    {
+        PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status); // More than current epoch time -> success
+        do
+        {
+            if (testTLSCtx->retryHandShake && !g_retryHandshake)
+            {
+                g_retryHandshake = true;
+                if (mutexWait)
+                {
+					mutexStatus = pal_osMutexRelease(g_mutexHandShake1);
+					TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, mutexStatus);
+					mutexWait = false;
+					pal_osDelay(600);
+                }
+            }
+            status = pal_handShake(palTLSHandle, palTLSConf);
+        }
+        while ( (PAL_ERR_TLS_WANT_READ == status) || (PAL_ERR_TLS_WANT_WRITE == status));
+    }
+    else //blocking
+    {
+        status = pal_handShake(palTLSHandle, palTLSConf);
+    }
+    PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+
+    /*#11*/
+    status = pal_sslGetVerifyResultExtended(palTLSHandle, &verifyResult);
+    PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+    /*#12*/
+    status = pal_sslWrite(palTLSHandle, TLS_GET_REQUEST, sizeof(TLS_GET_REQUEST), &written);
+    PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+    /*#13*/
+    pal_osDelay(5000);
+
+    /*#14*/
+    status = pal_sslRead(palTLSHandle, serverResponse, PAL_TLS_MESSAGE_SIZE, &actualLen);
+    PAL_TLS_INT32_CHECK_NOT_EQUAL_GOTO_FINISH(PAL_SUCCESS, status);
+
+finish:
+	if (mutexWait)
+	{
+		mutexStatus = pal_osMutexRelease(g_mutexHandShake1);
+		TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, mutexStatus);
+	}
+    /*#15*/
+    tmpStatus = pal_freeTLS(&palTLSHandle);
+    if (PAL_SUCCESS != tmpStatus)
+    {
+        PAL_LOG(ERR,"Expected: %d , Actual: %d , Line: %d\n", (int)PAL_SUCCESS, (int)tmpStatus, __LINE__);
+    }
+    /*#16*/
+    tmpStatus = pal_tlsConfigurationFree(&palTLSConf);
+    if (PAL_SUCCESS != tmpStatus)
+    {
+        PAL_LOG(ERR,"Expected: %d , Actual: %d , Line: %d\n", (int)PAL_SUCCESS, (int)tmpStatus, __LINE__);
+    }
+    /*#17*/
+    tmpStatus = pal_close(&socketTCP);
+    if (PAL_SUCCESS != tmpStatus)
+    {
+        PAL_LOG(ERR,"Expected: %d , Actual: %d , Line: %d\n", (int)PAL_SUCCESS, (int)tmpStatus, __LINE__);
+    }
+    if (PAL_SUCCESS == status)
+    {
+        status = tmpStatus;
+    }
+    return status;
+
+}
+
+void pal_TCPHandshakeFunc3(void const *argument)
+{
+    palStatus_t mutexStatus = PAL_SUCCESS;
+    palStatus_t* arg = (palStatus_t*)argument;
+
+    mutexStatus = pal_osMutexWait(g_mutexHandShake1, PAL_RTOS_WAIT_FOREVER);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, mutexStatus);
+
+    mutexStatus = pal_osMutexWait(g_mutex1, PAL_RTOS_WAIT_FOREVER);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, mutexStatus);
+
+    *arg = ThreadHandshakeTCP(true);
+
+    mutexStatus = pal_osMutexRelease(g_mutex1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, mutexStatus);
+}
+
+void pal_CertVerify(void const *argument)
+{
+#if (PAL_ENABLE_X509 == 1)
+    palStatus_t status = PAL_SUCCESS;
+    palStatus_t mutexStatus = PAL_SUCCESS;
+    palStatus_t* arg = (palStatus_t*)argument;
+    palX509Handle_t certHandle = NULLPTR;
+    int32_t verifyResult = 0;
+
+	mutexStatus = pal_osMutexWait(g_mutexHandShake1, PAL_RTOS_WAIT_FOREVER);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, mutexStatus);
+
+    status = pal_osMutexWait(g_mutex2, PAL_RTOS_WAIT_FOREVER);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_x509Initiate(&certHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_x509CertParse(certHandle, (const void*)pal_test_cas, sizeof(pal_test_cas));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    PAL_LOG(INFO,"Calling Cert Verify..");
+    *arg = pal_x509CertVerifyExtended(certHandle, certHandle, &verifyResult);
+    TEST_ASSERT_TRUE(PAL_ERR_X509_BADCERT_FUTURE & verifyResult);
+    
+    pal_x509Free(&certHandle);
+
+    mutexStatus = pal_osMutexRelease(g_mutexHandShake1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, mutexStatus);
+
+    mutexStatus = pal_osMutexRelease(g_mutex2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, mutexStatus);
+#endif
+}
+
+#if ((PAL_USE_SECURE_TIME == 1) && (PAL_ENABLE_X509 == 1))
+static void runTLSThreadTest(palThreadFuncPtr func1, palThreadFuncPtr func2, palStatus_t test1Result, palStatus_t test2Result)
+{
+	palStatus_t status = PAL_SUCCESS;
+	palThreadID_t threadID1 = NULLPTR;
+	palThreadID_t threadID2 = NULLPTR;
+	palStatus_t tlsArgs1 = PAL_SUCCESS;
+	palStatus_t tlsArgs2 = PAL_SUCCESS;
+
+    status = pal_osMutexCreate(&g_mutexHandShake1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osMutexCreate(&g_mutex1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osMutexCreate(&g_mutex2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osMutexWait(g_mutexHandShake1, PAL_RTOS_WAIT_FOREVER);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadCreateWithAlloc(func1, &tlsArgs1, PAL_osPriorityHigh, 5*PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID1);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osMutexRelease(g_mutexHandShake1);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	pal_osDelay(100);
+
+	status = pal_osThreadCreateWithAlloc(func2, &tlsArgs2, PAL_osPriorityAboveNormal, 5*PAL_TEST_THREAD_STACK_SIZE, NULL, &threadID2);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osMutexWait(g_mutex1, PAL_RTOS_WAIT_FOREVER);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osMutexWait(g_mutex2, PAL_RTOS_WAIT_FOREVER);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadTerminate(&threadID1);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+	status = pal_osThreadTerminate(&threadID2);
+	TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osMutexRelease(g_mutex1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osMutexRelease(g_mutex2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osMutexDelete(&g_mutex1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osMutexDelete(&g_mutex2);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_osMutexDelete(&g_mutexHandShake1);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    TEST_ASSERT_EQUAL_HEX(test1Result, tlsArgs1);
+    TEST_ASSERT_EQUAL_HEX(test2Result, tlsArgs2);
+}
+#endif
+
+
+
+/**
+* @brief Test try to process certificate verification with future certificate validation time while processing handshake
+*        in another thread to update the device time, we need to check that certificate verification is done against the 
+*        broken device time (0) and after handshake is done, we need to re-verify against the fixed time according to the
+*        server time sent by the server during handshake.
+*
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Create Thread1 to process DTLS handshake                | PAL_SUCCESS |
+* | 1 | Create Thread2 to process TLS handshake                 | PAL_ERR_X509_CERT_VERIFY_FAILED |
+*/
+TEST(pal_tls, TCPHandshakeWhileCertVerify_threads)
+{
+#if ((PAL_USE_SECURE_TIME == 1) && (PAL_ENABLE_X509 == 1))
+    palStatus_t status = PAL_SUCCESS;
+    palX509Handle_t certHandle = NULLPTR;
+    uint64_t systemTime = 0;
+    palSocketAddress_t socketAddr = { 0 };
+    palSocketLength_t addressLength = 0;
+
+    status = pal_getAddressInfo(PAL_TLS_TEST_SERVER_ADDRESS, &socketAddr, &addressLength);
+    if ((PAL_ERR_SOCKET_DNS_ERROR == status) || (PAL_ERR_SOCKET_INVALID_ADDRESS_FAMILY == status))
+    {
+        PAL_LOG(ERR, "error: address lookup returned an address not supported by current configuration cant continue test ( IPv6 add for IPv4 only configuration or IPv4 for IPv6 only configuration or error)");
+        return;
+    }
+
+    status = pal_osSetTime(0);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    runTLSThreadTest(pal_TCPHandshakeFunc3, pal_CertVerify, PAL_SUCCESS, PAL_ERR_X509_CERT_VERIFY_FAILED);
+
+    systemTime = pal_osGetTime();
+    TEST_ASSERT_TRUE(0 < systemTime);
+
+    status = pal_x509Initiate(&certHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_x509CertParse(certHandle, (const void*)pal_test_cas, sizeof(pal_test_cas));
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_x509CertVerify(certHandle, certHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+
+    status = pal_x509Free(&certHandle);
+    TEST_ASSERT_EQUAL_HEX(PAL_SUCCESS, status);
+#endif
+}
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test_address.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#ifndef PAL_TLS_TEST_SERVER_ADDRESS
+    #define PAL_TLS_TEST_SERVER_ADDRESS "192.168.8.19"
+#endif //PAL_TLS_TEST_SERVER_ADDRESS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_test_runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "unity.h"
+#include "unity_fixture.h"
+#include "pal.h"
+
+
+TEST_GROUP_RUNNER(pal_tls)
+{
+    RUN_TEST_CASE(pal_tls, tlsConfiguration);
+    RUN_TEST_CASE(pal_tls, tlsInitTLS);
+    RUN_TEST_CASE(pal_tls, tlsPrivateAndPublicKeys);
+    RUN_TEST_CASE(pal_tls, tlsCACertandPSK);
+    RUN_TEST_CASE(pal_tls, tlsHandshakeUDPTimeOut);
+    RUN_TEST_CASE(pal_tls, tlsHandshakeTCP);
+    RUN_TEST_CASE(pal_tls, tlsHandshakeTCP_nonBlocking);
+    RUN_TEST_CASE(pal_tls, tlsHandshakeTCP_FutureLWM2M); //Far future LWM2M - should update the time in SOTP
+    RUN_TEST_CASE(pal_tls, tlsHandshakeTCP_FutureLWM2M_NoTimeUpdate); // Near future LWM2M - No SOTP time update
+    RUN_TEST_CASE(pal_tls, tlsHandshakeTCP_ExpiredLWM2MCert);   // Expired LWM2M - Certificate verification MUST fail
+    RUN_TEST_CASE(pal_tls, tlsHandshakeTCP_ExpiredServerCert_Trusted); // Expired BootStrap - should update the times in SOTP
+    RUN_TEST_CASE(pal_tls, tlsHandshakeTCP_FutureTrustedServer_NoTimeUpdate); // Near future BootStrap - No SOTP time update
+    RUN_TEST_CASE(pal_tls, tlsHandshakeTCP_NearPastTrustedServer_NoTimeUpdate); // Near past BootStrap - No SOTP time update
+    RUN_TEST_CASE(pal_tls, TCPHandshakeWhileCertVerify_threads);
+    RUN_TEST_CASE(pal_tls, tlsHandshakeUDP);
+    RUN_TEST_CASE(pal_tls, tlsHandshakeUDP_NonBlocking);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/TLS/pal_tls_utils.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#ifndef TEST_TLS_PAL_TEST_UTILS_H_
+#define TEST_TLS_PAL_TEST_UTILS_H_
+
+#include "pal_network.h"
+#include "pal_TLS.h"
+
+typedef struct palTLSSocketTest{
+    palSocket_t socket;
+    palSocketAddress_t* socketAddress;
+    palSocketLength_t addressLength;
+    palTLSTransportMode_t transportationMode;
+}palTLSSocketTest_t;
+
+#define PAL_TLS_MESSAGE_SIZE 256
+#define TLS_GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
+#ifndef PAL_TLS_TEST_SERVER_ADDRESS
+    #include "pal_tls_test_address.h"
+#endif
+#define TLS_SERVER_PORT 5544
+#define TLS_SERVER_PORT_NB 5544
+#define TLS_RENEGOTIATE_SERVER_PORT TLS_SERVER_PORT
+#define DTLS_SERVER_PORT 4422
+#define DTLS_SERVER_PORT_TIMEOUT 9 //Discard protocol
+#define DTLS_TIMEOUT_TEST_SERVER_ADDRESS "8.8.8.8"
+
+
+
+const unsigned char g_psk[] = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
+};
+const unsigned char g_psk_id[] = "Client_identity";
+
+//ECC Key
+const unsigned char g_pubKey[] = 
+{
+  0x30, 0x82, 0x01, 0x99, 0x30, 0x82, 0x01, 0x3d, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01,
+  0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x29,
+  0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x03, 0x50, 0x41, 0x4c, 0x31, 0x0c,
+  0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x61, 0x72, 0x6d, 0x31, 0x0b, 0x30, 0x09,
+  0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30,
+  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x30, 0x31, 0x32,
+  0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x30, 0x31, 0x13, 0x30, 0x11, 0x06,
+  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x50, 0x41, 0x4c, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
+  0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x61, 0x72, 0x6d, 0x31, 0x0b,
+  0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x30, 0x59, 0x30, 0x13, 0x06,
+  0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03,
+  0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x18, 0x8f, 0xc6, 0x40, 0xf3, 0xf4, 0xbc, 0xd9, 0xed, 0x72,
+  0x7e, 0x96, 0x8f, 0xcc, 0x56, 0x31, 0x6d, 0x72, 0x1d, 0x4e, 0xd8, 0xb2, 0xc1, 0x5b, 0xcb, 0xcf,
+  0xd6, 0xc5, 0xdb, 0x1f, 0xdf, 0x99, 0x21, 0x01, 0xbc, 0x0c, 0x03, 0xb8, 0xa9, 0xbd, 0xd7, 0xb7,
+  0x4f, 0x06, 0x8c, 0x5f, 0x6e, 0xe8, 0x64, 0xc9, 0x69, 0x46, 0x96, 0xf8, 0xfd, 0x14, 0xe5, 0xe3,
+  0x5b, 0x8c, 0x92, 0x99, 0x04, 0xe6, 0xa3, 0x4d, 0x30, 0x4b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d,
+  0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14,
+  0xb8, 0x4f, 0xcc, 0xad, 0x6b, 0xad, 0xa1, 0x31, 0x75, 0x74, 0x57, 0xe3, 0x76, 0x9f, 0x5d, 0xc3,
+  0x4f, 0xcf, 0x20, 0x53, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+  0x14, 0xfe, 0x53, 0x4c, 0xfa, 0x9a, 0xc7, 0x2f, 0x0c, 0x72, 0xbf, 0xaa, 0x47, 0xc5, 0x16, 0x92,
+  0x67, 0x7f, 0x0e, 0x02, 0xef, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03,
+  0x02, 0x05, 0x00, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x97, 0x90, 0xa3, 0x5d, 0xab,
+  0xee, 0x4f, 0x56, 0x12, 0x15, 0x0f, 0xbe, 0x3a, 0x39, 0x21, 0x54, 0x44, 0x67, 0x48, 0xf8, 0xb4,
+  0x83, 0xbe, 0xda, 0x66, 0x62, 0xa0, 0xa5, 0x67, 0x1c, 0xf4, 0xba, 0x02, 0x20, 0x22, 0x41, 0x3f,
+  0x52, 0x3a, 0xaa, 0x9d, 0x3c, 0xf1, 0x99, 0x7d, 0x2c, 0x04, 0x89, 0xff, 0xce, 0x80, 0x56, 0xd1,
+  0x9c, 0xd9, 0x19, 0x06, 0xd3, 0xee, 0x41, 0x2b, 0x49, 0x76, 0x27, 0xfe, 0x4e
+};
+
+const uint8_t g_prvKey[] = 
+{
+  0x30, 0x78, 0x02, 0x01, 0x01, 0x04, 0x21, 0x00, 0xac, 0xfb, 0x43, 0x6f, 0xa1, 0x3c, 0x2d, 0x1a,
+  0x91, 0xd7, 0x58, 0xf8, 0x1f, 0x0f, 0xc5, 0x00, 0x11, 0xe1, 0x56, 0xe6, 0xed, 0x89, 0x96, 0x8b,
+  0x12, 0xe6, 0x32, 0x70, 0x82, 0x06, 0x01, 0xed, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
+  0x3d, 0x03, 0x01, 0x07, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x18, 0x8f, 0xc6, 0x40, 0xf3, 0xf4,
+  0xbc, 0xd9, 0xed, 0x72, 0x7e, 0x96, 0x8f, 0xcc, 0x56, 0x31, 0x6d, 0x72, 0x1d, 0x4e, 0xd8, 0xb2,
+  0xc1, 0x5b, 0xcb, 0xcf, 0xd6, 0xc5, 0xdb, 0x1f, 0xdf, 0x99, 0x21, 0x01, 0xbc, 0x0c, 0x03, 0xb8,
+  0xa9, 0xbd, 0xd7, 0xb7, 0x4f, 0x06, 0x8c, 0x5f, 0x6e, 0xe8, 0x64, 0xc9, 0x69, 0x46, 0x96, 0xf8,
+  0xfd, 0x14, 0xe5, 0xe3, 0x5b, 0x8c, 0x92, 0x99, 0x04, 0xe6
+};
+
+
+const char pal_test_cas[] = 
+{
+  0x30, 0x82, 0x01, 0x98, 0x30, 0x82, 0x01, 0x3c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01,
+  0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x29,
+  0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x03, 0x50, 0x41, 0x4c, 0x31, 0x0c,
+  0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x03, 0x61, 0x72, 0x6d, 0x31, 0x0b, 0x30, 0x09,
+  0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x49, 0x4c, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30,
+  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x30, 0x31, 0x32,
+  0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x29, 0x31, 0x0c, 0x30, 0x0a, 0x06,
+  0x03, 0x55, 0x04, 0x03, 0x13, 0x03, 0x50, 0x41, 0x4c, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55,
+  0x04, 0x0a, 0x13, 0x03, 0x61, 0x72, 0x6d, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+  0x13, 0x02, 0x49, 0x4c, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
+  0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xa4,
+  0x26, 0x26, 0x29, 0x98, 0x43, 0x6c, 0xc2, 0x2c, 0xbe, 0x0a, 0x90, 0xe3, 0x78, 0x44, 0xa9, 0x15,
+  0x0b, 0x02, 0x26, 0xf6, 0x14, 0xda, 0x36, 0x5b, 0x0f, 0x1d, 0x15, 0xb1, 0x56, 0x76, 0xec, 0x7f,
+  0x59, 0x6b, 0x9d, 0x69, 0xd9, 0xd8, 0x16, 0x22, 0xf1, 0x90, 0x63, 0xa1, 0xd3, 0xb7, 0xd7, 0x32,
+  0x31, 0x8d, 0xc7, 0xbe, 0x8f, 0xc8, 0x20, 0x5a, 0x9d, 0xfa, 0x03, 0x79, 0x7a, 0xcb, 0x7e, 0xa3,
+  0x53, 0x30, 0x51, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01,
+  0xff, 0x02, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xfe,
+  0x53, 0x4c, 0xfa, 0x9a, 0xc7, 0x2f, 0x0c, 0x72, 0xbf, 0xaa, 0x47, 0xc5, 0x16, 0x92, 0x67, 0x7f,
+  0x0e, 0x02, 0xef, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+  0xfe, 0x53, 0x4c, 0xfa, 0x9a, 0xc7, 0x2f, 0x0c, 0x72, 0xbf, 0xaa, 0x47, 0xc5, 0x16, 0x92, 0x67,
+  0x7f, 0x0e, 0x02, 0xef, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
+  0x05, 0x00, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0x97, 0xce, 0xc5, 0x3c, 0x94, 0xb5,
+  0xd4, 0x3b, 0xec, 0x92, 0xed, 0x2b, 0x96, 0x3f, 0xdc, 0xae, 0x16, 0xd2, 0x02, 0x6a, 0xa6, 0x8d,
+  0xf5, 0xb1, 0x5b, 0x61, 0x95, 0xfc, 0x4d, 0x17, 0x0e, 0xab, 0x02, 0x20, 0x40, 0x7b, 0x27, 0x11,
+  0x83, 0x87, 0xfe, 0x62, 0xa2, 0x67, 0x7c, 0xa8, 0x8e, 0xd5, 0xf3, 0xdc, 0x62, 0xf9, 0x35, 0x91,
+  0x0b, 0x43, 0x80, 0xc9, 0x12, 0x30, 0x2e, 0x66, 0x64, 0xbf, 0xf2, 0xcb
+};
+
+#endif /* TEST_TLS_PAL_TEST_UTILS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Update/pal_update_test.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,663 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal.h"
+#include "unity.h"
+#include "unity_fixture.h"
+#include "string.h"
+#include "mbed_trace.h"
+
+
+#define KILOBYTE 1024
+
+#define FIRST_IMAGE_INDEX        0
+
+TEST_GROUP(pal_update);
+
+
+palBuffer_t g_writeBuffer = {0};
+palBuffer_t g_readBuffer = {0};
+palImageHeaderDeails_t g_imageHeader = {0};
+uint8_t g_isTestDone;
+
+
+uint8_t numberofBlocks = 0;
+
+/*! \brief Sanity test the update test are running.
+*/
+TEST_SETUP(pal_update)
+{
+    PAL_LOG(INFO, "running new test\r\n");
+
+}
+
+typedef enum _updateTestState
+{
+    test_init = 1,
+    test_write,
+    test_commit,
+    test_read
+}updateTestState;
+
+PAL_PRIVATE void stateAdvance(palImageEvents_t state)
+{
+    PAL_PRINTF("Finished event %d\r\n",state);
+    state++;
+    PAL_PRINTF("Starting event %d\r\n",state);
+    int rc = PAL_SUCCESS;
+    PAL_PRINTF("Write ptr = (%p - %p) read ptr = (%p - %p)\r\n",
+            g_writeBuffer.buffer,g_writeBuffer.buffer + g_writeBuffer.maxBufferLength,
+            g_readBuffer.buffer, g_readBuffer.buffer + g_readBuffer.maxBufferLength);
+    switch (state)
+    {
+    case PAL_IMAGE_EVENT_PREPARE:
+          rc = pal_imagePrepare(FIRST_IMAGE_INDEX, &g_imageHeader);
+          PAL_PRINTF("pal_imagePrepare returned %d \r\n",rc);
+          break;
+    case PAL_IMAGE_EVENT_WRITE:
+          rc = pal_imageWrite(FIRST_IMAGE_INDEX, 0, (palConstBuffer_t*)&g_writeBuffer);
+          PAL_PRINTF("pal_imageWrite returned %d \r\n",rc);
+          TEST_ASSERT_TRUE(rc >= 0);
+          break;
+    case PAL_IMAGE_EVENT_FINALIZE:
+          rc = pal_imageFinalize(FIRST_IMAGE_INDEX);
+          PAL_PRINTF("pal_imageFinalize returned %d \r\n",rc);
+          TEST_ASSERT_TRUE(rc >= 0);
+          break;
+    case PAL_IMAGE_EVENT_READTOBUFFER:
+          rc = pal_imageReadToBuffer(FIRST_IMAGE_INDEX,0,&g_readBuffer);
+          TEST_ASSERT_TRUE(rc >= 0);
+          PAL_PRINTF("pal_imageReadToBuffer  with offset %d return %d \r\n",0,rc);
+          break;
+    case PAL_IMAGE_EVENT_ACTIVATE:
+          PAL_PRINTF("Checking the output\r\n");
+          PAL_PRINTF("\r\ng_readBuffer bufferLength=%" PRIu32 "\r\n",g_readBuffer.maxBufferLength);
+
+
+          TEST_ASSERT_EQUAL_MEMORY(g_writeBuffer.buffer,g_readBuffer.buffer,g_readBuffer.maxBufferLength);
+          PAL_PRINTF("write ptr = %p read ptr = %p\r\n",g_writeBuffer.buffer,g_readBuffer.buffer);
+
+          free(g_readBuffer.buffer);
+          free(g_writeBuffer.buffer);
+          pal_imageDeInit();
+          g_isTestDone = 1;
+          break;
+    default:
+        PAL_PRINTF("Error - this should not happen\r\n");
+        PAL_PRINTF("Write ptr = %p read ptr = %p\r\n",g_writeBuffer.buffer,g_readBuffer.buffer);
+        free(g_readBuffer.buffer);
+        free(g_writeBuffer.buffer);
+        pal_imageDeInit();
+        g_isTestDone = 1;
+    }
+}
+
+
+
+
+
+
+void printBuffer(uint8_t* buffer, size_t bufSize)
+{
+    size_t i = 0;
+    PAL_PRINTF("0x");
+    for (i=0;i < bufSize;i++)
+    {
+        PAL_PRINTF("%x",buffer[i]);
+    }
+    PAL_PRINTF("\r\n");
+}
+
+
+PAL_PRIVATE void fillBuffer(uint8_t* buffer, size_t bufSize)
+{
+    size_t  i = 0;
+    uint8_t value = 0;
+    int8_t step = -1;
+    PAL_PRINTF("Filling buffer size %zu\r\n",bufSize);
+    for(i=0; i < bufSize ; i++)
+    {
+        buffer[i] = value;
+        if ((0 == value) || (255 == value))
+        {
+            step*=-1;
+        }
+        value+=step;
+    }
+    PAL_PRINTF("Buffer is full\r\n");
+
+}
+
+
+TEST_TEAR_DOWN(pal_update)
+{
+}
+
+
+
+void pal_update_xK(int sizeInK)
+{
+
+  palStatus_t rc = PAL_SUCCESS;
+  if (!(sizeInK % KILOBYTE))
+  {
+      PAL_PRINTF("\n-====== PAL_UPDATE_%dKb ======- \n",sizeInK / KILOBYTE);
+  }
+  else
+  {
+      PAL_PRINTF("\n-====== PAL_UPDATE_%db ======- \n",sizeInK);
+  }
+  uint8_t *writeData = (uint8_t*)malloc(sizeInK);
+  uint8_t *readData  = (uint8_t*)malloc(sizeInK);
+
+  TEST_ASSERT_TRUE(writeData != NULL);
+  TEST_ASSERT_TRUE(readData != NULL);
+
+  uint64_t version = 11111111;
+  uint32_t hash    = 0x22222222;
+
+  g_isTestDone = 0;
+
+  g_imageHeader.version = version;
+
+  g_imageHeader.hash.buffer =(uint8_t*)&hash;
+  g_imageHeader.hash.bufferLength = sizeof(hash);
+  g_imageHeader.hash.maxBufferLength = sizeof(hash);
+
+  g_imageHeader.imageSize = sizeInK;
+
+  g_writeBuffer.buffer = writeData;
+  g_writeBuffer.bufferLength = sizeInK;
+  g_writeBuffer.maxBufferLength = sizeInK;
+
+  PAL_PRINTF("write buffer length %" PRIu32 " max length %" PRIu32 "\r\n",g_writeBuffer.bufferLength,g_writeBuffer.maxBufferLength);
+  fillBuffer(g_writeBuffer.buffer,g_writeBuffer.bufferLength);
+
+  g_readBuffer.buffer = readData;
+  g_readBuffer.maxBufferLength = sizeInK;
+
+
+  rc =pal_imageInitAPI(stateAdvance);
+  PAL_PRINTF("pal_imageInitAPI returned %" PRIu32 " \r\n",rc);
+  TEST_ASSERT_TRUE(rc >= 0);
+
+  /*Wait until the async test finishes*/
+  while (!g_isTestDone)
+      pal_osDelay(5); //Make the OS switch context
+
+}
+
+/*! \brief Writing a 1Kb image and verifying its value.
+ * \test
+*  This test simulates a state machine for writing and reading a 1Kb image.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize the test.                                      | Success |
+* | 2 | `pal_imagePrepare`                               | PAL_SUCCESS |
+* | 3 | `pal_imageWrite`                                 | PAL_SUCCESS |
+* | 4 | `pal_imageFinalize`                              | PAL_SUCCESS |
+* | 5 | `pal_imageReadToBuffer`                          | PAL_SUCCESS |
+* | 6 | Compare the written image with the read image.            | memcmp == 0 |
+*/
+
+TEST(pal_update, pal_update_1k)
+{
+    pal_update_xK(1*KILOBYTE);
+}
+
+
+/*! \brief Writing a 2Kb image and verifying its value.
+ * \test
+*  This test simulates a state machine for writing and reading a 2Kb image.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize the test.                                      | Success |
+* | 2 | `pal_imagePrepare`                               | PAL_SUCCESS |
+* | 3 | `pal_imageWrite`                                 | PAL_SUCCESS |
+* | 4 | `pal_imageFinalize`                              | PAL_SUCCESS |
+* | 5 | `pal_imageReadToBuffer`                          | PAL_SUCCESS |
+* | 6 | Compare the written image with the read image.            | memcmp == 0 |
+*/
+
+TEST(pal_update, pal_update_2k)
+{
+    pal_update_xK(2*KILOBYTE);
+}
+
+/*! \brief Writing a 4Kb image and verifying its value.
+ * \test
+*  This test simulates a state machine for writing and reading a 4Kb image.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize the test.                                     | Success |
+* | 2 | `pal_imagePrepare`                               | PAL_SUCCESS |
+* | 3 | `pal_imageWrite`                                 | PAL_SUCCESS |
+* | 4 | `pal_imageFinalize`                              | PAL_SUCCESS |
+* | 5 | `pal_imageReadToBuffer`                          | PAL_SUCCESS |
+* | 6 | Compare the written image with the read image.            | memcmp == 0 |
+*/
+
+TEST(pal_update, pal_update_4k)
+{
+    pal_update_xK(4*KILOBYTE);
+}
+
+/*! \brief Writing an 8Kb image and verifying its value.
+ * \test
+*  This test simulates a state machine for writing and reading an 8Kb image.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize the test.                              | Success |
+* | 2 | `pal_imagePrepare`                      | PAL_SUCCESS |
+* | 3 | `pal_imageWrite`                        | PAL_SUCCESS |
+* | 4 | `pal_imageFinalize`                     | PAL_SUCCESS |
+* | 5 | `pal_imageReadToBuffer`                 | PAL_SUCCESS |
+* | 6 | Compare the written image with the read image.   | memcmp == 0 |
+*/
+
+TEST(pal_update, pal_update_8k)
+{
+    pal_update_xK(8*KILOBYTE);
+}
+
+/*! \brief Writing a 16Kb image and verifying its value.
+ * \test
+*  This test simulates a state machine for writing and reading a 16Kb image.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize the test.                                 | Success |
+* | 2 | `pal_imagePrepare`                           | PAL_SUCCESS |
+* | 3 | `pal_imageWrite`                             | PAL_SUCCESS |
+* | 4 | `pal_imageFinalize`                          | PAL_SUCCESS |
+* | 5 | `pal_imageReadToBuffer`                      | PAL_SUCCESS |
+* | 6 | Compare the written image with the read image.        | memcmp == 0 |
+*/
+
+TEST(pal_update, pal_update_16k)
+{
+    pal_update_xK(16*KILOBYTE);
+}
+
+
+/*! \brief Writing a small image (5b) and verifying its value.
+ * \test
+*  This test simulates a state machine for writing and reading a 5b image.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize the test.                             | Success |
+* | 2 | `pal_imagePrepare`                       | PAL_SUCCESS |
+* | 3 | `pal_imageWrite`                         | PAL_SUCCESS |
+* | 4 | `pal_imageFinalize`                      | PAL_SUCCESS |
+* | 5 | `pal_imageReadToBuffer`                  | PAL_SUCCESS |
+* | 6 | Compare the written image with the read image.    | memcmp == 0 |
+*/
+
+
+TEST(pal_update,pal_update_writeSmallChunk_5b)
+{
+    pal_update_xK(5);
+}
+
+
+/*! \brief Writing an unaligned image of 1001b and verifying its value.
+ * \test
+*  This test simulates a state machine for writing and reading a 51001b image.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize the test.                                   | Success |
+* | 2 | `pal_imagePrepare`                            | PAL_SUCCESS |
+* | 3 | `pal_imageWrite`                              | PAL_SUCCESS |
+* | 4 | `pal_imageFinalize`                           | PAL_SUCCESS |
+* | 5 | `pal_imageReadToBuffer`                       | PAL_SUCCESS |
+* | 6 | Compare the written image with the read image.         | memcmp == 0 |
+*/
+
+
+TEST(pal_update,pal_update_writeUnaligned_1001b)
+{
+    //1039 is a prime number so probably never aligned.
+    pal_update_xK(1039);
+}
+
+
+
+
+PAL_PRIVATE void multiWriteMultiRead(palImageEvents_t state)
+{
+    int rc = PAL_SUCCESS;
+    static uint8_t counter = 0;
+    static uint8_t *writeBase = NULL;
+    static uint8_t *readBase = NULL;
+    if (NULL == writeBase)
+    {
+        writeBase = g_writeBuffer.buffer;
+        g_writeBuffer.maxBufferLength = g_writeBuffer.maxBufferLength/numberofBlocks;
+        g_writeBuffer.bufferLength = g_writeBuffer.bufferLength/numberofBlocks;
+
+        readBase = g_readBuffer.buffer;
+        g_readBuffer.maxBufferLength = g_readBuffer.maxBufferLength/numberofBlocks;
+    }
+    PAL_PRINTF("Finished event %d\r\n",state);
+    if (PAL_IMAGE_EVENT_WRITE == state) // Just wrote data
+    {
+        counter++;
+        if (numberofBlocks == counter) // Wrote all needed blocks
+        {
+            state++; // Advance to next state
+            counter = 0; //Initialize counter
+        }
+    }
+    else if (PAL_IMAGE_EVENT_READTOBUFFER == state) // Just read data
+    {
+        counter++ ;
+        if (numberofBlocks == counter) // Read all needed blocks
+        {
+            state++; // Advance to next state
+            counter = 0;
+        }
+    }
+    else
+    {
+        state++; // Advance to next state
+    }
+
+    PAL_PRINTF("Starting event %d\r\n",state);
+
+    switch (state)
+    {
+    case PAL_IMAGE_EVENT_PREPARE:
+          rc = pal_imagePrepare(FIRST_IMAGE_INDEX, &g_imageHeader);
+          PAL_PRINTF("pal_imagePrepare returned %d \r\n",rc);
+          break;
+    case PAL_IMAGE_EVENT_WRITE:
+          PAL_PRINTF("Write KILOBYTE * %d = %d\r\n",counter,KILOBYTE*(counter));
+          g_writeBuffer.buffer = &writeBase[KILOBYTE*(counter)];// Writing 1k every time
+          rc = pal_imageWrite(FIRST_IMAGE_INDEX, KILOBYTE*(counter),(palConstBuffer_t*)&g_writeBuffer);
+          PAL_PRINTF("pal_imageWrite returned %d \r\n",rc);
+          TEST_ASSERT_TRUE(rc >= 0);
+          break;
+    case PAL_IMAGE_EVENT_FINALIZE:
+          rc = pal_imageFinalize(FIRST_IMAGE_INDEX);
+          PAL_PRINTF("pal_imageFinalize returned %d \r\n",rc);
+          TEST_ASSERT_TRUE(rc >= 0);
+          break;
+    case PAL_IMAGE_EVENT_READTOBUFFER:
+          PAL_PRINTF("Read KILOBYTE * %d = %d\r\n",counter, KILOBYTE*(counter));
+          g_readBuffer.buffer = &readBase[KILOBYTE*(counter)];// Writing 1k every time
+          g_readBuffer.bufferLength = 0;
+          rc = pal_imageReadToBuffer(FIRST_IMAGE_INDEX, KILOBYTE*(counter),&g_readBuffer);
+          PAL_PRINTF("pal_imageReadToBuffer  with offset %d return %d \r\n",0,rc);
+          break;
+    case PAL_IMAGE_EVENT_ACTIVATE:
+
+          PAL_PRINTF("Checking the output\r\n");
+
+          TEST_ASSERT_TRUE(rc >= 0);
+          TEST_ASSERT_TRUE(!memcmp(readBase,writeBase,numberofBlocks*KILOBYTE));
+          free(writeBase);
+          free(readBase);
+          pal_imageDeInit();
+          g_isTestDone = 1;
+          break;
+    default:
+        PAL_PRINTF("Error\r\n");
+        free(writeBase);
+        free(readBase);
+        pal_imageDeInit();
+        g_isTestDone = 1;
+        break;
+    }
+}
+
+
+/*! \brief Writing a 4Kb image and reading it with a 1Kb buffer.
+ * \test
+*  This test simulates a state machine for writing and reading a 4Kb image.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize the test.                                             | Success |
+* | 2 | `pal_imagePrepare`                                     | PAL_SUCCESS |
+* | 3 | `pal_imageWrite`                                       | PAL_SUCCESS |
+* | 4 | `pal_imageFinalize`                                    | PAL_SUCCESS |
+* | 5 | `pal_imageReadToBuffer`                                | PAL_SUCCESS |
+* | 6 | Compare the written image with the read image.                  | memcmp == 0 |
+*/
+
+TEST(pal_update, pal_update_4k_write_1k_4_times)
+{
+  palStatus_t rc = PAL_SUCCESS;
+
+  uint8_t *writeData = (uint8_t*)malloc(4*KILOBYTE);
+  uint8_t *readData  = (uint8_t*)malloc(4*KILOBYTE);
+
+
+  TEST_ASSERT_TRUE(writeData != NULL);
+  TEST_ASSERT_TRUE(readData != NULL);
+
+  uint64_t version = 11111111;
+  uint32_t hash    = 0x22222222;
+  g_isTestDone = 0;
+
+  g_imageHeader.version = version;
+
+  g_imageHeader.hash.buffer =(uint8_t*)&hash;
+  g_imageHeader.hash.bufferLength = sizeof(hash);
+  g_imageHeader.hash.maxBufferLength = sizeof(hash);
+
+  g_imageHeader.imageSize = 4*KILOBYTE;
+
+  fillBuffer(writeData,4*KILOBYTE);
+
+  g_writeBuffer.buffer = writeData;
+  g_writeBuffer.bufferLength = 4*KILOBYTE;
+  g_writeBuffer.maxBufferLength = 4*KILOBYTE;
+  PAL_PRINTF("pal_update_4k");
+  PAL_PRINTF("Write buffer length %" PRIu32 " max length %" PRIu32 "\r\n",g_writeBuffer.bufferLength,g_writeBuffer.maxBufferLength);
+  fillBuffer(g_writeBuffer.buffer,g_writeBuffer.bufferLength);
+
+  g_readBuffer.buffer = readData;
+  g_readBuffer.maxBufferLength =  4*KILOBYTE;
+
+  numberofBlocks = 4;
+
+  rc = pal_imageInitAPI(multiWriteMultiRead);
+  PAL_PRINTF("pal_imageInitAPI returned %" PRIu32 " \r\n",rc);
+  TEST_ASSERT_TRUE(rc >= 0);
+  /*Wait until the async test finishes*/
+  while (!g_isTestDone)
+      pal_osDelay(5); // Make the OS switch context
+
+}
+
+/*! \brief Writing a different image with incrementing size.
+ * \test
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize the test.                           | Success |
+* | 2 | `1kb_image`                          | Success |
+* | 3 | `2kb_image`                          | Success |
+* | 4 | `4kb_image`                          | Success |
+* | 5 | `8kb_image`                          | Success |
+* | 6 | `16kb_image`                         | Success |
+* | 7 | `32kb_image`                         | Success |
+*/
+TEST(pal_update, pal_update_stressTest)
+{
+    uint8_t it,j;
+    PAL_PRINTF("****************************************************\r\n");
+    PAL_PRINTF("******* Testing multiple writes sequentially *******\r\n");
+    PAL_PRINTF("****************************************************\r\n");
+    for (j=0; j < 5; j++)
+    {
+        PAL_PRINTF("1\r\n");
+        for (it = 1; it < 32; it*=2)
+        {
+            pal_update_xK(it*KILOBYTE);
+
+        }
+    }
+}
+
+
+
+
+
+
+PAL_PRIVATE void readStateMachine(palImageEvents_t state)
+{
+    static uint8_t *readData = NULL ;
+    static uint32_t bytesWasRead = 0;
+    int rc = PAL_SUCCESS;
+    PAL_PRINTF("Finished event %d\r\n",state);
+    /*If just finished reading*/
+    if (PAL_IMAGE_EVENT_READTOBUFFER == state)
+    {
+        PAL_PRINTF("g_readBuffer.bufferLength %" PRIu32 "\r\n",g_readBuffer.bufferLength);
+        if (0 < g_readBuffer.bufferLength)
+        {
+            PAL_PRINTF("Writing %" PRIu32 " bytes to readData[%" PRIu32 "]\r\n",g_readBuffer.bufferLength,bytesWasRead);
+            memcpy(&readData[bytesWasRead],g_readBuffer.buffer,g_readBuffer.bufferLength);
+            bytesWasRead+=g_readBuffer.bufferLength;
+        }
+        else
+        {
+            state++;
+        }
+    }
+    else
+    {
+        state++;
+    }
+    PAL_PRINTF("Starting event %d\r\n",state);
+    switch (state)
+    {
+    case PAL_IMAGE_EVENT_PREPARE:
+          bytesWasRead = 0;
+          PAL_PRINTF("Allocating %" PRIu32 " byes for test \r\n",g_writeBuffer.maxBufferLength);
+          readData = (uint8_t*)malloc(g_writeBuffer.maxBufferLength);
+          TEST_ASSERT_TRUE(readData != NULL);
+          rc = pal_imagePrepare(FIRST_IMAGE_INDEX,&g_imageHeader);
+          PAL_PRINTF("pal_imagePrepare returned %d \r\n",rc);
+          break;
+    case PAL_IMAGE_EVENT_WRITE:
+          rc = pal_imageWrite(FIRST_IMAGE_INDEX,0,(palConstBuffer_t*)&g_writeBuffer);
+          PAL_PRINTF("pal_imageWrite returned %d \r\n",rc);
+          TEST_ASSERT_TRUE(rc >= 0);
+          break;
+    case PAL_IMAGE_EVENT_FINALIZE:
+          rc = pal_imageFinalize(FIRST_IMAGE_INDEX);
+          PAL_PRINTF("pal_imageFinalize returned %d \r\n",rc);
+          TEST_ASSERT_TRUE(rc >= 0);
+          break;
+    case PAL_IMAGE_EVENT_READTOBUFFER:
+          g_readBuffer.bufferLength = 0;
+          memset(g_readBuffer.buffer,0,g_readBuffer.maxBufferLength);
+          rc = pal_imageReadToBuffer(FIRST_IMAGE_INDEX,bytesWasRead,&g_readBuffer);
+          PAL_PRINTF("pal_imageReadToBuffer  with offset %" PRIu32 " return %d \r\n",bytesWasRead,rc);
+          //TEST_ASSERT_TRUE((rc >= 0) || (rc != -10));
+          break;
+    case PAL_IMAGE_EVENT_ACTIVATE:
+          PAL_PRINTF("Checking the output\r\n");
+          PAL_PRINTF("\r\ng_readBuffer bufferLength=%" PRIu32 "\r\n",g_readBuffer.maxBufferLength);
+          TEST_ASSERT_TRUE(!memcmp(readData,g_writeBuffer.buffer,g_writeBuffer.bufferLength));
+          PAL_PRINTF("write ptr = %p read ptr = %p\r\n",g_writeBuffer.buffer,g_readBuffer.buffer);
+          free(g_readBuffer.buffer);
+          free(g_writeBuffer.buffer);
+          free(readData);
+          pal_imageDeInit();
+          g_isTestDone = 1;
+          break;
+    default:
+        PAL_PRINTF("Error - this should not happen\r\n");
+        PAL_PRINTF("write ptr = %p read ptr = %p\r\n",g_writeBuffer.buffer,g_readBuffer.buffer);
+        free(g_readBuffer.buffer);
+        free(g_writeBuffer.buffer);
+        free(readData);
+        pal_imageDeInit();
+        g_isTestDone = 1;
+        TEST_ASSERT_TRUE(rc >= 0);
+    }
+}
+
+
+
+/*! \brief Writing an image and verifying its value by multiple reads.
+ * \test
+*  This test simulates a state machine for writing and reading an image.
+*
+* | # |    Step                        |   Expected  |
+* |---|--------------------------------|-------------|
+* | 1 | Initialize the test.                                        | Success |
+* | 2 | `pal_imagePrepare`                                 | PAL_SUCCESS |
+* | 3 | `pal_imageWrite`                                   | PAL_SUCCESS |
+* | 4 | `pal_imageFinalize`                                | PAL_SUCCESS |
+* | 5 | `pal_imageReadToBuffer`                            | PAL_SUCCESS |
+* | 6 | Compare the written image with the read image.              | memcmp == 0 |
+*/
+
+TEST(pal_update, pal_update_Read)
+{
+      uint32_t sizeIn=1500;
+      palStatus_t rc = PAL_SUCCESS;
+      PAL_PRINTF("\n-====== PAL_UPDATE_READ TEST %" PRIu32 " b ======- \n",sizeIn);
+      uint8_t *writeData = (uint8_t*)malloc(sizeIn);
+      uint8_t *readData  = (uint8_t*)malloc(sizeIn/5);
+
+      TEST_ASSERT_TRUE(writeData != NULL);
+      TEST_ASSERT_TRUE(readData != NULL);
+
+      uint64_t version = 11111111;
+      uint32_t hash    = 0x22222222;
+
+      g_isTestDone = 0;
+
+      g_imageHeader.version = version;
+
+      g_imageHeader.hash.buffer = (uint8_t*)&hash;
+      g_imageHeader.hash.bufferLength = sizeof(hash);
+      g_imageHeader.hash.maxBufferLength = sizeof(hash);
+
+      g_imageHeader.imageSize = sizeIn;
+
+      g_writeBuffer.buffer = writeData;
+      g_writeBuffer.bufferLength = sizeIn;
+      g_writeBuffer.maxBufferLength = sizeIn;
+
+      PAL_PRINTF("write buffer length %" PRIu32 " max length %" PRIu32 "\r\n",g_writeBuffer.bufferLength,g_writeBuffer.maxBufferLength);
+      fillBuffer(g_writeBuffer.buffer,g_writeBuffer.bufferLength);
+
+      g_readBuffer.buffer = readData;
+      g_readBuffer.maxBufferLength = sizeIn/5;
+      g_readBuffer.bufferLength = 0;
+
+      rc =pal_imageInitAPI(readStateMachine);
+      PAL_PRINTF("pal_imageInitAPI returned %" PRIu32 " \r\n",rc);
+      TEST_ASSERT_TRUE(rc >= 0);
+
+      /*Wait until the async test finishes*/
+      while (!g_isTestDone)
+          pal_osDelay(5); // Make the OS switch context
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/Update/pal_update_test_runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "unity.h"
+#include "unity_fixture.h"
+#include "pal.h"
+
+
+// PAL Update API tests
+TEST_GROUP_RUNNER(pal_update)
+{
+  RUN_TEST_CASE(pal_update, pal_update_writeSmallChunk_5b);
+  RUN_TEST_CASE(pal_update, pal_update_writeUnaligned_1001b);
+  RUN_TEST_CASE(pal_update, pal_update_1k);
+  RUN_TEST_CASE(pal_update, pal_update_2k);
+  RUN_TEST_CASE(pal_update, pal_update_4k);
+  RUN_TEST_CASE(pal_update, pal_update_8k);
+  RUN_TEST_CASE(pal_update, pal_update_16k);
+  RUN_TEST_CASE(pal_update, pal_update_Read);
+  RUN_TEST_CASE(pal_update, pal_update_stressTest);
+  RUN_TEST_CASE(pal_update, pal_update_4k_write_1k_4_times);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/test_main.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,377 @@
+
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "stdio.h"
+
+#include "PlatIncludes.h"
+#include "test_runners.h"
+#include "pal_BSP.h"
+#include "pal.h"
+#include "mbed_trace.h"
+#include "unity.h"
+#include "unity_fixture.h"
+
+extern struct _Unity Unity;
+
+#define PAL_TEST_STATUS_FILE_LOCATION "/tstSts"
+#define PAL_TEST_STATUS_FILE_DATA_MAX_SIZE 128
+
+void * g_palTestNetworkInterface = NULL;
+void * g_palTestTLSInterfaceCTX = NULL;
+
+
+pal_args_t g_args; // defiend as global so it could persist 
+                   // during task execution on FreeRTOS
+
+#ifdef DEBUG
+#define	PAL_TESTS_LOG_LEVEL ((uint8_t)((TRACE_MASK_LEVEL & TRACE_ACTIVE_LEVEL_ALL) | (TRACE_MASK_CONFIG & TRACE_CARRIAGE_RETURN)))
+#else
+#define	PAL_TESTS_LOG_LEVEL ((uint8_t)((TRACE_MASK_LEVEL & TRACE_ACTIVE_LEVEL_ERROR) | (TRACE_MASK_CONFIG & TRACE_CARRIAGE_RETURN)))
+#endif
+
+
+palTestsStatusData_t palTestStatus = {-1,-1,-1,0,0,0};
+
+
+palStatus_t getPalTestStatus(void)
+{
+    palStatus_t status = PAL_SUCCESS, status2 = PAL_SUCCESS;
+    char filePath[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    palFileDescriptor_t fd = 0;
+    size_t dataSizeWritten = 0;
+    char data[128] = {0};
+  
+
+    status = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, filePath);
+    if (PAL_SUCCESS == status) 
+    {
+        strncat(filePath,PAL_TEST_STATUS_FILE_LOCATION,PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
+        status = pal_fsFopen(filePath, PAL_FS_FLAG_READONLY, &fd);
+         if (PAL_SUCCESS == status)
+         {
+
+             status =  pal_fsFread(&fd, (void *)data, PAL_TEST_STATUS_FILE_DATA_MAX_SIZE, &dataSizeWritten);
+             if ((PAL_SUCCESS == status) && (dataSizeWritten > 0))
+             {
+                 printf("reading DATA into test\r\n");
+                 sscanf(data,"%i %i %i %llu %llu %llu", &palTestStatus.module, &palTestStatus.test, &palTestStatus.inner, &palTestStatus.numOfTestsFailures, &palTestStatus.numberOfTests, &palTestStatus.numberOfIgnoredTests);
+             }
+             status2 = pal_fsFclose(&fd);
+             if (PAL_SUCCESS != status2) 
+             {
+                 PAL_LOG(ERR,"Failed to close data file of test status after read");
+             }
+             status2 = pal_fsUnlink(filePath);
+             if (PAL_SUCCESS != status2) 
+             {
+                 PAL_LOG(ERR,"Failed to delete data file of test status after read");
+             }
+         }
+        else if (PAL_ERR_FS_NO_FILE == status) {
+            //this is not an error... in most times there will be no file
+            status = PAL_SUCCESS;
+        }
+    }
+
+    PAL_LOG(DBG,"*********************************\n"
+    		"** Test status: 				**\n"
+    		"** Module %d    				**\n"
+    		"** Test %d      				**\n"
+    		"** Inner %d     				**\n"
+    		"** num of tests failures %llu	**\n"
+    		"** num of tests %llu     		**\n"
+    		"** num of ignored tests %llu   **\n"
+    		"*********************************\n",
+			palTestStatus.module, palTestStatus.test, palTestStatus.inner,
+			palTestStatus.numOfTestsFailures, palTestStatus.numberOfTests,
+			palTestStatus.numberOfIgnoredTests);
+
+    return status;
+}
+
+void updatePalTestStatusAfterReboot(void)
+{
+	if (palTestStatus.numberOfTests > 0)
+	{
+		Unity.TestFailures = palTestStatus.numOfTestsFailures;
+		Unity.NumberOfTests = palTestStatus.numberOfTests;
+		Unity.CurrentTestIgnored =palTestStatus.numberOfIgnoredTests;
+		PAL_LOG(DBG,"Unity number of tests was updated\r\n");
+	}
+}
+
+
+palStatus_t setPalTestStatus(palTestsStatusData_t palRebootTestStatus)
+{
+    palStatus_t status = PAL_SUCCESS, status2 = PAL_SUCCESS;;
+    char filePath[PAL_MAX_FILE_AND_FOLDER_LENGTH] = {0};
+    palFileDescriptor_t fd = 0;
+    size_t dataSizeWritten = 0;
+    char data[PAL_TEST_STATUS_FILE_DATA_MAX_SIZE] = {0};
+    
+
+    status = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY, PAL_MAX_FILE_AND_FOLDER_LENGTH, filePath);
+    if (PAL_SUCCESS == status) 
+    {
+        strncat(filePath,PAL_TEST_STATUS_FILE_LOCATION,PAL_MAX_FILE_AND_FOLDER_LENGTH - strlen(filePath));
+        status = pal_fsFopen(filePath, PAL_FS_FLAG_READWRITETRUNC, &fd);
+         if (PAL_SUCCESS == status)
+         {
+        	 snprintf((char *)data,PAL_TEST_STATUS_FILE_DATA_MAX_SIZE, "%d %d %d %llu %llu %llu ", palRebootTestStatus.module, palRebootTestStatus.test, palRebootTestStatus.inner, palRebootTestStatus.numOfTestsFailures, palRebootTestStatus.numberOfTests, palRebootTestStatus.numberOfIgnoredTests);
+        	 status =  pal_fsFwrite(&fd, (void *)data, PAL_TEST_STATUS_FILE_DATA_MAX_SIZE, &dataSizeWritten);
+             pal_fsFclose(&fd);
+             if (PAL_SUCCESS != status2) 
+             {
+                 PAL_LOG(ERR,"Failed to close data file of test status after write");
+             }
+         }
+    }
+    return status;
+}
+
+
+palStatus_t palTestReboot(palTestModules_t module ,palTestSOTPTests_t test )
+{
+    palStatus_t status = PAL_SUCCESS;
+	palTestsStatusData_t palRebootTestStatus;
+	palRebootTestStatus.module = module;
+    palRebootTestStatus.test = test;
+    palRebootTestStatus.inner = 1;
+    palRebootTestStatus.numberOfTests = Unity.NumberOfTests;
+    palRebootTestStatus.numOfTestsFailures = Unity.TestFailures;
+    palRebootTestStatus.numberOfIgnoredTests = Unity.CurrentTestIgnored;
+
+    status = setPalTestStatus(palRebootTestStatus);
+    if (PAL_SUCCESS != status)
+    {
+        PAL_LOG(ERR,"Failed to set test status before reboot");
+    }
+    else
+    {
+		pal_osReboot();
+    }
+    return status;
+}
+
+
+
+
+
+void TEST_pal_all_GROUPS_RUNNER(void)
+{
+    PRINT_MEMORY_STATS;
+    switch (palTestStatus.module) // fall through is in design
+    {
+        case -1:
+            //TEST_pal_sanity_GROUP_RUNNER(); // always run this at least once
+        case PAL_TEST_MODULE_SOTP:
+            PRINT_MEMORY_STATS;
+            /**
+             *  CAUTION:THIS TEST MUDOLE REBOOTS THE SYSTEM
+             *  THIS TEST MUST BE 1ST!!!!!
+             *  DO NOT MOVE THIS TEST!!!!!
+            */
+            #ifndef PAL_SKIP_TEST_MODULE_SOTP
+                TEST_pal_SOTP_GROUP_RUNNER();
+            #endif
+        case PAL_TEST_MODULE_RTOS:
+            PRINT_MEMORY_STATS;
+            #ifndef PAL_SKIP_TEST_MODULE_RTOS
+                TEST_pal_rtos_GROUP_RUNNER();
+            #endif
+        case PAL_TEST_MODULE_SOCKET:
+            PRINT_MEMORY_STATS;
+            #ifndef PAL_SKIP_TEST_MODULE_NETWORK
+                TEST_pal_socket_GROUP_RUNNER();
+            #endif
+        case PAL_TEST_MODULE_CRYPTO:
+            PRINT_MEMORY_STATS;
+            #ifndef PAL_SKIP_TEST_MODULE_CRYPTO
+                TEST_pal_crypto_GROUP_RUNNER();
+            #endif
+        case PAL_TEST_MODULE_FILESYSTEM:
+            PRINT_MEMORY_STATS;
+            #ifndef PAL_SKIP_TEST_MODULE_FILESYSTEM
+                TEST_pal_fileSystem_GROUP_RUNNER();
+            #endif
+        case PAL_TEST_MODULE_UPDATE:
+            PRINT_MEMORY_STATS;
+            #ifndef PAL_SKIP_TEST_MODULE_UPDATE
+                TEST_pal_update_GROUP_RUNNER();
+            #endif
+        case PAL_TEST_MODULE_INTERNALFLASH:
+            PRINT_MEMORY_STATS;
+            #ifndef PAL_SKIP_TEST_MODULE_INTERNALFLASH
+                TEST_pal_internalFlash_GROUP_RUNNER();
+            #endif
+        case PAL_TEST_MODULE_TLS:
+            PRINT_MEMORY_STATS;
+            #ifndef PAL_SKIP_TEST_MODULE_TLS
+                TEST_pal_tls_GROUP_RUNNER();
+            #endif
+            PRINT_MEMORY_STATS;
+            break;
+        default:
+            PAL_PRINTF("this should not happen!!! Error Error Error");
+    }
+}
+
+
+
+void palTestMain(palTestModules_t modules,void* network)
+{
+	const char * myargv[] = {"app","-v"};
+    g_palTestNetworkInterface = network; 
+    g_palTestTLSInterfaceCTX = network;
+	mbed_trace_init();
+	mbed_trace_config_set(PAL_TESTS_LOG_LEVEL);
+    palStatus_t getTestStatusReturnValue = getPalTestStatus();
+    if (PAL_SUCCESS != getTestStatusReturnValue) 
+    {
+        PAL_LOG(ERR,"%s: Failed to get current status of tests 0x%" PRIu32 "\r\n",__FUNCTION__,getTestStatusReturnValue);
+    }
+
+    UnityPrint("*****PAL_TEST_START*****");
+    UNITY_PRINT_EOL();
+    switch (modules) 
+    {
+        case PAL_TEST_MODULE_ALL:
+        {
+	        UnityMain(sizeof(myargv) / sizeof(myargv[0]), myargv, TEST_pal_all_GROUPS_RUNNER);
+			break;
+        }
+        case PAL_TEST_MODULE_SOTP:
+        {
+            UnityMain(sizeof(myargv) / sizeof(myargv[0]), myargv, TEST_pal_SOTP_GROUP_RUNNER);
+            break;
+        }
+
+        case PAL_TEST_MODULE_RTOS:
+        {
+            UnityMain(sizeof(myargv) / sizeof(myargv[0]), myargv, TEST_pal_rtos_GROUP_RUNNER);
+            break;
+        }
+
+        case PAL_TEST_MODULE_SOCKET:
+        {
+            UnityMain(sizeof(myargv)/ sizeof(myargv[0]), myargv, TEST_pal_socket_GROUP_RUNNER);
+            break;
+        }
+
+        case PAL_TEST_MODULE_CRYPTO:
+        {
+            UnityMain(sizeof(myargv) / sizeof(myargv[0]), myargv, TEST_pal_crypto_GROUP_RUNNER);
+            break;
+        }
+
+        case PAL_TEST_MODULE_FILESYSTEM:
+        {
+            UnityMain(sizeof(myargv) / sizeof(myargv[0]), myargv, TEST_pal_fileSystem_GROUP_RUNNER);
+            break;
+        }
+
+        case PAL_TEST_MODULE_UPDATE:
+        {
+            UnityMain(sizeof(myargv) / sizeof(myargv[0]), myargv, TEST_pal_update_GROUP_RUNNER);
+            break;
+        }
+
+        case PAL_TEST_MODULE_INTERNALFLASH:
+        {
+            UnityMain(sizeof(myargv) / sizeof(myargv[0]), myargv, TEST_pal_internalFlash_GROUP_RUNNER);
+            break;
+        }
+
+        case PAL_TEST_MODULE_TLS:
+        {
+            UnityMain(sizeof(myargv) / sizeof(myargv[0]), myargv, TEST_pal_tls_GROUP_RUNNER);
+            break;
+        }
+        
+        case PAL_TEST_MODULE_SANITY:
+        {
+            UnityMain(sizeof(myargv) / sizeof(myargv[0]), myargv, TEST_pal_sanity_GROUP_RUNNER);
+            break;
+        }
+
+        default:
+        {
+            UnityPrint("*****ERROR WRONG TEST SUITE WAS CHOOSEN*****");                
+            break;
+        }
+
+    }
+    UnityPrint("*****PAL_TEST_END*****");
+    UNITY_PRINT_EOL();
+
+    mbed_trace_free();
+
+}
+
+void palAllTestMain(void* network)
+{
+    palTestMain(PAL_TEST_MODULE_ALL, network);
+}
+
+void palFileSystemTestMain(void* network)
+{
+    palTestMain(PAL_TEST_MODULE_FILESYSTEM, network);
+}
+
+void palNetworkTestMain(void* network)
+{
+   palTestMain(PAL_TEST_MODULE_SOCKET, network); 
+}
+
+void palCryptoTestMain(void* network)
+{
+   palTestMain(PAL_TEST_MODULE_CRYPTO, network); 
+}
+
+void palRTOSTestMain(void* network)
+{
+   palTestMain(PAL_TEST_MODULE_RTOS, network); 
+}
+
+void palStorageTestMain(void* network)
+{
+   palTestMain(PAL_TEST_MODULE_INTERNALFLASH, network); 
+}
+
+void palTLSTestMain(void* network)
+{
+   palTestMain(PAL_TEST_MODULE_TLS, network); 
+}
+
+void palUpdateTestMain(void* network)
+{
+   palTestMain(PAL_TEST_MODULE_UPDATE, network); 
+}
+
+void palSOTPTestMain(void* network)
+{
+    palTestMain(PAL_TEST_MODULE_SOTP, network); 
+}
+
+void palSanityTestMain(void* network)
+{
+     palTestMain(PAL_TEST_MODULE_SANITY, network); 
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/PAL_Modules/test_runners.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#ifndef MBED_CLIENT_PAL_TEST_RUNNERS_H_
+#define MBED_CLIENT_PAL_TEST_RUNNERS_H_
+#include "pal.h"
+#include "pal_BSP.h"
+
+
+
+#ifndef PAL_TEST_RTOS
+#define PAL_TEST_RTOS 0
+#endif // PAL_TEST_RTOS
+
+#ifndef PAL_TEST_NETWORK
+#define PAL_TEST_NETWORK 0
+#endif // PAL_TEST_NETWORK
+
+#ifndef PAL_TEST_TLS
+#define PAL_TEST_TLS 0
+#endif // PAL_TEST_TLS
+
+#ifndef PAL_TEST_CRYPTO
+#define PAL_TEST_CRYPTO 0
+#endif // PAL_TEST_CRYPTO
+
+#ifndef PAL_TEST_FS
+#define PAL_TEST_FS 0
+#endif // PAL_TEST_FS
+
+#ifndef PAL_TEST_UPDATE
+#define PAL_TEST_UPDATE 0
+#endif // PAL_TEST_UPDATE
+
+#ifndef PAL_TEST_FLASH
+#define PAL_TEST_FLASH 1
+#endif // PAL_TEST_FLASH
+
+#ifndef TEST_PRINTF
+    #define TEST_PRINTF(ARGS...) PAL_PRINTF(ARGS)
+#endif //TEST_PRINTF
+
+#ifdef PAL_LINUX
+#define PAL_TEST_THREAD_STACK_SIZE 16*1024*sizeof(uint32_t)
+#else
+#define PAL_TEST_THREAD_STACK_SIZE 512*sizeof(uint32_t)
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef void (*testMain_t)(pal_args_t *);
+int test_main(int argc, char * argv[], testMain_t func);
+
+
+
+void TEST_pal_rtos_GROUP_RUNNER(void);
+
+void TEST_pal_socket_GROUP_RUNNER(void);
+
+void TEST_pal_tls_GROUP_RUNNER(void);
+
+void TEST_pal_crypto_GROUP_RUNNER(void);
+
+void TEST_pal_fileSystem_GROUP_RUNNER(void);
+
+void TEST_pal_update_GROUP_RUNNER(void);
+
+void TEST_pal_internalFlash_GROUP_RUNNER(void);
+
+void TEST_pal_SOTP_GROUP_RUNNER(void);
+
+void TEST_pal_sanity_GROUP_RUNNER(void);
+
+
+typedef struct _palTestsStatusData_t
+{
+    int module;
+    int test;
+    int inner;
+    unsigned long long  numberOfTests;
+    unsigned long long  numOfTestsFailures;
+    unsigned long long  numberOfIgnoredTests;
+}palTestsStatusData_t;
+
+
+typedef enum _palTestModules_t
+{
+    PAL_TEST_MODULE_START,
+    PAL_TEST_MODULE_RTOS = PAL_TEST_MODULE_START,
+    PAL_TEST_MODULE_SOCKET,
+    PAL_TEST_MODULE_TLS,
+    PAL_TEST_MODULE_CRYPTO,
+    PAL_TEST_MODULE_FILESYSTEM,
+    PAL_TEST_MODULE_UPDATE,
+    PAL_TEST_MODULE_INTERNALFLASH,
+    PAL_TEST_MODULE_SOTP,
+    PAL_TEST_MODULE_SANITY,
+    PAL_TEST_MODULE_ALL,
+    PAL_TEST_MODULE_END
+}palTestModules_t;
+
+typedef enum _palTestSOTPTests_t
+{
+    PAL_TEST_SOTP_TEST_START,
+    PAL_TEST_SOTP_TEST_SW_HW_ROT = PAL_TEST_SOTP_TEST_START,
+    PAL_TEST_SOTP_TEST_TIME_INIT,
+    PAL_TEST_SOTP_TEST_RANDOM,
+    PAL_TEST_SOTP_TEST_END
+}palTestSOTPTests_t;
+
+palStatus_t setPalTestStatus(palTestsStatusData_t palRebootTestStatus);
+
+palStatus_t getPalTestStatus(void);
+
+palStatus_t palTestReboot(palTestModules_t module ,palTestSOTPTests_t test );
+
+void updatePalTestStatusAfterReboot(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBED_CLIENT_PAL_TEST_RUNNERS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Sotp/security/pal_security_test_main.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal_BSP.h"
+#include "stdio.h"
+
+void palSOTPTestMain(void* network);
+
+//create a public wapper to this & reduce this to one line 
+int main(int argc, char * argv[])
+{
+    bspStatus_t status = BSP_SUCCESS;
+    void* context = NULL;
+    status = initPlatform(&context);
+    if (BSP_SUCCESS == status) 
+    {
+        palSOTPTestMain(context);      
+    }
+    return status;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/Crypto/pal_crypto_test_main.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal_BSP.h"
+#include "stdio.h"
+
+void palCryptoTestMain(void* network);
+
+//create a public wapper to this & reduce this to one line 
+int main(int argc, char * argv[])
+{
+    bspStatus_t status = BSP_SUCCESS;
+    void* context = NULL;
+    status = initPlatform(&context);
+    if (BSP_SUCCESS == status) 
+    {
+        palCryptoTestMain(context);      
+    }
+    return status;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/FileSystem/pal_FileSystem_test_main.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#include "pal_BSP.h"
+#include "stdio.h"
+
+void palFileSystemTestMain(void* network);
+
+//create a public wapper to this & reduce this to one line 
+int main(int argc, char * argv[])
+{
+    bspStatus_t status = BSP_SUCCESS;
+    void* context = NULL;
+    status = initPlatform(&context);
+    if (BSP_SUCCESS == status) 
+    {
+        palFileSystemTestMain(context);      
+    }
+    return status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/Full_pal/pal_all_test_main.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+
+#include "pal_BSP.h"
+#include "stdio.h"
+
+void palAllTestMain(void* network);
+
+//create a public wapper to this & reduce this to one line 
+int main(int argc, char * argv[])
+{
+    bspStatus_t status = BSP_SUCCESS;
+    void* context = NULL;
+    status = initPlatform(&context);
+    if (BSP_SUCCESS == status) 
+    {
+        palAllTestMain(context);      
+    }
+    return status;
+}
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/Networking/pal_Networking_test_main.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal_BSP.h"
+#include "stdio.h"
+
+void palNetworkTestMain(void* network);
+
+//create a public wapper to this & reduce this to one line 
+int main(int argc, char * argv[])
+{
+    bspStatus_t status = BSP_SUCCESS;
+    void* context = NULL;
+    status = initPlatform(&context);
+    if (BSP_SUCCESS == status) 
+    {
+        palNetworkTestMain(context);      
+    }
+    return status;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/RTOS/pal_rtos_test_main.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal_BSP.h"
+#include "stdio.h"
+
+void palRTOSTestMain(void* network);
+
+//create a public wapper to this & reduce this to one line 
+int main(int argc, char * argv[])
+{
+    bspStatus_t status = BSP_SUCCESS;
+    void* context = NULL;
+    status = initPlatform(&context);
+    if (BSP_SUCCESS == status) 
+    {
+        palRTOSTestMain(context);      
+    }
+    return status;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/Sanity/pal_sanity_test_main.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal_BSP.h"
+#include "stdio.h"
+
+void palSanityTestMain(void* network);
+
+//create a public wapper to this & reduce this to one line 
+int main(int argc, char * argv[])
+{
+    bspStatus_t status = BSP_SUCCESS;
+    void* context = NULL;
+    status = initPlatform(&context);
+    if (BSP_SUCCESS == status) 
+    {
+        palSanityTestMain(context);      
+    }
+    return status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/Storage/pal_Storage_test_main.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal_BSP.h"
+#include "stdio.h"
+
+void palStorageTestMain(void* network);
+
+//create a public wapper to this & reduce this to one line 
+int main(int argc, char * argv[])
+{
+    bspStatus_t status = BSP_SUCCESS;
+    void* context = NULL;
+    status = initPlatform(&context);
+    if (BSP_SUCCESS == status) 
+    {
+        palStorageTestMain(context);      
+    }
+    return status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/TLS/pal_TLS_test_main.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+ 
+#include "pal_BSP.h"
+#include "stdio.h"
+
+ void palTLSTestMain(void* network);
+
+//create a public wapper to this & reduce this to one line 
+int main(int argc, char * argv[])
+{
+    bspStatus_t status = BSP_SUCCESS;
+    void* context = NULL;
+    status = initPlatform(&context);
+    if (BSP_SUCCESS == status) 
+    {
+        palTLSTestMain(context);      
+    }
+    return status;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/Update/pal_Update_test_main.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal_BSP.h"
+#include "stdio.h"
+
+ void palUpdateTestMain(void* network);
+
+//create a public wapper to this & reduce this to one line 
+int main(int argc, char * argv[])
+{
+    bspStatus_t status = BSP_SUCCESS;
+    void* context = NULL;
+    status = initPlatform(&context);
+    if (BSP_SUCCESS == status) 
+    {
+        palUpdateTestMain(context);      
+    }
+    return status;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/Unitest/a_pal_reformat/pal_a_pal_reformat_test_main.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+
+#include "pal_BSP.h"
+#include "stdio.h"
+#include "PlatIncludes.h"
+
+void palSanityTestMain(void* network);
+
+
+//create a public wapper to this & reduce this to one line 
+int main(int argc, char * argv[])
+{
+    bspStatus_t status = BSP_SUCCESS;
+    int err =0;
+    void* context = NULL;
+    status = initPlatformReformat(&context);
+    if (BSP_SUCCESS == status)
+    {
+    	palSanityTestMain(context);
+    }
+    return status;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/TESTS/pal_make.py	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,19 @@
+import sys
+import subprocess
+import re 
+
+pal_warn = re.compile("Warning.*pal")
+pal_dont_treat_as_warn = re.compile("Warning.*PAL_INSECURE")
+
+proc = subprocess.Popen(sys.argv[1].split(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+for line in proc.stdout:
+    print line
+    if len(pal_warn.findall(line)) > 0:
+	    if not len(pal_dont_treat_as_warn.findall(line)) > 0:
+			raise Exception("No Warnings Allowed in Pal")
+proc.wait()
+print "mbed compile returned {}".format(proc.returncode)
+if not proc.returncode == 0:
+    raise Exception("mbed compile failed")
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,4 @@
+examples/*
+test/*
+extras/fixture/test/*
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/colour_prompt.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,115 @@
+# ==========================================
+#   Unity Project - A Test Framework for C
+#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+#   [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+if RUBY_PLATFORM =~/(win|w)32$/
+	begin
+		require 'Win32API'
+	rescue LoadError
+		puts "ERROR! \"Win32API\" library not found"
+		puts "\"Win32API\" is required for colour on a windows machine"
+		puts "  try => \"gem install Win32API\" on the command line"
+		puts
+	end
+	# puts
+  # puts 'Windows Environment Detected...'
+	# puts 'Win32API Library Found.'
+	# puts
+end
+
+class ColourCommandLine
+  def initialize
+    if RUBY_PLATFORM =~/(win|w)32$/
+      get_std_handle = Win32API.new("kernel32", "GetStdHandle", ['L'], 'L')
+      @set_console_txt_attrb =
+        Win32API.new("kernel32","SetConsoleTextAttribute",['L','N'], 'I')
+      @hout = get_std_handle.call(-11)
+    end
+  end
+
+  def change_to(new_colour)
+    if RUBY_PLATFORM =~/(win|w)32$/
+      @set_console_txt_attrb.call(@hout,self.win32_colour(new_colour))
+    else
+	  	"\033[30;#{posix_colour(new_colour)};22m"
+	 	end
+  end
+
+  def win32_colour(colour)
+    case colour
+      when :black then 0
+      when :dark_blue then 1
+      when :dark_green then 2
+      when :dark_cyan then 3
+      when :dark_red then 4
+      when :dark_purple then 5
+      when :dark_yellow, :narrative then 6
+      when :default_white, :default, :dark_white then 7
+      when :silver then 8
+      when :blue then 9
+      when :green, :success then 10
+      when :cyan, :output then 11
+      when :red, :failure then 12
+      when :purple then 13
+      when :yellow then 14
+      when :white then 15
+      else
+        0
+    end
+  end
+
+	def posix_colour(colour)
+    # ANSI Escape Codes - Foreground colors
+    # | Code | Color                     |
+    # | 39   | Default foreground color  |
+    # | 30   | Black                     |
+    # | 31   | Red                       |
+    # | 32   | Green                     |
+    # | 33   | Yellow                    |
+    # | 34   | Blue                      |
+    # | 35   | Magenta                   |
+    # | 36   | Cyan                      |
+    # | 37   | Light gray                |
+    # | 90   | Dark gray                 |
+    # | 91   | Light red                 |
+    # | 92   | Light green               |
+    # | 93   | Light yellow              |
+    # | 94   | Light blue                |
+    # | 95   | Light magenta             |
+    # | 96   | Light cyan                |
+    # | 97   | White                     |
+
+	  case colour
+      when :black then 30
+      when :red, :failure then 31
+      when :green, :success then 32
+			when :yellow then 33
+      when :blue, :narrative then 34
+      when :purple, :magenta then 35
+      when :cyan, :output then 36
+      when :white, :default_white then 37
+      when :default then 39
+      else
+        39
+    end
+  end
+
+  def out_c(mode, colour, str)
+    case RUBY_PLATFORM
+			when /(win|w)32$/
+			  change_to(colour)
+				 $stdout.puts str if mode == :puts
+				 $stdout.print str if mode == :print
+			  change_to(:default_white)
+			else
+				$stdout.puts("#{change_to(colour)}#{str}\033[0m") if mode == :puts
+				$stdout.print("#{change_to(colour)}#{str}\033[0m") if mode == :print
+		end
+  end
+end # ColourCommandLine
+
+def colour_puts(role,str)  ColourCommandLine.new.out_c(:puts, role, str)  end
+def colour_print(role,str) ColourCommandLine.new.out_c(:print, role, str) end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/colour_reporter.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,39 @@
+# ==========================================
+#   Unity Project - A Test Framework for C
+#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+#   [Released under MIT License. Please refer to license.txt for details]
+# ========================================== 
+
+require "#{File.expand_path(File.dirname(__FILE__))}/colour_prompt"
+
+$colour_output = true
+
+def report(message)
+  if not $colour_output
+    $stdout.puts(message)
+  else
+    message = message.join('\n') if (message.class == Array)
+    message.each_line do |line|
+      line.chomp!
+      colour = case(line)
+        when /(?:total\s+)?tests:?\s+(\d+)\s+(?:total\s+)?failures:?\s+\d+\s+Ignored:?/i
+          ($1.to_i == 0) ? :green : :red
+        when /PASS/
+          :green
+        when /^OK$/
+          :green
+        when /(?:FAIL|ERROR)/
+          :red
+        when /IGNORE/
+          :yellow
+        when /^(?:Creating|Compiling|Linking)/
+          :white
+        else
+          :silver
+      end
+      colour_puts(colour, line)
+    end
+  end
+  $stdout.flush
+  $stderr.flush
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/generate_module.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,202 @@
+# ==========================================
+#   Unity Project - A Test Framework for C
+#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+#   [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+# This script creates all the files with start code necessary for a new module.
+# A simple module only requires a source file, header file, and test file.
+# Triad modules require a source, header, and test file for each triad type (like model, conductor, and hardware).
+
+require 'rubygems'
+require 'fileutils'
+
+HERE = File.expand_path(File.dirname(__FILE__)) + '/'
+
+#help text when requested
+HELP_TEXT = [ "\nGENERATE MODULE\n-------- ------",
+              "\nUsage: ruby generate_module [options] module_name",
+              "  -i\"include\" sets the path to output headers to 'include' (DEFAULT ../src)",
+              "  -s\"../src\"  sets the path to output source to '../src'   (DEFAULT ../src)",
+              "  -t\"C:/test\" sets the path to output source to 'C:/test'  (DEFAULT ../test)",
+              "  -p\"MCH\"     sets the output pattern to MCH.",
+              "              dh  - driver hardware.",
+              "              dih - driver interrupt hardware.",
+              "              mch - model conductor hardware.",
+              "              mvp - model view presenter.",
+              "              src - just a single source module. (DEFAULT)",
+              "  -d          destroy module instead of creating it.",
+              "  -u          update subversion too (requires subversion command line)",
+              "  -y\"my.yml\"  selects a different yaml config file for module generation",
+              "" ].join("\n")
+
+#Built in patterns
+PATTERNS = { 'src' => {''         => { :inc => [] } },
+             'dh'  => {'Driver'   => { :inc => ['%1$sHardware.h'] },
+                       'Hardware' => { :inc => [] }
+                      },
+             'dih' => {'Driver'   => { :inc => ['%1$sHardware.h', '%1$sInterrupt.h'] },
+                       'Interrupt'=> { :inc => ['%1$sHardware.h'] },
+                       'Hardware' => { :inc => [] }
+                      },
+             'mch' => {'Model'    => { :inc => [] },
+                       'Conductor'=> { :inc => ['%1$sModel.h', '%1$sHardware.h'] },
+                       'Hardware' => { :inc => [] }
+                      },
+             'mvp' => {'Model'    => { :inc => [] },
+                       'Presenter'=> { :inc => ['%1$sModel.h', '%1$sView.h'] },
+                       'View'     => { :inc => [] }
+                      }
+           }
+
+#TEMPLATE_TST
+TEMPLATE_TST = %q[#include "unity.h"
+%2$s#include "%1$s.h"
+
+void setUp(void)
+{
+}
+
+void tearDown(void)
+{
+}
+
+void test_%1$s_NeedToImplement(void)
+{
+    TEST_IGNORE_MESSAGE("Need to Implement %1$s");
+}
+]
+
+#TEMPLATE_SRC
+TEMPLATE_SRC = %q[%2$s#include "%1$s.h"
+]
+
+#TEMPLATE_INC
+TEMPLATE_INC = %q[#ifndef _%3$s_H
+#define _%3$s_H%2$s
+
+#endif // _%3$s_H
+]
+
+# Parse the command line parameters.
+ARGV.each do |arg|
+  case(arg)
+    when /^-d/      then @destroy = true
+    when /^-u/      then @update_svn = true
+    when /^-p(\w+)/ then @pattern = $1
+    when /^-s(.+)/  then @path_src = $1
+    when /^-i(.+)/  then @path_inc = $1
+    when /^-t(.+)/  then @path_tst = $1
+    when /^-y(.+)/  then @yaml_config = $1
+    when /^(\w+)/
+      raise "ERROR: You can't have more than one Module name specified!" unless @module_name.nil?
+      @module_name = arg
+    when /^-(h|-help)/
+      puts HELP_TEXT
+      exit
+    else
+      raise "ERROR: Unknown option specified '#{arg}'"
+  end
+end
+raise "ERROR: You must have a Module name specified! (use option -h for help)" if @module_name.nil?
+
+#load yaml file if one was requested
+if @yaml_config
+  require 'yaml'
+  cfg = YAML.load_file(HERE + @yaml_config)[:generate_module]
+  @path_src     = cfg[:defaults][:path_src]   if @path_src.nil?
+  @path_inc     = cfg[:defaults][:path_inc]   if @path_inc.nil?
+  @path_tst     = cfg[:defaults][:path_tst]   if @path_tst.nil?
+  @update_svn   = cfg[:defaults][:update_svn] if @update_svn.nil?
+  @extra_inc    = cfg[:includes]
+  @boilerplates = cfg[:boilerplates]
+else
+  @boilerplates = {}
+end
+
+# Create default file paths if none were provided
+@path_src = HERE + "../src/"  if @path_src.nil?
+@path_inc = @path_src         if @path_inc.nil?
+@path_tst = HERE + "../test/" if @path_tst.nil?
+@path_src += '/'              unless (@path_src[-1] == 47)
+@path_inc += '/'              unless (@path_inc[-1] == 47)
+@path_tst += '/'              unless (@path_tst[-1] == 47)
+@pattern  = 'src'             if @pattern.nil?
+@includes = { :src => [], :inc => [], :tst => [] }
+@includes.merge!(@extra_inc) unless @extra_inc.nil?
+
+#create triad definition
+TRIAD = [ { :ext => '.c', :path => @path_src,        :template => TEMPLATE_SRC, :inc => :src, :boilerplate => @boilerplates[:src] },
+          { :ext => '.h', :path => @path_inc,        :template => TEMPLATE_INC, :inc => :inc, :boilerplate => @boilerplates[:inc] },
+          { :ext => '.c', :path => @path_tst+'Test', :template => TEMPLATE_TST, :inc => :tst, :boilerplate => @boilerplates[:tst] },
+        ]
+
+#prepare the pattern for use
+@patterns = PATTERNS[@pattern.downcase]
+raise "ERROR: The design pattern specified isn't one that I recognize!" if @patterns.nil?
+
+# Assemble the path/names of the files we need to work with.
+files = []
+TRIAD.each do |triad|
+  @patterns.each_pair do |pattern_file, pattern_traits|
+    files << {
+      :path => "#{triad[:path]}#{@module_name}#{pattern_file}#{triad[:ext]}",
+      :name => "#{@module_name}#{pattern_file}",
+      :template => triad[:template],
+      :boilerplate => triad[:boilerplate],
+      :includes => case(triad[:inc])
+                     when :src then @includes[:src] | pattern_traits[:inc].map{|f| f % [@module_name]}
+                     when :inc then @includes[:inc]
+                     when :tst then @includes[:tst] | pattern_traits[:inc].map{|f| "Mock#{f}"% [@module_name]}
+                   end
+    }
+  end
+end
+
+# destroy files if that was what was requested
+if @destroy
+  files.each do |filespec|
+    file = filespec[:path]
+    if File.exist?(file)
+      if @update_svn
+        `svn delete \"#{file}\" --force`
+        puts "File #{file} deleted and removed from source control"
+      else
+        FileUtils.remove(file)
+        puts "File #{file} deleted"
+      end
+    else
+      puts "File #{file} does not exist so cannot be removed."
+    end
+  end
+  puts "Destroy Complete"
+  exit
+end
+
+#Abort if any module already exists
+files.each do |file|
+  raise "ERROR: File #{file[:name]} already exists. Exiting." if File.exist?(file[:path])
+end
+
+# Create Source Modules
+files.each_with_index do |file, i|
+  File.open(file[:path], 'w') do |f|
+    f.write(file[:boilerplate] % [file[:name]]) unless file[:boilerplate].nil?
+    f.write(file[:template] % [ file[:name],
+                                file[:includes].map{|f| "#include \"#{f}\"\n"}.join,
+                                file[:name].upcase ]
+           )
+  end
+  if (@update_svn)
+    `svn add \"#{file[:path]}\"`
+    if $?.exitstatus == 0
+      puts "File #{file[:path]} created and added to source control"
+    else
+      puts "File #{file[:path]} created but FAILED adding to source control!"
+    end
+  else
+    puts "File #{file[:path]} created"
+  end
+end
+
+puts 'Generate Complete'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/generate_test_runner.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,391 @@
+# ==========================================
+#   Unity Project - A Test Framework for C
+#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+#   [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+$QUICK_RUBY_VERSION = RUBY_VERSION.split('.').inject(0){|vv,v| vv * 100 + v.to_i }
+File.expand_path(File.join(File.dirname(__FILE__),'colour_prompt'))
+
+class UnityTestRunnerGenerator
+
+  def initialize(options = nil)
+    @options = UnityTestRunnerGenerator.default_options
+    case(options)
+      when NilClass then @options
+      when String   then @options.merge!(UnityTestRunnerGenerator.grab_config(options))
+      when Hash     then @options.merge!(options)
+      else          raise "If you specify arguments, it should be a filename or a hash of options"
+    end
+    require "#{File.expand_path(File.dirname(__FILE__))}/type_sanitizer"
+  end
+
+  def self.default_options
+    {
+      :includes      => [],
+      :plugins       => [],
+      :framework     => :unity,
+      :test_prefix   => "test|spec|should",
+      :setup_name    => "setUp",
+      :teardown_name => "tearDown",
+      :main_name     => "main",
+    }
+  end
+
+  def self.grab_config(config_file)
+    options = self.default_options
+    unless (config_file.nil? or config_file.empty?)
+      require 'yaml'
+      yaml_guts = YAML.load_file(config_file)
+      options.merge!(yaml_guts[:unity] || yaml_guts[:cmock])
+      raise "No :unity or :cmock section found in #{config_file}" unless options
+    end
+    return(options)
+  end
+
+  def run(input_file, output_file, options=nil)
+    tests = []
+    testfile_includes = []
+    used_mocks = []
+
+    @options.merge!(options) unless options.nil?
+    module_name = File.basename(input_file)
+
+    #pull required data from source file
+    source = File.read(input_file)
+    source = source.force_encoding("ISO-8859-1").encode("utf-8", :replace => nil) if ($QUICK_RUBY_VERSION > 10900)
+    tests               = find_tests(source)
+    headers             = find_includes(source)
+    testfile_includes   = (headers[:local] + headers[:system])
+    used_mocks          = find_mocks(testfile_includes)
+    testfile_includes   = (testfile_includes - used_mocks)
+    testfile_includes.delete_if{|inc| inc =~ /(unity|cmock)/}
+
+    #build runner file
+    generate(input_file, output_file, tests, used_mocks, testfile_includes)
+
+    #determine which files were used to return them
+    all_files_used = [input_file, output_file]
+    all_files_used += testfile_includes.map {|filename| filename + '.c'} unless testfile_includes.empty?
+    all_files_used += @options[:includes] unless @options[:includes].empty?
+    return all_files_used.uniq
+  end
+
+  def generate(input_file, output_file, tests, used_mocks, testfile_includes)
+    File.open(output_file, 'w') do |output|
+      create_header(output, used_mocks, testfile_includes)
+      create_externs(output, tests, used_mocks)
+      create_mock_management(output, used_mocks)
+      create_suite_setup_and_teardown(output)
+      create_reset(output, used_mocks)
+      create_main(output, input_file, tests, used_mocks)
+    end
+
+    if (@options[:header_file] && !@options[:header_file].empty?)
+      File.open(@options[:header_file], 'w') do |output|
+        create_h_file(output, @options[:header_file], tests, testfile_includes, used_mocks)
+      end
+    end
+  end
+
+  def find_tests(source)
+    tests_and_line_numbers = []
+
+    source_scrubbed = source.clone
+    source_scrubbed = source_scrubbed.gsub(/"[^"]*"/, '')      # remove things in strings
+    source_scrubbed = source_scrubbed.gsub(/\/\/.*$/, '')      # remove line comments
+    source_scrubbed = source_scrubbed.gsub(/\/\*.*?\*\//m, '') # remove block comments
+    lines = source_scrubbed.split(/(^\s*\#.*$)                 # Treat preprocessor directives as a logical line
+                              | (;|\{|\}) /x)                  # Match ;, {, and } as end of lines
+
+    lines.each_with_index do |line, index|
+      #find tests
+      if line =~ /^((?:\s*TEST_CASE\s*\(.*?\)\s*)*)\s*void\s+((?:#{@options[:test_prefix]}).*)\s*\(\s*(.*)\s*\)/
+        arguments = $1
+        name = $2
+        call = $3
+        params = $4
+        args = nil
+        if (@options[:use_param_tests] and !arguments.empty?)
+          args = []
+          arguments.scan(/\s*TEST_CASE\s*\((.*)\)\s*$/) {|a| args << a[0]}
+        end
+        tests_and_line_numbers << { :test => name, :args => args, :call => call, :params => params, :line_number => 0 }
+      end
+    end
+    tests_and_line_numbers.uniq! {|v| v[:test] }
+
+    #determine line numbers and create tests to run
+    source_lines = source.split("\n")
+    source_index = 0;
+    tests_and_line_numbers.size.times do |i|
+      source_lines[source_index..-1].each_with_index do |line, index|
+        if (line =~ /#{tests_and_line_numbers[i][:test]}/)
+          source_index += index
+          tests_and_line_numbers[i][:line_number] = source_index + 1
+          break
+        end
+      end
+    end
+
+    return tests_and_line_numbers
+  end
+
+  def find_includes(source)
+
+    #remove comments (block and line, in three steps to ensure correct precedence)
+    source.gsub!(/\/\/(?:.+\/\*|\*(?:$|[^\/])).*$/, '')  # remove line comments that comment out the start of blocks
+    source.gsub!(/\/\*.*?\*\//m, '')                     # remove block comments
+    source.gsub!(/\/\/.*$/, '')                          # remove line comments (all that remain)
+
+    #parse out includes
+    includes = {
+      :local => source.scan(/^\s*#include\s+\"\s*(.+)\.[hH]\s*\"/).flatten,
+      :system => source.scan(/^\s*#include\s+<\s*(.+)\s*>/).flatten.map { |inc| "<#{inc}>" }
+    }
+    return includes
+  end
+
+  def find_mocks(includes)
+    mock_headers = []
+    includes.each do |include_path|
+      include_file = File.basename(include_path)
+      mock_headers << include_path if (include_file =~ /^mock/i)
+    end
+    return mock_headers
+  end
+
+  def create_header(output, mocks, testfile_includes=[])
+    output.puts('/* AUTOGENERATED FILE. DO NOT EDIT. */')
+    create_runtest(output, mocks)
+    output.puts("\n/*=======Automagically Detected Files To Include=====*/")
+    output.puts("#include \"#{@options[:framework].to_s}.h\"")
+    output.puts('#include "cmock.h"') unless (mocks.empty?)
+    output.puts('#include <setjmp.h>')
+    output.puts('#include <stdio.h>')
+    output.puts('#include "CException.h"') if @options[:plugins].include?(:cexception)
+    if (@options[:header_file] && !@options[:header_file].empty?)
+      output.puts("#include \"#{File.basename(@options[:header_file])}\"")
+    else
+      @options[:includes].flatten.uniq.compact.each do |inc|
+        output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}")
+      end
+      testfile_includes.each do |inc|
+        output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}")
+      end
+    end
+    mocks.each do |mock|
+      output.puts("#include \"#{mock.gsub('.h','')}.h\"")
+    end
+    if @options[:enforce_strict_ordering]
+      output.puts('')
+      output.puts('int GlobalExpectCount;')
+      output.puts('int GlobalVerifyOrder;')
+      output.puts('char* GlobalOrderError;')
+    end
+  end
+
+  def create_externs(output, tests, mocks)
+    output.puts("\n/*=======External Functions This Runner Calls=====*/")
+    output.puts("extern void #{@options[:setup_name]}(void);")
+    output.puts("extern void #{@options[:teardown_name]}(void);")
+    tests.each do |test|
+      output.puts("extern void #{test[:test]}(#{test[:call] || 'void'});")
+    end
+    output.puts('')
+  end
+
+  def create_mock_management(output, mock_headers)
+    unless (mock_headers.empty?)
+      output.puts("\n/*=======Mock Management=====*/")
+      output.puts("static void CMock_Init(void)")
+      output.puts("{")
+      if @options[:enforce_strict_ordering]
+        output.puts("  GlobalExpectCount = 0;")
+        output.puts("  GlobalVerifyOrder = 0;")
+        output.puts("  GlobalOrderError = NULL;")
+      end
+      mocks = mock_headers.map {|mock| File.basename(mock)}
+      mocks.each do |mock|
+        mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
+        output.puts("  #{mock_clean}_Init();")
+      end
+      output.puts("}\n")
+
+      output.puts("static void CMock_Verify(void)")
+      output.puts("{")
+      mocks.each do |mock|
+        mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
+        output.puts("  #{mock_clean}_Verify();")
+      end
+      output.puts("}\n")
+
+      output.puts("static void CMock_Destroy(void)")
+      output.puts("{")
+      mocks.each do |mock|
+        mock_clean = TypeSanitizer.sanitize_c_identifier(mock)
+        output.puts("  #{mock_clean}_Destroy();")
+      end
+      output.puts("}\n")
+    end
+  end
+
+  def create_suite_setup_and_teardown(output)
+    unless (@options[:suite_setup].nil?)
+      output.puts("\n/*=======Suite Setup=====*/")
+      output.puts("static int suite_setup(void)")
+      output.puts("{")
+      output.puts(@options[:suite_setup])
+      output.puts("}")
+    end
+    unless (@options[:suite_teardown].nil?)
+      output.puts("\n/*=======Suite Teardown=====*/")
+      output.puts("static int suite_teardown(int num_failures)")
+      output.puts("{")
+      output.puts(@options[:suite_teardown])
+      output.puts("}")
+    end
+  end
+
+  def create_runtest(output, used_mocks)
+    cexception = @options[:plugins].include? :cexception
+    va_args1   = @options[:use_param_tests] ? ', ...' : ''
+    va_args2   = @options[:use_param_tests] ? '__VA_ARGS__' : ''
+    output.puts("\n/*=======Test Runner Used To Run Each Test Below=====*/")
+    output.puts("#define RUN_TEST_NO_ARGS") if @options[:use_param_tests]
+    output.puts("#define RUN_TEST(TestFunc, TestLineNum#{va_args1}) \\")
+    output.puts("{ \\")
+    output.puts("  Unity.CurrentTestName = #TestFunc#{va_args2.empty? ? '' : " \"(\" ##{va_args2} \")\""}; \\")
+    output.puts("  Unity.CurrentTestLineNumber = TestLineNum; \\")
+    output.puts("  Unity.NumberOfTests++; \\")
+    output.puts("  CMock_Init(); \\") unless (used_mocks.empty?)
+    output.puts("  UNITY_CLR_DETAILS(); \\") unless (used_mocks.empty?)
+    output.puts("  if (TEST_PROTECT()) \\")
+    output.puts("  { \\")
+    output.puts("    CEXCEPTION_T e; \\") if cexception
+    output.puts("    Try { \\") if cexception
+    output.puts("      #{@options[:setup_name]}(); \\")
+    output.puts("      TestFunc(#{va_args2}); \\")
+    output.puts("    } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, \"Unhandled Exception!\"); } \\") if cexception
+    output.puts("  } \\")
+    output.puts("  if (TEST_PROTECT() && !TEST_IS_IGNORED) \\")
+    output.puts("  { \\")
+    output.puts("    #{@options[:teardown_name]}(); \\")
+    output.puts("    CMock_Verify(); \\") unless (used_mocks.empty?)
+    output.puts("  } \\")
+    output.puts("  CMock_Destroy(); \\") unless (used_mocks.empty?)
+    output.puts("  UnityConcludeTest(); \\")
+    output.puts("}\n")
+  end
+
+  def create_reset(output, used_mocks)
+    output.puts("\n/*=======Test Reset Option=====*/")
+    output.puts("void resetTest(void);")
+    output.puts("void resetTest(void)")
+    output.puts("{")
+    output.puts("  CMock_Verify();") unless (used_mocks.empty?)
+    output.puts("  CMock_Destroy();") unless (used_mocks.empty?)
+    output.puts("  #{@options[:teardown_name]}();")
+    output.puts("  CMock_Init();") unless (used_mocks.empty?)
+    output.puts("  #{@options[:setup_name]}();")
+    output.puts("}")
+  end
+
+  def create_main(output, filename, tests, used_mocks)
+    output.puts("\n\n/*=======MAIN=====*/")
+    if (@options[:main_name] != "main")
+      output.puts("int #{@options[:main_name]}(void);")
+    end
+    output.puts("int #{@options[:main_name]}(void)")
+    output.puts("{")
+    output.puts("  suite_setup();") unless @options[:suite_setup].nil?
+    output.puts("  UnityBegin(\"#{filename.gsub(/\\/,'\\\\')}\");")
+    if (@options[:use_param_tests])
+      tests.each do |test|
+        if ((test[:args].nil?) or (test[:args].empty?))
+          output.puts("  RUN_TEST(#{test[:test]}, #{test[:line_number]}, RUN_TEST_NO_ARGS);")
+        else
+          test[:args].each {|args| output.puts("  RUN_TEST(#{test[:test]}, #{test[:line_number]}, #{args});")}
+        end
+      end
+    else
+        tests.each { |test| output.puts("  RUN_TEST(#{test[:test]}, #{test[:line_number]});") }
+    end
+    output.puts()
+    output.puts("  CMock_Guts_MemFreeFinal();") unless used_mocks.empty?
+    output.puts("  return #{@options[:suite_teardown].nil? ? "" : "suite_teardown"}(UnityEnd());")
+    output.puts("}")
+  end
+
+  def create_h_file(output, filename, tests, testfile_includes, used_mocks)
+    filename = File.basename(filename).gsub(/[-\/\\\.\,\s]/, "_").upcase
+    output.puts("/* AUTOGENERATED FILE. DO NOT EDIT. */")
+    output.puts("#ifndef _#{filename}")
+    output.puts("#define _#{filename}\n\n")
+    output.puts("#include \"#{@options[:framework].to_s}.h\"")
+    output.puts('#include "cmock.h"') unless (used_mocks.empty?)
+    @options[:includes].flatten.uniq.compact.each do |inc|
+      output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}")
+    end
+    testfile_includes.each do |inc|
+      output.puts("#include #{inc.include?('<') ? inc : "\"#{inc.gsub('.h','')}.h\""}")
+    end
+    output.puts "\n"
+    tests.each do |test|
+      if ((test[:params].nil?) or (test[:params].empty?))
+        output.puts("void #{test[:test]}(void);")
+      else
+        output.puts("void #{test[:test]}(#{test[:params]});")
+      end
+    end
+    output.puts("#endif\n\n")
+  end
+end
+
+if ($0 == __FILE__)
+  options = { :includes => [] }
+  yaml_file = nil
+
+  #parse out all the options first (these will all be removed as we go)
+  ARGV.reject! do |arg|
+    case(arg)
+      when '-cexception'
+        options[:plugins] = [:cexception]; true
+      when /\.*\.ya?ml/
+        options = UnityTestRunnerGenerator.grab_config(arg); true
+      when /--(\w+)=\"?(.*)\"?/
+        options[$1.to_sym] = $2; true
+      when /\.*\.h/
+        options[:includes] << arg; true
+      else false
+    end
+  end
+
+  #make sure there is at least one parameter left (the input file)
+  if !ARGV[0]
+    puts ["\nusage: ruby #{__FILE__} (files) (options) input_test_file (output)",
+           "\n  input_test_file         - this is the C file you want to create a runner for",
+           "  output                  - this is the name of the runner file to generate",
+           "                            defaults to (input_test_file)_Runner",
+           "  files:",
+           "    *.yml / *.yaml        - loads configuration from here in :unity or :cmock",
+           "    *.h                   - header files are added as #includes in runner",
+           "  options:",
+           "    -cexception           - include cexception support",
+           "    --setup_name=\"\"       - redefine setUp func name to something else",
+           "    --teardown_name=\"\"    - redefine tearDown func name to something else",
+           "    --main_name=\"\"        - redefine main func name to something else",
+           "    --test_prefix=\"\"      - redefine test prefix from default test|spec|should",
+           "    --suite_setup=\"\"      - code to execute for setup of entire suite",
+           "    --suite_teardown=\"\"   - code to execute for teardown of entire suite",
+           "    --use_param_tests=1   - enable parameterized tests (disabled by default)",
+           "    --header_file=\"\"      - path/name of test header file to generate too"
+          ].join("\n")
+    exit 1
+  end
+
+  #create the default test runner name if not specified
+  ARGV[1] = ARGV[0].gsub(".c","_Runner.c") if (!ARGV[1])
+
+  UnityTestRunnerGenerator.new(options).run(ARGV[0], ARGV[1])
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/parseOutput.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,191 @@
+#============================================================
+#  Author:   John Theofanopoulos
+#  A simple parser.   Takes the output files generated during the build process and
+# extracts information relating to the tests.  
+#
+#  Notes:
+#    To capture an output file under VS builds use the following:
+#      devenv [build instructions]  > Output.txt & type Output.txt
+# 
+#    To capture an output file under GCC/Linux builds use the following:
+#      make | tee Output.txt
+#
+#    To use this parser use the following command
+#    ruby parseOutput.rb [options] [file]
+#        options:  -xml  : produce a JUnit compatible XML file
+#        file      :  file to scan for results
+#============================================================
+
+
+class ParseOutput
+# The following flag is set to true when a test is found or false otherwise.
+    @testFlag
+    @xmlOut
+    @arrayList
+    @totalTests
+    @classIndex
+
+#   Set the flag to indicate if there will be an XML output file or not  
+    def setXmlOutput()
+        @xmlOut = true
+    end
+    
+#  if write our output to XML
+    def writeXmlOuput()
+            output = File.open("report.xml", "w")
+            output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+            @arrayList.each do |item|
+                output << item << "\n"
+            end
+            output << "</testsuite>\n"
+    end
+    
+#  This function will try and determine when the suite is changed.   This is
+# is the name that gets added to the classname parameter.
+    def  testSuiteVerify(testSuiteName)
+        if @testFlag == false
+            @testFlag = true;
+            # Split the path name 
+            testName = testSuiteName.split("/")
+            # Remove the extension
+            baseName = testName[testName.size - 1].split(".")
+            @testSuite = "test." + baseName[0]
+            printf "New Test: %s\n", @testSuite
+        end
+    end
+    
+
+# Test was flagged as having passed so format the output
+    def testPassed(array)
+        lastItem = array.length - 1
+        testName = array[lastItem - 1]
+        testSuiteVerify(array[@className])
+        printf "%-40s PASS\n", testName
+        if @xmlOut == true
+            @arrayList.push "     <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\"/>"
+        end          
+    end
+
+# Test was flagged as being ingored so format the output
+    def testIgnored(array)
+        lastItem = array.length - 1
+        testName = array[lastItem - 2]
+        reason = array[lastItem].chomp
+        testSuiteVerify(array[@className])
+        printf "%-40s IGNORED\n", testName
+        if @xmlOut == true
+            @arrayList.push "     <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">"
+            @arrayList.push "            <skipped type=\"TEST IGNORED\"> " + reason + " </skipped>"
+            @arrayList.push "     </testcase>"
+        end          
+    end
+
+# Test was flagged as having failed  so format the line
+    def testFailed(array)
+        lastItem = array.length - 1
+        testName = array[lastItem - 2]
+        reason = array[lastItem].chomp + " at line: " + array[lastItem - 3]
+        testSuiteVerify(array[@className])
+        printf "%-40s FAILED\n", testName
+        if @xmlOut == true
+            @arrayList.push "     <testcase classname=\"" + @testSuite + "\" name=\"" + testName + "\">"
+            @arrayList.push "            <failure type=\"ASSERT FAILED\"> " + reason + " </failure>"
+            @arrayList.push "     </testcase>"
+        end          
+    end
+
+    
+# Figure out what OS we are running on.   For now we are assuming if it's not Windows it must
+# be Unix based.  
+    def detectOS()
+        myOS = RUBY_PLATFORM.split("-")
+        if myOS.size == 2
+            if myOS[1] == "mingw32"
+                @className = 1
+            else
+                @className = 0
+            end
+	else
+                @className = 0
+        end
+        
+    end
+
+# Main function used to parse the file that was captured.
+    def process(name)
+        @testFlag = false
+        @arrayList = Array.new
+
+        detectOS()
+
+        puts "Parsing file: " + name
+    
+      
+        testPass = 0
+        testFail = 0
+        testIgnore = 0
+        puts ""
+        puts "=================== RESULTS ====================="
+        puts ""
+        File.open(name).each do |line|
+        # Typical test lines look like this:
+        # <path>/<test_file>.c:36:test_tc1000_opsys:FAIL: Expected 1 Was 0
+        # <path>/<test_file>.c:112:test_tc5004_initCanChannel:IGNORE: Not Yet Implemented
+        # <path>/<test_file>.c:115:test_tc5100_initCanVoidPtrs:PASS
+        #
+        # where path is different on Unix vs Windows devices (Windows leads with a drive letter)
+            lineArray = line.split(":")
+            lineSize = lineArray.size
+            # If we were able to split the line then we can look to see if any of our target words
+            # were found.  Case is important.
+            if lineSize >= 4
+                # Determine if this test passed
+                if  line.include? ":PASS"
+                    testPassed(lineArray)
+                    testPass += 1
+                elsif line.include? ":FAIL:"
+                    testFailed(lineArray)
+                    testFail += 1
+                elsif line.include? ":IGNORE:"
+                    testIgnored(lineArray)
+                    testIgnore += 1
+                # If none of the keywords are found there are no more tests for this suite so clear
+                # the test flag
+                else
+                    @testFlag = false
+                end
+            else
+                @testFlag = false
+                end
+            end
+        puts ""
+        puts "=================== SUMMARY ====================="
+        puts ""
+        puts "Tests Passed  : " + testPass.to_s
+        puts "Tests Failed  : " + testFail.to_s
+        puts "Tests Ignored : " + testIgnore.to_s
+        @totalTests = testPass + testFail + testIgnore
+        if @xmlOut == true
+            heading = "<testsuite tests=\"" +  @totalTests.to_s  + "\" failures=\"" + testFail.to_s + "\""  + " skips=\"" +  testIgnore.to_s + "\">" 
+            @arrayList.insert(0, heading) 
+            writeXmlOuput()
+        end
+
+    #  return result
+    end
+
+ end
+
+# If the command line has no values in, used a default value of Output.txt
+parseMyFile = ParseOutput.new
+
+if ARGV.size >= 1 
+    ARGV.each do |a|
+        if a == "-xml"
+            parseMyFile.setXmlOutput();
+        else
+            parseMyFile.process(a)
+            break
+        end
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/stylize_as_junit.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,264 @@
+#!/usr/bin/ruby
+#
+# unity_to_junit.rb
+#
+require 'fileutils'
+require 'optparse'
+require 'ostruct'
+require 'set'
+
+require 'pp'
+
+VERSION = 1.0
+
+class ArgvParser
+
+  #
+  # Return a structure describing the options.
+  #
+  def self.parse(args)
+    # The options specified on the command line will be collected in *options*.
+    # We set default values here.
+    options = OpenStruct.new
+    options.results_dir = "."
+    options.root_path = "."
+    options.out_file = "results.xml"
+
+    opts = OptionParser.new do |opts|
+      opts.banner = "Usage: unity_to_junit.rb [options]"
+
+      opts.separator ""
+      opts.separator "Specific options:"
+
+      opts.on("-r", "--results <dir>", "Look for Unity Results files here.") do |results|
+        #puts "results #{results}"
+        options.results_dir = results
+      end
+
+      opts.on("-p", "--root_path <path>", "Prepend this path to files in results.") do |root_path|
+        options.root_path = root_path
+      end
+
+      opts.on("-o", "--output <filename>", "XML file to generate.") do |out_file|
+        #puts "out_file: #{out_file}"
+        options.out_file = out_file
+      end
+
+      opts.separator ""
+      opts.separator "Common options:"
+
+      # No argument, shows at tail.  This will print an options summary.
+      opts.on_tail("-h", "--help", "Show this message") do
+        puts opts
+        exit
+      end
+
+      # Another typical switch to print the version.
+      opts.on_tail("--version", "Show version") do
+        puts "unity_to_junit.rb version #{VERSION}"
+        exit
+      end
+    end
+
+    opts.parse!(args)
+    options
+  end  # parse()
+
+end  # class OptparseExample
+
+class UnityToJUnit
+  include FileUtils::Verbose
+  attr_reader :report, :total_tests, :failures, :ignored
+
+  def initialize
+    @report = ''
+    @unit_name = ''
+  end
+
+  def run
+    # Clean up result file names
+    results = @targets.map {|target| target.gsub(/\\/,"/")}
+    #puts "Output File: #{@out_file}"
+    f = File.new(@out_file, "w")
+    write_xml_header(f)
+    write_suites_header( f )
+    results.each do |result_file|
+      lines = File.readlines(result_file).map { |line| line.chomp }
+      if lines.length == 0
+        raise "Empty test result file: #{result_file}"
+      else
+        result_output = get_details(result_file, lines)
+        tests,failures,ignored = parse_test_summary(lines)
+        result_output[:counts][:total] = tests
+        result_output[:counts][:failed] = failures
+        result_output[:counts][:ignored] = ignored
+        result_output[:counts][:passed] = (result_output[:counts][:total] - result_output[:counts][:failed] - result_output[:counts][:ignored])
+      end
+      #use line[0] from the test output to get the test_file path and name
+      test_file_str = lines[0].gsub("\\","/")
+      test_file_str = test_file_str.split(":")
+      test_file = if (test_file_str.length < 2)
+        result_file
+      else
+        test_file_str[0] + ':' + test_file_str[1]
+      end
+      result_output[:source][:path] = File.dirname(test_file)
+      result_output[:source][:file] = File.basename(test_file)
+
+      # save result_output
+      @unit_name = File.basename(test_file, ".*")
+
+      write_suite_header( result_output[:counts], f)
+      write_failures( result_output, f )
+      write_tests( result_output, f )
+      write_ignored( result_output, f )
+      write_suite_footer( f )
+    end
+    write_suites_footer( f )
+    f.close
+  end
+
+  def set_targets(target_array)
+    @targets = target_array
+  end
+
+  def set_root_path(path)
+    @root = path
+  end
+  def set_out_file(filename)
+    @out_file = filename
+  end
+  def usage(err_msg=nil)
+    puts "\nERROR: "
+    puts err_msg if err_msg
+    puts "Usage: unity_to_junit.rb [options]"
+    puts ""
+    puts "Specific options:"
+    puts "    -r, --results <dir>              Look for Unity Results files here."
+    puts "    -p, --root_path <path>           Prepend this path to files in results."
+    puts "    -o, --output <filename>          XML file to generate."
+    puts ""
+    puts "Common options:"
+    puts "    -h, --help                       Show this message"
+    puts "        --version                    Show version"
+
+    exit 1
+  end
+
+  protected
+  def get_details(result_file, lines)
+    results = get_results_structure
+    lines.each do |line|
+      line = line.gsub("\\","/")
+      src_file,src_line,test_name,status,msg = line.split(/:/)
+      line_out = ((@root and (@root != 0)) ? "#{@root}#{line}" : line ).gsub(/\//, "\\")
+      case(status)
+        when 'IGNORE' then results[:ignores] << {:test => test_name, :line => src_line, :message => msg}
+        when 'FAIL'   then results[:failures] << {:test => test_name, :line => src_line, :message => msg}
+        when 'PASS'   then results[:successes] << {:test => test_name, :line => src_line, :message => msg}
+      end
+    end
+    return results
+  end
+
+  def parse_test_summary(summary)
+    if summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ }
+      [$1.to_i,$2.to_i,$3.to_i]
+    else
+      raise "Couldn't parse test results: #{summary}"
+    end
+  end
+  def here; File.expand_path(File.dirname(__FILE__)); end
+
+  private
+
+  def get_results_structure
+    return {
+      :source    => {:path => '', :file => ''},
+      :successes => [],
+      :failures  => [],
+      :ignores   => [],
+      :counts    => {:total => 0, :passed => 0, :failed => 0, :ignored  => 0},
+      :stdout    => [],
+    }
+  end
+
+  def write_xml_header( stream )
+    stream.puts "<?xml version='1.0' encoding='utf-8' ?>"
+  end
+
+  def write_suites_header( stream )
+    stream.puts "<testsuites>"
+  end
+
+  def write_suite_header( counts, stream )
+    stream.puts "\t<testsuite errors=\"0\" skipped=\"#{counts[:ignored]}\" failures=\"#{counts[:failed]}\" tests=\"#{counts[:total]}\" name=\"unity\">"
+  end
+
+  def write_failures( results, stream )
+    result = results[:failures]
+    result.each do |item|
+      filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
+      stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">"
+      stream.puts "\t\t\t<failure message=\"#{item[:message]}\" type=\"Assertion\"/>"
+      stream.puts "\t\t\t<system-err>&#xD;[File] #{filename}&#xD;[Line] #{item[:line]}&#xD;</system-err>"
+      stream.puts "\t\t</testcase>"
+    end
+  end
+
+  def write_tests( results, stream )
+    result = results[:successes]
+    result.each do |item|
+      filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
+      stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\" />"
+    end
+  end
+
+  def write_ignored( results, stream )
+    result = results[:ignores]
+    result.each do |item|
+      filename = File.join(results[:source][:path], File.basename(results[:source][:file], '.*'))
+      puts "Writing ignored tests for test harness: #{filename}"
+      stream.puts "\t\t<testcase classname=\"#{@unit_name}\" name=\"#{item[:test]}\" time=\"0\">"
+      stream.puts "\t\t\t<skipped message=\"#{item[:message]}\" type=\"Assertion\"/>"
+      stream.puts "\t\t\t<system-err>&#xD;[File] #{filename}&#xD;[Line] #{item[:line]}&#xD;</system-err>"
+      stream.puts "\t\t</testcase>"
+    end
+  end
+
+  def write_suite_footer( stream )
+    stream.puts "\t</testsuite>"
+  end
+
+  def write_suites_footer( stream )
+    stream.puts "</testsuites>"
+  end
+end #UnityToJUnit
+
+if __FILE__ == $0
+  #parse out the command options
+  options = ArgvParser.parse(ARGV)
+
+  #create an instance to work with
+  utj = UnityToJUnit.new
+  begin
+    #look in the specified or current directory for result files
+    targets = "#{options.results_dir.gsub(/\\/, '/')}**/*.test*"
+
+    results = Dir[targets]
+    raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty?
+    utj.set_targets(results)
+
+    #set the root path
+    utj.set_root_path(options.root_path)
+
+    #set the output XML file name
+    #puts "Output File from options: #{options.out_file}"
+    utj.set_out_file(options.out_file)
+
+    #run the summarizer
+    puts utj.run
+  rescue Exception => e
+    utj.usage e.message
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/test_file_filter.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,23 @@
+# ==========================================
+#   Unity Project - A Test Framework for C
+#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+#   [Released under MIT License. Please refer to license.txt for details]
+# ========================================== 
+
+require'yaml'
+
+module RakefileHelpers
+  class TestFileFilter
+    def initialize(all_files = false)
+      @all_files = all_files
+      if not @all_files == true
+        if File.exist?('test_file_filter.yml')
+          filters = YAML.load_file( 'test_file_filter.yml' )
+          @all_files, @only_files, @exclude_files = 
+            filters[:all_files], filters[:only_files], filters[:exclude_files] 
+        end
+      end
+    end		
+    attr_accessor :all_files, :only_files, :exclude_files
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/type_sanitizer.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,8 @@
+module TypeSanitizer
+  
+  def self.sanitize_c_identifier(unsanitized)
+    # convert filename to valid C identifier by replacing invalid chars with '_'
+    return unsanitized.gsub(/[-\/\\\.\,\s]/, "_")
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/unity_test_summary.py	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,135 @@
+#! python3
+# ==========================================
+#   Unity Project - A Test Framework for C
+#   Copyright (c) 2015 Alexander Mueller / XelaRellum@web.de
+#   [Released under MIT License. Please refer to license.txt for details]
+#   Based on the ruby script by  Mike Karlesky, Mark VanderVoord, Greg Williams
+# ==========================================
+import sys
+import os
+import re
+from glob import glob
+
+class UnityTestSummary:
+    def __init__(self):
+        self.report = ''
+        self.total_tests = 0
+        self.failures = 0
+        self.ignored = 0
+
+    def run(self):
+        # Clean up result file names
+        results = []
+        for target in self.targets:
+            results.append(target.replace('\\', '/'))
+
+        # Dig through each result file, looking for details on pass/fail:
+        failure_output = []
+        ignore_output = []
+
+        for result_file in results:
+            lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n')))
+            if len(lines) == 0:
+                raise Exception("Empty test result file: %s" % result_file)
+
+            details = self.get_details(result_file, lines)
+            failures = details['failures']
+            ignores = details['ignores']
+            if len(failures) > 0: failure_output.append('\n'.join(failures))
+            if len(ignores) > 0: ignore_output.append('n'.join(ignores))
+            tests,failures,ignored = self.parse_test_summary('\n'.join(lines))
+            self.total_tests += tests
+            self.failures += failures
+            self.ignored += ignored
+
+        if self.ignored > 0:
+            self.report += "\n"
+            self.report += "--------------------------\n"
+            self.report += "UNITY IGNORED TEST SUMMARY\n"
+            self.report += "--------------------------\n"
+            self.report += "\n".join(ignore_output)
+
+        if self.failures > 0:
+            self.report += "\n"
+            self.report += "--------------------------\n"
+            self.report += "UNITY FAILED TEST SUMMARY\n"
+            self.report += "--------------------------\n"
+            self.report += '\n'.join(failure_output)
+
+        self.report += "\n"
+        self.report += "--------------------------\n"
+        self.report += "OVERALL UNITY TEST SUMMARY\n"
+        self.report += "--------------------------\n"
+        self.report += "{total_tests} TOTAL TESTS {failures} TOTAL FAILURES {ignored} IGNORED\n".format(total_tests = self.total_tests, failures=self.failures, ignored=self.ignored)
+        self.report += "\n"
+
+        return self.report
+
+    def set_targets(self, target_array):
+            self.targets = target_array
+
+    def set_root_path(self, path):
+        self.root = path
+
+    def usage(self, err_msg=None):
+        print("\nERROR: ")
+        if err_msg:
+            print(err_msg)
+        print("\nUsage: unity_test_summary.py result_file_directory/ root_path/")
+        print("     result_file_directory - The location of your results files.")
+        print("                             Defaults to current directory if not specified.")
+        print("                             Should end in / if specified.")
+        print("     root_path - Helpful for producing more verbose output if using relative paths.")
+        sys.exit(1)
+
+    def get_details(self, result_file, lines):
+        results = { 'failures': [], 'ignores': [], 'successes': [] }
+        for line in lines:
+            parts = line.split(':')
+            if len(parts) != 5:
+                continue
+            src_file,src_line,test_name,status,msg = parts
+            if len(self.root) > 0:
+                line_out = "%s%s" % (self.root, line)
+            else:
+                line_out = line
+            if status == 'IGNORE':
+                results['ignores'].append(line_out)
+            elif status == 'FAIL':
+                results['failures'].append(line_out)
+            elif status == 'PASS':
+                results['successes'].append(line_out)
+        return results
+
+    def parse_test_summary(self, summary):
+        m = re.search(r"([0-9]+) Tests ([0-9]+) Failures ([0-9]+) Ignored", summary)
+        if not m:
+            raise Exception("Couldn't parse test results: %s" % summary)
+
+        return int(m.group(1)), int(m.group(2)), int(m.group(3))
+
+
+if __name__ == '__main__':
+  uts = UnityTestSummary()
+  try:
+    #look in the specified or current directory for result files
+    if len(sys.argv) > 1:
+        targets_dir = sys.argv[1]
+    else:
+        targets_dir = './'
+    targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*')))
+    if len(targets) == 0:
+        raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir)
+    uts.set_targets(targets)
+
+    #set the root path
+    if len(sys.argv) > 2:
+        root_path = sys.argv[2]
+    else:
+        root_path = os.path.split(__file__)[0]
+    uts.set_root_path(root_path)
+
+    #run the summarizer
+    print(uts.run())
+  except Exception as e:
+    uts.usage(e)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/unity_test_summary.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,148 @@
+# ==========================================
+#   Unity Project - A Test Framework for C
+#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+#   [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+#!/usr/bin/ruby
+#
+# unity_test_summary.rb
+#
+require 'fileutils'
+require 'set'
+
+class UnityTestSummary
+  include FileUtils::Verbose
+
+  attr_reader :report, :total_tests, :failures, :ignored
+
+  def initialize(opts = {})
+    @report = ''
+    @total_tests = 0
+    @failures = 0
+    @ignored = 0
+
+
+  end
+
+  def run
+    # Clean up result file names
+    results = @targets.map {|target| target.gsub(/\\/,'/')}
+
+    # Dig through each result file, looking for details on pass/fail:
+    failure_output = []
+    ignore_output = []
+
+    results.each do |result_file|
+      lines = File.readlines(result_file).map { |line| line.chomp }
+      if lines.length == 0
+        raise "Empty test result file: #{result_file}"
+      else
+        output = get_details(result_file, lines)
+        failure_output << output[:failures] unless output[:failures].empty?
+        ignore_output  << output[:ignores]  unless output[:ignores].empty?
+        tests,failures,ignored = parse_test_summary(lines)
+        @total_tests += tests
+        @failures += failures
+        @ignored += ignored
+      end
+    end
+
+    if @ignored > 0
+      @report += "\n"
+      @report += "--------------------------\n"
+      @report += "UNITY IGNORED TEST SUMMARY\n"
+      @report += "--------------------------\n"
+      @report += ignore_output.flatten.join("\n")
+    end
+
+    if @failures > 0
+      @report += "\n"
+      @report += "--------------------------\n"
+      @report += "UNITY FAILED TEST SUMMARY\n"
+      @report += "--------------------------\n"
+      @report += failure_output.flatten.join("\n")
+    end
+
+    @report += "\n"
+    @report += "--------------------------\n"
+    @report += "OVERALL UNITY TEST SUMMARY\n"
+    @report += "--------------------------\n"
+    @report += "#{@total_tests} TOTAL TESTS #{@failures} TOTAL FAILURES #{@ignored} IGNORED\n"
+    @report += "\n"
+  end
+
+  def set_targets(target_array)
+    @targets = target_array
+  end
+
+  def set_root_path(path)
+    @root = path
+  end
+
+  def usage(err_msg=nil)
+    puts "\nERROR: "
+    puts err_msg if err_msg
+    puts "\nUsage: unity_test_summary.rb result_file_directory/ root_path/"
+    puts "     result_file_directory - The location of your results files."
+    puts "                             Defaults to current directory if not specified."
+    puts "                             Should end in / if specified."
+    puts "     root_path - Helpful for producing more verbose output if using relative paths."
+    exit 1
+  end
+
+  protected
+
+  def get_details(result_file, lines)
+    results = { :failures => [], :ignores => [], :successes => [] }
+    lines.each do |line|
+      src_file,src_line,test_name,status,msg = line.split(/:/)
+      line_out = ((@root && (@root != 0)) ? "#{@root}#{line}" : line ).gsub(/\//, "\\")
+      case(status)
+        when 'IGNORE' then results[:ignores]   << line_out
+        when 'FAIL'   then results[:failures]  << line_out
+        when 'PASS'   then results[:successes] << line_out
+      end
+    end
+    return results
+  end
+
+  def parse_test_summary(summary)
+    if summary.find { |v| v =~ /(\d+) Tests (\d+) Failures (\d+) Ignored/ }
+      [$1.to_i,$2.to_i,$3.to_i]
+    else
+      raise "Couldn't parse test results: #{summary}"
+    end
+  end
+
+  def here; File.expand_path(File.dirname(__FILE__)); end
+
+end
+
+if $0 == __FILE__
+
+  #parse out the command options
+  opts, args = ARGV.partition {|v| v =~ /^--\w+/}
+  opts.map! {|v| v[2..-1].to_sym }
+
+  #create an instance to work with
+  uts = UnityTestSummary.new(opts)
+
+  begin
+    #look in the specified or current directory for result files
+    args[0] ||= './'
+    targets = "#{ARGV[0].gsub(/\\/, '/')}**/*.test*"
+    results = Dir[targets]
+    raise "No *.testpass, *.testfail, or *.testresults files found in '#{targets}'" if results.empty?
+    uts.set_targets(results)
+
+    #set the root path
+    args[1] ||= Dir.pwd + '/'
+    uts.set_root_path(ARGV[1])
+
+    #run the summarizer
+    puts uts.run
+  rescue Exception => e
+    uts.usage e.message
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/auto/unity_to_junit.py	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,146 @@
+import sys
+import os
+from glob import glob
+
+from pyparsing import *
+from junit_xml import TestSuite, TestCase
+
+
+class UnityTestSummary:
+    def __init__(self):
+        self.report = ''
+        self.total_tests = 0
+        self.failures = 0
+        self.ignored = 0
+        self.targets = 0
+        self.root = None
+        self.test_suites = dict()
+
+    def run(self):
+        # Clean up result file names
+        results = []
+        for target in self.targets:
+            results.append(target.replace('\\', '/'))
+
+        # Dig through each result file, looking for details on pass/fail:
+        for result_file in results:
+            lines = list(map(lambda line: line.rstrip(), open(result_file, "r").read().split('\n')))
+            if len(lines) == 0:
+                raise Exception("Empty test result file: %s" % result_file)
+
+            # define an expression for your file reference
+            entry_one = Combine(
+                oneOf(list(alphas)) + ':/' +
+                Word(alphanums + '_-./'))
+
+            entry_two = Word(printables + ' ', excludeChars=':')
+            entry = entry_one | entry_two
+
+            delimiter = Literal(':').suppress()
+            tc_result_line = Group(entry.setResultsName('tc_file_name') + delimiter + entry.setResultsName(
+                'tc_line_nr') + delimiter + entry.setResultsName('tc_name') + delimiter + entry.setResultsName(
+                'tc_status') + Optional(
+                delimiter + entry.setResultsName('tc_msg'))).setResultsName("tc_line")
+
+            eol = LineEnd().suppress()
+            sol = LineStart().suppress()
+            blank_line = sol + eol
+
+            tc_summary_line = Group(Word(nums).setResultsName("num_of_tests") + "Tests" + Word(nums).setResultsName(
+                "num_of_fail") + "Failures" + Word(nums).setResultsName("num_of_ignore") + "Ignored").setResultsName(
+                "tc_summary")
+            tc_end_line = Or(Literal("FAIL"), Literal('Ok')).setResultsName("tc_result")
+
+            # run it and see...
+            pp1 = tc_result_line | Optional(tc_summary_line | tc_end_line)
+            pp1.ignore(blank_line | OneOrMore("-"))
+
+            result = list()
+            for l in lines:
+                result.append((pp1.parseString(l)).asDict())
+            # delete empty results
+            result = filter(None, result)
+
+            tc_list = list()
+            for r in result:
+                if 'tc_line' in r:
+                    tmp_tc_line = r['tc_line']
+
+                    # get only the file name which will be used as the classname
+                    file_name = tmp_tc_line['tc_file_name'].split('\\').pop().split('/').pop().rsplit('.', 1)[0]
+                    tmp_tc = TestCase(name=tmp_tc_line['tc_name'], classname=file_name)
+                    if 'tc_status' in tmp_tc_line:
+                        if str(tmp_tc_line['tc_status']) == 'IGNORE':
+                            if 'tc_msg' in tmp_tc_line:
+                                tmp_tc.add_skipped_info(message=tmp_tc_line['tc_msg'],
+                                                        output=r'[File]={0}, [Line]={1}'.format(
+                                                            tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr']))
+                            else:
+                                tmp_tc.add_skipped_info(message=" ")
+                        elif str(tmp_tc_line['tc_status']) == 'FAIL':
+                            if 'tc_msg' in tmp_tc_line:
+                                tmp_tc.add_failure_info(message=tmp_tc_line['tc_msg'],
+                                                        output=r'[File]={0}, [Line]={1}'.format(
+                                                            tmp_tc_line['tc_file_name'], tmp_tc_line['tc_line_nr']))
+                            else:
+                                tmp_tc.add_failure_info(message=" ")
+
+                    tc_list.append((str(result_file), tmp_tc))
+
+            for k, v in tc_list:
+                try:
+                    self.test_suites[k].append(v)
+                except KeyError:
+                    self.test_suites[k] = [v]
+        ts = []
+        for suite_name in self.test_suites:
+            ts.append(TestSuite(suite_name, self.test_suites[suite_name]))
+
+        with open('result.xml', 'w') as f:
+            TestSuite.to_file(f, ts, prettyprint='True', encoding='utf-8')
+
+        return self.report
+
+    def set_targets(self, target_array):
+        self.targets = target_array
+
+    def set_root_path(self, path):
+        self.root = path
+
+    @staticmethod
+    def usage(err_msg=None):
+        print("\nERROR: ")
+        if err_msg:
+            print(err_msg)
+        print("\nUsage: unity_test_summary.py result_file_directory/ root_path/")
+        print("     result_file_directory - The location of your results files.")
+        print("                             Defaults to current directory if not specified.")
+        print("                             Should end in / if specified.")
+        print("     root_path - Helpful for producing more verbose output if using relative paths.")
+        sys.exit(1)
+
+
+if __name__ == '__main__':
+    uts = UnityTestSummary()
+    try:
+        # look in the specified or current directory for result files
+        if len(sys.argv) > 1:
+            targets_dir = sys.argv[1]
+        else:
+            targets_dir = './'
+        targets = list(map(lambda x: x.replace('\\', '/'), glob(targets_dir + '*.test*')))
+        if len(targets) == 0:
+            raise Exception("No *.testpass or *.testfail files found in '%s'" % targets_dir)
+        uts.set_targets(targets)
+
+        # set the root path
+        if len(sys.argv) > 2:
+            root_path = sys.argv[2]
+        else:
+            root_path = os.path.split(__file__)[0]
+        uts.set_root_path(root_path)
+
+        # run the summarizer
+        print(uts.run())
+    except Exception as e:
+        UnityTestSummary.usage(e)
Binary file simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/docs/UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf has changed
Binary file simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/docs/UnityAssertionsReference.pdf has changed
Binary file simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/docs/UnityConfigurationGuide.pdf has changed
Binary file simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/docs/UnityGettingStartedGuide.pdf has changed
Binary file simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/docs/UnityHelperScriptsGuide.pdf has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/docs/license.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) <year> 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/readme.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,5 @@
+Example 1
+=========
+
+Close to the simplest possible example of Unity, using only basic features.
+Run make to build & run the example tests.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/src/ProductionCode.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,24 @@
+
+#include "ProductionCode.h"
+
+int Counter = 0;
+int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; /* some obnoxious array to search that is 1-based indexing instead of 0. */
+
+/* This function is supposed to search through NumbersToFind and find a particular number.  
+ * If it finds it, the index is returned.  Otherwise 0 is returned which sorta makes sense since 
+ * NumbersToFind is indexed from 1.  Unfortunately it's broken 
+ * (and should therefore be caught by our tests) */
+int FindFunction_WhichIsBroken(int NumberToFind)
+{
+    int i = 0;
+    while (i <= 8) /* Notice I should have been in braces */
+        i++;
+        if (NumbersToFind[i] == NumberToFind) /* Yikes!  I'm getting run after the loop finishes instead of during it! */
+            return i;
+    return 0;
+}
+
+int FunctionWhichReturnsLocalVariable(void)
+{
+    return Counter;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/src/ProductionCode.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,3 @@
+
+int FindFunction_WhichIsBroken(int NumberToFind);
+int FunctionWhichReturnsLocalVariable(void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/src/ProductionCode2.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,11 @@
+
+#include "ProductionCode2.h"
+
+char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction)
+{
+  (void)Poor;
+  (void)LittleFunction;
+  /* Since There Are No Tests Yet, This Function Could Be Empty For All We Know.
+   * Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget */
+  return (char*)0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/src/ProductionCode2.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+
+char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/test/TestProductionCode.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,62 @@
+
+#include "ProductionCode.h"
+#include "unity.h"
+
+/* sometimes you may want to get at local data in a module.
+ * for example: If you plan to pass by reference, this could be useful
+ * however, it should often be avoided */
+extern int Counter; 
+
+void setUp(void)
+{
+  /* This is run before EACH TEST */
+  Counter = 0x5a5a;
+}
+
+void tearDown(void)
+{
+}
+
+void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void)
+{
+  /* All of these should pass */
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78));
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1));
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33));
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999));
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1));
+}
+
+void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void)
+{
+  /* You should see this line fail in your test summary */
+  TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34));
+  
+  /* Notice the rest of these didn't get a chance to run because the line above failed.  
+   * Unit tests abort each test function on the first sign of trouble. 
+   * Then NEXT test function runs as normal. */
+  TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888));
+}
+
+void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void)
+{
+    /* This should be true because setUp set this up for us before this test */
+    TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable());
+    
+    /* This should be true because we can still change our answer */
+    Counter = 0x1234;
+    TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable());
+}
+
+void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void)
+{
+    /* This should be true again because setup was rerun before this test (and after we changed it to 0x1234) */
+    TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable());
+}
+
+void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void)
+{
+    /* Sometimes you get the test wrong.  When that happens, you get a failure too... and a quick look should tell
+     * you what actually happened...which in this case was a failure to setup the initial condition. */
+    TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/test/TestProductionCode2.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,31 @@
+
+#include "ProductionCode2.h"
+#include "unity.h"
+
+/* These should be ignored because they are commented out in various ways:
+#include "whatever.h" 
+#include "somethingelse.h"
+*/
+
+void setUp(void)
+{
+}
+
+void tearDown(void)
+{
+}
+
+void test_IgnoredTest(void)
+{
+    TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose");
+}
+
+void test_AnotherIgnoredTest(void)
+{
+    TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet");
+}
+
+void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void)
+{
+    TEST_IGNORE(); /* Like This */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/test/test_runners/TestProductionCode2_Runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,53 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+  } \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "ProductionCode2.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_IgnoredTest(void);
+extern void test_AnotherIgnoredTest(void);
+extern void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  tearDown();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("test/TestProductionCode2.c");
+  RUN_TEST(test_IgnoredTest, 18);
+  RUN_TEST(test_AnotherIgnoredTest, 23);
+  RUN_TEST(test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented, 28);
+
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_1/test/test_runners/TestProductionCode_Runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,57 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+  } \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "ProductionCode.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void);
+extern void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void);
+extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void);
+extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void);
+extern void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  tearDown();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("test/TestProductionCode.c");
+  RUN_TEST(test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode, 20);
+  RUN_TEST(test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken, 30);
+  RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue, 41);
+  RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain, 51);
+  RUN_TEST(test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed, 57);
+
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/readme.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,5 @@
+Example 2
+=========
+
+Same as the first example, but now using Unity's test fixture to group tests
+together. Using the test fixture also makes writing test runners much easier.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/src/ProductionCode.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,24 @@
+
+#include "ProductionCode.h"
+
+int Counter = 0;
+int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; //some obnoxious array to search that is 1-based indexing instead of 0.
+
+// This function is supposed to search through NumbersToFind and find a particular number.  
+// If it finds it, the index is returned.  Otherwise 0 is returned which sorta makes sense since 
+// NumbersToFind is indexed from 1.  Unfortunately it's broken 
+// (and should therefore be caught by our tests)
+int FindFunction_WhichIsBroken(int NumberToFind)
+{
+    int i = 0;
+    while (i <= 8) //Notice I should have been in braces
+        i++;
+        if (NumbersToFind[i] == NumberToFind) //Yikes!  I'm getting run after the loop finishes instead of during it!
+            return i;
+    return 0;
+}
+
+int FunctionWhichReturnsLocalVariable(void)
+{
+    return Counter;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/src/ProductionCode.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,3 @@
+
+int FindFunction_WhichIsBroken(int NumberToFind);
+int FunctionWhichReturnsLocalVariable(void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/src/ProductionCode2.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,11 @@
+
+#include "ProductionCode2.h"
+
+char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction)
+{
+  (void)Poor;
+  (void)LittleFunction;
+  //Since There Are No Tests Yet, This Function Could Be Empty For All We Know.
+  // Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget
+  return (char*)0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/src/ProductionCode2.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+
+char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/test/TestProductionCode.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,64 @@
+#include "ProductionCode.h"
+#include "unity.h"
+#include "unity_fixture.h"
+
+TEST_GROUP(ProductionCode);
+
+//sometimes you may want to get at local data in a module.
+//for example: If you plan to pass by reference, this could be useful
+//however, it should often be avoided
+extern int Counter;
+
+TEST_SETUP(ProductionCode)
+{
+  //This is run before EACH TEST
+  Counter = 0x5a5a;
+}
+
+TEST_TEAR_DOWN(ProductionCode)
+{
+}
+
+TEST(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode)
+{
+  //All of these should pass
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78));
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1));
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33));
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999));
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1));
+}
+
+TEST(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken)
+{
+  // You should see this line fail in your test summary
+  TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34));
+
+  // Notice the rest of these didn't get a chance to run because the line above failed.
+  // Unit tests abort each test function on the first sign of trouble.
+  // Then NEXT test function runs as normal.
+  TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888));
+}
+
+TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue)
+{
+    //This should be true because setUp set this up for us before this test
+    TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable());
+
+    //This should be true because we can still change our answer
+    Counter = 0x1234;
+    TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable());
+}
+
+TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain)
+{
+    //This should be true again because setup was rerun before this test (and after we changed it to 0x1234)
+    TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable());
+}
+
+TEST(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed)
+{
+    //Sometimes you get the test wrong.  When that happens, you get a failure too... and a quick look should tell
+    // you what actually happened...which in this case was a failure to setup the initial condition.
+    TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/test/TestProductionCode2.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,33 @@
+#include "ProductionCode2.h"
+#include "unity.h"
+#include "unity_fixture.h"
+
+TEST_GROUP(ProductionCode2);
+
+/* These should be ignored because they are commented out in various ways:
+#include "whatever.h"
+*/
+//#include "somethingelse.h"
+
+TEST_SETUP(ProductionCode2)
+{
+}
+
+TEST_TEAR_DOWN(ProductionCode2)
+{
+}
+
+TEST(ProductionCode2, IgnoredTest)
+{
+    TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose");
+}
+
+TEST(ProductionCode2, AnotherIgnoredTest)
+{
+    TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet");
+}
+
+TEST(ProductionCode2, ThisFunctionHasNotBeenTested_NeedsToBeImplemented)
+{
+    TEST_IGNORE(); //Like This
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/test/test_runners/TestProductionCode2_Runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,9 @@
+#include "unity.h"
+#include "unity_fixture.h"
+
+TEST_GROUP_RUNNER(ProductionCode2)
+{
+  RUN_TEST_CASE(ProductionCode2, IgnoredTest);
+  RUN_TEST_CASE(ProductionCode2, AnotherIgnoredTest);
+  RUN_TEST_CASE(ProductionCode2, ThisFunctionHasNotBeenTested_NeedsToBeImplemented);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/test/test_runners/TestProductionCode_Runner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,11 @@
+#include "unity.h"
+#include "unity_fixture.h"
+
+TEST_GROUP_RUNNER(ProductionCode)
+{
+  RUN_TEST_CASE(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode);
+  RUN_TEST_CASE(ProductionCode, FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken);
+  RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue);
+  RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain);
+  RUN_TEST_CASE(ProductionCode, FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_2/test/test_runners/all_tests.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,12 @@
+#include "unity_fixture.h"
+
+static void RunAllTests(void)
+{
+  RUN_TEST_GROUP(ProductionCode);
+  RUN_TEST_GROUP(ProductionCode2);
+}
+
+int main(int argc, const char * argv[])
+{
+  return UnityMain(argc, argv, RunAllTests);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/helper/UnityHelper.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,10 @@
+#include "unity.h"
+#include "UnityHelper.h"
+#include <stdio.h>
+#include <string.h>
+
+void AssertEqualExampleStruct(const EXAMPLE_STRUCT_T expected, const EXAMPLE_STRUCT_T actual, const unsigned short line)
+{
+    UNITY_TEST_ASSERT_EQUAL_INT(expected.x, actual.x, line, "Example Struct Failed For Field x");
+    UNITY_TEST_ASSERT_EQUAL_INT(expected.y, actual.y, line, "Example Struct Failed For Field y");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/helper/UnityHelper.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,12 @@
+#ifndef _TESTHELPER_H
+#define _TESTHELPER_H
+
+#include "Types.h"
+
+void AssertEqualExampleStruct(const EXAMPLE_STRUCT_T expected, const EXAMPLE_STRUCT_T actual, const unsigned short line);
+
+#define UNITY_TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual, line, message) AssertEqualExampleStruct(expected, actual, line);
+
+#define TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual) UNITY_TEST_ASSERT_EQUAL_EXAMPLE_STRUCT_T(expected, actual, __LINE__, NULL);
+
+#endif // _TESTHELPER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/rakefile.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,43 @@
+HERE = File.expand_path(File.dirname(__FILE__)) + '/'
+UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/../..'
+
+require 'rake'
+require 'rake/clean'
+require HERE+'rakefile_helper'
+
+TEMP_DIRS = [
+	File.join(HERE, 'build')
+]
+
+TEMP_DIRS.each do |dir|
+  directory(dir)
+  CLOBBER.include(dir)
+end
+
+task :prepare_for_tests => TEMP_DIRS
+
+include RakefileHelpers
+
+# Load default configuration, for now
+DEFAULT_CONFIG_FILE = 'target_gcc_32.yml'
+configure_toolchain(DEFAULT_CONFIG_FILE)
+
+task :unit => [:prepare_for_tests] do
+  run_tests get_unit_test_files
+end
+
+desc "Generate test summary"
+task :summary do
+  report_summary
+end
+
+desc "Build and test Unity"
+task :all => [:clean, :unit, :summary]
+task :default => [:clobber, :all]
+task :ci => [:default]
+task :cruise => [:default]
+
+desc "Load configuration"
+task :config, :config_file do |t, args|
+  configure_toolchain(args[:config_file])
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/rakefile_helper.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,256 @@
+require 'yaml'
+require 'fileutils'
+require UNITY_ROOT+'/auto/unity_test_summary'
+require UNITY_ROOT+'/auto/generate_test_runner'
+require UNITY_ROOT+'/auto/colour_reporter'
+
+module RakefileHelpers
+
+  C_EXTENSION = '.c'
+
+  def load_configuration(config_file)
+    $cfg_file = config_file
+    $cfg = YAML.load(File.read($cfg_file))
+  end
+
+  def configure_clean
+    CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil?
+  end
+
+  def configure_toolchain(config_file=DEFAULT_CONFIG_FILE)
+    config_file += '.yml' unless config_file =~ /\.yml$/
+    load_configuration(config_file)
+    configure_clean
+  end
+
+  def get_unit_test_files
+    path = $cfg['compiler']['unit_tests_path'] + 'Test*' + C_EXTENSION
+    path.gsub!(/\\/, '/')
+    FileList.new(path)
+  end
+
+  def get_local_include_dirs
+    include_dirs = $cfg['compiler']['includes']['items'].dup
+    include_dirs.delete_if {|dir| dir.is_a?(Array)}
+    return include_dirs
+  end
+
+  def extract_headers(filename)
+    includes = []
+    lines = File.readlines(filename)
+    lines.each do |line|
+      m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/)
+      if not m.nil?
+        includes << m[1]
+      end
+    end
+    return includes
+  end
+
+  def find_source_file(header, paths)
+    paths.each do |dir|
+      src_file = dir + header.ext(C_EXTENSION)
+      if (File.exists?(src_file))
+        return src_file
+      end
+    end
+    return nil
+  end
+
+  def tackit(strings)
+    if strings.is_a?(Array)
+      result = "\"#{strings.join}\""
+    else
+      result = strings
+    end
+    return result
+  end
+
+  def squash(prefix, items)
+    result = ''
+    items.each { |item| result += " #{prefix}#{tackit(item)}" }
+    return result
+  end
+
+  def build_compiler_fields
+    command  = tackit($cfg['compiler']['path'])
+    if $cfg['compiler']['defines']['items'].nil?
+      defines  = ''
+    else
+      defines  = squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'])
+    end
+    options  = squash('', $cfg['compiler']['options'])
+    includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])
+    includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
+    return {:command => command, :defines => defines, :options => options, :includes => includes}
+  end
+
+  def compile(file, defines=[])
+    compiler = build_compiler_fields
+    cmd_str  = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " +
+               "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}"
+    obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}"
+    execute(cmd_str + obj_file)
+    return obj_file
+  end
+
+  def build_linker_fields
+    command  = tackit($cfg['linker']['path'])
+    if $cfg['linker']['options'].nil?
+      options  = ''
+    else
+      options  = squash('', $cfg['linker']['options'])
+    end
+    if ($cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?)
+      includes = ''
+    else
+      includes = squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items'])
+    end
+    includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
+    return {:command => command, :options => options, :includes => includes}
+  end
+
+  def link_it(exe_name, obj_list)
+    linker = build_linker_fields
+    cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " +
+      (obj_list.map{|obj|"#{$cfg['linker']['object_files']['path']}#{obj} "}).join +
+      $cfg['linker']['bin_files']['prefix'] + ' ' +
+      $cfg['linker']['bin_files']['destination'] +
+      exe_name + $cfg['linker']['bin_files']['extension']
+    execute(cmd_str)
+  end
+
+  def build_simulator_fields
+    return nil if $cfg['simulator'].nil?
+    if $cfg['simulator']['path'].nil?
+      command = ''
+    else
+      command = (tackit($cfg['simulator']['path']) + ' ')
+    end
+    if $cfg['simulator']['pre_support'].nil?
+      pre_support = ''
+    else
+      pre_support = squash('', $cfg['simulator']['pre_support'])
+    end
+    if $cfg['simulator']['post_support'].nil?
+      post_support = ''
+    else
+      post_support = squash('', $cfg['simulator']['post_support'])
+    end
+    return {:command => command, :pre_support => pre_support, :post_support => post_support}
+  end
+
+  def execute(command_string, verbose=true, raise_on_fail=true)
+    report command_string
+    output = `#{command_string}`.chomp
+    report(output) if (verbose && !output.nil? && (output.length > 0))
+    if (($?.exitstatus != 0) and (raise_on_fail))
+      raise "Command failed. (Returned #{$?.exitstatus})"
+    end
+    return output
+  end
+
+  def report_summary
+    summary = UnityTestSummary.new
+    summary.set_root_path(HERE)
+    results_glob = "#{$cfg['compiler']['build_path']}*.test*"
+    results_glob.gsub!(/\\/, '/')
+    results = Dir[results_glob]
+    summary.set_targets(results)
+    summary.run
+    fail_out "FAIL: There were failures" if (summary.failures > 0)
+  end
+
+  def run_tests(test_files)
+
+    report 'Running system tests...'
+
+    # Tack on TEST define for compiling unit tests
+    load_configuration($cfg_file)
+    test_defines = ['TEST']
+    $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil?
+    $cfg['compiler']['defines']['items'] << 'TEST'
+
+    include_dirs = get_local_include_dirs
+
+    # Build and execute each unit test
+    test_files.each do |test|
+      obj_list = []
+
+      # Detect dependencies and build required required modules
+      extract_headers(test).each do |header|
+        # Compile corresponding source file if it exists
+        src_file = find_source_file(header, include_dirs)
+        if !src_file.nil?
+          obj_list << compile(src_file, test_defines)
+        end
+      end
+
+      # Build the test runner (generate if configured to do so)
+      test_base = File.basename(test, C_EXTENSION)
+      runner_name = test_base + '_Runner.c'
+      if $cfg['compiler']['runner_path'].nil?
+        runner_path = $cfg['compiler']['build_path'] + runner_name
+        test_gen = UnityTestRunnerGenerator.new($cfg_file)
+        test_gen.run(test, runner_path)
+      else
+        runner_path = $cfg['compiler']['runner_path'] + runner_name
+      end
+
+      obj_list << compile(runner_path, test_defines)
+
+      # Build the test module
+      obj_list << compile(test, test_defines)
+
+      # Link the test executable
+      link_it(test_base, obj_list)
+
+      # Execute unit test and generate results file
+      simulator = build_simulator_fields
+      executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension']
+      if simulator.nil?
+        cmd_str = executable
+      else
+        cmd_str = "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}"
+      end
+      output = execute(cmd_str, true, false)
+      test_results = $cfg['compiler']['build_path'] + test_base
+      if output.match(/OK$/m).nil?
+        test_results += '.testfail'
+      else
+        test_results += '.testpass'
+      end
+      File.open(test_results, 'w') { |f| f.print output }
+    end
+  end
+
+  def build_application(main)
+
+    report "Building application..."
+
+    obj_list = []
+    load_configuration($cfg_file)
+    main_path = $cfg['compiler']['source_path'] + main + C_EXTENSION
+
+    # Detect dependencies and build required required modules
+    include_dirs = get_local_include_dirs
+    extract_headers(main_path).each do |header|
+      src_file = find_source_file(header, include_dirs)
+      if !src_file.nil?
+        obj_list << compile(src_file)
+      end
+    end
+
+    # Build the main source file
+    main_base = File.basename(main_path, C_EXTENSION)
+    obj_list << compile(main_path)
+
+    # Create the executable
+    link_it(main_base, obj_list)
+  end
+
+  def fail_out(msg)
+    puts msg
+    exit(-1)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/readme.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,19 @@
+Example 3
+=========
+
+This example project gives an example of some passing, ignored, and failing tests.
+It's simple and meant for you to look over and get an idea for what all of this stuff does.
+
+You can build and test using the makefile if you have gcc installed (you may need to tweak
+the locations of some tools in the makefile).  Otherwise, the rake version will let you
+test with gcc or a couple versions of IAR.  You can tweak the yaml files to get those versions
+running.
+
+Ruby is required if you're using the rake version (obviously).  This version shows off most of
+Unity's advanced features (automatically creating test runners, fancy summaries, etc.)
+
+The makefile version doesn't require anything outside of your normal build tools, but won't do the
+extras for you.  So that you can test right away, we've written the test runners for you and
+put them in the test\no_ruby subdirectory.  If you make changes to the tests or source, you might
+need to update these (like when you add or remove tests).  Do that for a while and you'll learn
+why you really want to start using the Ruby tools.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/src/ProductionCode.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,24 @@
+
+#include "ProductionCode.h"
+
+int Counter = 0;
+int NumbersToFind[9] = { 0, 34, 55, 66, 32, 11, 1, 77, 888 }; //some obnoxious array to search that is 1-based indexing instead of 0.
+
+// This function is supposed to search through NumbersToFind and find a particular number.  
+// If it finds it, the index is returned.  Otherwise 0 is returned which sorta makes sense since 
+// NumbersToFind is indexed from 1.  Unfortunately it's broken 
+// (and should therefore be caught by our tests)
+int FindFunction_WhichIsBroken(int NumberToFind)
+{
+    int i = 0;
+    while (i <= 8) //Notice I should have been in braces
+        i++;
+        if (NumbersToFind[i] == NumberToFind) //Yikes!  I'm getting run after the loop finishes instead of during it!
+            return i;
+    return 0;
+}
+
+int FunctionWhichReturnsLocalVariable(void)
+{
+    return Counter;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/src/ProductionCode.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,3 @@
+
+int FindFunction_WhichIsBroken(int NumberToFind);
+int FunctionWhichReturnsLocalVariable(void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/src/ProductionCode2.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,11 @@
+
+#include "ProductionCode2.h"
+
+char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction)
+{
+  (void)Poor;
+  (void)LittleFunction;
+  //Since There Are No Tests Yet, This Function Could Be Empty For All We Know.
+  // Which isn't terribly useful... but at least we put in a TEST_IGNORE so we won't forget
+  return (char*)0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/src/ProductionCode2.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+
+char* ThisFunctionHasNotBeenTested(int Poor, char* LittleFunction);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/test/TestProductionCode.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,62 @@
+
+#include "ProductionCode.h"
+#include "unity.h"
+
+//sometimes you may want to get at local data in a module.
+//for example: If you plan to pass by reference, this could be useful
+//however, it should often be avoided
+extern int Counter; 
+
+void setUp(void)
+{
+  //This is run before EACH TEST
+  Counter = 0x5a5a;
+}
+
+void tearDown(void)
+{
+}
+
+void test_FindFunction_WhichIsBroken_ShouldReturnZeroIfItemIsNotInList_WhichWorksEvenInOurBrokenCode(void)
+{
+  //All of these should pass
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(78));
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(1));
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(33));
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(999));
+  TEST_ASSERT_EQUAL(0, FindFunction_WhichIsBroken(-1));
+}
+
+void test_FindFunction_WhichIsBroken_ShouldReturnTheIndexForItemsInList_WhichWillFailBecauseOurFunctionUnderTestIsBroken(void)
+{
+  // You should see this line fail in your test summary
+  TEST_ASSERT_EQUAL(1, FindFunction_WhichIsBroken(34));
+  
+  // Notice the rest of these didn't get a chance to run because the line above failed.  
+  // Unit tests abort each test function on the first sign of trouble. 
+  // Then NEXT test function runs as normal.
+  TEST_ASSERT_EQUAL(8, FindFunction_WhichIsBroken(8888));
+}
+
+void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValue(void)
+{
+    //This should be true because setUp set this up for us before this test
+    TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable());
+    
+    //This should be true because we can still change our answer
+    Counter = 0x1234;
+    TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable());
+}
+
+void test_FunctionWhichReturnsLocalVariable_ShouldReturnTheCurrentCounterValueAgain(void)
+{
+    //This should be true again because setup was rerun before this test (and after we changed it to 0x1234)
+    TEST_ASSERT_EQUAL_HEX(0x5a5a, FunctionWhichReturnsLocalVariable());
+}
+
+void test_FunctionWhichReturnsLocalVariable_ShouldReturnCurrentCounter_ButFailsBecauseThisTestIsActuallyFlawed(void)
+{
+    //Sometimes you get the test wrong.  When that happens, you get a failure too... and a quick look should tell
+    // you what actually happened...which in this case was a failure to setup the initial condition.
+    TEST_ASSERT_EQUAL_HEX(0x1234, FunctionWhichReturnsLocalVariable());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/example_3/test/TestProductionCode2.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,31 @@
+
+#include "ProductionCode2.h"
+#include "unity.h"
+
+/* These should be ignored because they are commented out in various ways:
+#include "whatever.h" 
+*/
+//#include "somethingelse.h"
+
+void setUp(void)
+{
+}
+
+void tearDown(void)
+{
+}
+
+void test_IgnoredTest(void)
+{
+    TEST_IGNORE_MESSAGE("This Test Was Ignored On Purpose");
+}
+
+void test_AnotherIgnoredTest(void)
+{
+    TEST_IGNORE_MESSAGE("These Can Be Useful For Leaving Yourself Notes On What You Need To Do Yet");
+}
+
+void test_ThisFunctionHasNotBeenTested_NeedsToBeImplemented(void)
+{
+    TEST_IGNORE(); //Like This
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/examples/unity_config.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,257 @@
+/* Unity Configuration
+ * As of May 11th, 2016 at ThrowTheSwitch/Unity commit 837c529
+ * See Also: Unity/docs/UnityConfigurationGuide.pdf
+ *
+ * Unity is designed to run on almost anything that is targeted by a C compiler.
+ * It would be awesome if this could be done with zero configuration. While
+ * there are some targets that come close to this dream, it is sadly not
+ * universal. It is likely that you are going to need at least a couple of the
+ * configuration options described in this document.
+ *
+ * All of Unity's configuration options are `#defines`. Most of these are simple
+ * definitions. A couple are macros with arguments. They live inside the
+ * unity_internals.h header file. We don't necessarily recommend opening that
+ * file unless you really need to. That file is proof that a cross-platform
+ * library is challenging to build. From a more positive perspective, it is also
+ * proof that a great deal of complexity can be centralized primarily to one
+ * place in order to provide a more consistent and simple experience elsewhere.
+ *
+ * Using These Options
+ * It doesn't matter if you're using a target-specific compiler and a simulator
+ * or a native compiler. In either case, you've got a couple choices for
+ * configuring these options:
+ *
+ *  1. Because these options are specified via C defines, you can pass most of
+ *     these options to your compiler through command line compiler flags. Even
+ *     if you're using an embedded target that forces you to use their
+ *     overbearing IDE for all configuration, there will be a place somewhere in
+ *     your project to configure defines for your compiler.
+ *  2. You can create a custom `unity_config.h` configuration file (present in
+ *     your toolchain's search paths). In this file, you will list definitions
+ *     and macros specific to your target. All you must do is define
+ *     `UNITY_INCLUDE_CONFIG_H` and Unity will rely on `unity_config.h` for any
+ *     further definitions it may need.
+ */
+
+#ifndef UNITY_CONFIG_H
+#define UNITY_CONFIG_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* ************************* AUTOMATIC INTEGER TYPES ***************************
+ * C's concept of an integer varies from target to target. The C Standard has
+ * rules about the `int` matching the register size of the target
+ * microprocessor. It has rules about the `int` and how its size relates to
+ * other integer types. An `int` on one target might be 16 bits while on another
+ * target it might be 64. There are more specific types in compilers compliant
+ * with C99 or later, but that's certainly not every compiler you are likely to
+ * encounter. Therefore, Unity has a number of features for helping to adjust
+ * itself to match your required integer sizes. It starts off by trying to do it
+ * automatically.
+ **************************************************************************** */
+
+/* The first thing that Unity does to guess your types is check `stdint.h`. This
+ * file includes defines like `UINT_MAX` that Unity can make use of to learn a
+ * lot about your system. It's possible you don't want it to do this or it's
+ * possible that your system doesn't support `stdint.h`. If that's the case,
+ * you're going to want to define this. That way, Unity will know to skip the
+ * inclusion of this file and you won't be left with a compiler error.
+ */
+/* #define UNITY_EXCLUDE_STDINT_H */
+
+/* The second attempt to guess your types is to check `limits.h`. Some compilers
+ * that don't support `stdint.h` could include `limits.h` instead. If you don't
+ * want Unity to check this file either, define this to make it skip the
+ * inclusion.
+ */
+/* #define UNITY_EXCLUDE_LIMITS_H */
+
+/* The third and final attempt to guess your types is to use the `sizeof()`
+ * operator. Even if the first two options don't work, this one covers most
+ * cases. There _is_ a rare compiler or two out there that doesn't support
+ * `sizeof()` in the preprocessing stage, though. For these, you have the
+ * ability to disable this feature as well.
+ */
+/* #define UNITY_EXCLUDE_SIZEOF */
+
+
+/* ********************** MANUAL INTEGER TYPE DEFINITION ***********************
+ * If you've disabled all of the automatic options above, you're going to have
+ * to do the configuration yourself. There are just a handful of defines that
+ * you are going to specify if you don't like the defaults.
+ **************************************************************************** */
+
+ /* Define this to be the number of bits an `int` takes up on your system. The
+ * default, if not auto-detected, is 32 bits.
+ *
+ * Example:
+ */
+/* #define UNITY_INT_WIDTH 16 */
+
+/* Define this to be the number of bits a `long` takes up on your system. The
+ * default, if not autodetected, is 32 bits. This is used to figure out what
+ * kind of 64-bit support your system can handle.  Does it need to specify a
+ * `long` or a `long long` to get a 64-bit value. On 16-bit systems, this option
+ * is going to be ignored.
+ *
+ * Example:
+ */
+/* #define UNITY_LONG_WIDTH 16 */
+
+/* Define this to be the number of bits a pointer takes up on your system. The
+ * default, if not autodetected, is 32-bits. If you're getting ugly compiler
+ * warnings about casting from pointers, this is the one to look at.
+ *
+ * Example:
+ */
+/* #define UNITY_POINTER_WIDTH 64 */
+
+/* Unity will automatically include 64-bit support if it auto-detects it, or if
+ * your `int`, `long`, or pointer widths are greater than 32-bits. Define this
+ * to enable 64-bit support if none of the other options already did it for you.
+ * There can be a significant size and speed impact to enabling 64-bit support
+ * on small targets, so don't define it if you don't need it.
+ */
+/* #define UNITY_INCLUDE_64 */
+
+
+/* *************************** FLOATING POINT TYPES ****************************
+ * In the embedded world, it's not uncommon for targets to have no support for
+ * floating point operations at all or to have support that is limited to only
+ * single precision. We are able to guess integer sizes on the fly because
+ * integers are always available in at least one size. Floating point, on the
+ * other hand, is sometimes not available at all. Trying to include `float.h` on
+ * these platforms would result in an error. This leaves manual configuration as
+ * the only option.
+ **************************************************************************** */
+
+ /* By default, Unity guesses that you will want single precision floating point
+  * support, but not double precision. It's easy to change either of these using
+  * the include and exclude options here. You may include neither, either, or
+  * both, as suits your needs.
+  */
+/* #define UNITY_INCLUDE_FLOAT  */
+/* #define UNITY_EXCLUDE_FLOAT  */
+/* #define UNITY_INCLUDE_DOUBLE */
+/* #define UNITY_EXCLUDE_DOUBLE */
+
+/* For features that are enabled, the following floating point options also
+ * become available.
+ */
+
+/* Unity aims for as small of a footprint as possible and avoids most standard
+ * library calls (some embedded platforms don't have a standard library!).
+ * Because of this, its routines for printing integer values are minimalist and
+ * hand-coded. To keep Unity universal, though, we chose to _not_ develop our
+ * own floating point print routines. Instead, the display of floating point
+ * values during a failure are optional. By default, Unity will not print the
+ * actual results of floating point assertion failure. So a failed assertion
+ * will produce a message like `"Values Not Within Delta"`. If you would like
+ * verbose failure messages for floating point assertions, use these options to
+ * give more explicit failure messages (e.g. `"Expected 4.56 Was 4.68"`). Note
+ * that this feature requires the use of `sprintf` so might not be desirable in
+ * all cases.
+ */
+/* #define UNITY_FLOAT_VERBOSE  */
+/* #define UNITY_DOUBLE_VERBOSE */
+
+/* If enabled, Unity assumes you want your `FLOAT` asserts to compare standard C
+ * floats. If your compiler supports a specialty floating point type, you can
+ * always override this behavior by using this definition.
+ *
+ * Example:
+ */
+/* #define UNITY_FLOAT_TYPE float16_t */
+
+/* If enabled, Unity assumes you want your `DOUBLE` asserts to compare standard
+ * C doubles. If you would like to change this, you can specify something else
+ * by using this option. For example, defining `UNITY_DOUBLE_TYPE` to `long
+ * double` could enable gargantuan floating point types on your 64-bit processor
+ * instead of the standard `double`.
+ *
+ * Example:
+ */
+/* #define UNITY_DOUBLE_TYPE long double */
+
+/* If you look up `UNITY_ASSERT_EQUAL_FLOAT` and `UNITY_ASSERT_EQUAL_DOUBLE` as
+ * documented in the Unity Assertion Guide, you will learn that they are not
+ * really asserting that two values are equal but rather that two values are
+ * "close enough" to equal. "Close enough" is controlled by these precision
+ * configuration options. If you are working with 32-bit floats and/or 64-bit
+ * doubles (the normal on most processors), you should have no need to change
+ * these options. They are both set to give you approximately 1 significant bit
+ * in either direction. The float precision is 0.00001 while the double is
+ * 10^-12. For further details on how this works, see the appendix of the Unity
+ * Assertion Guide.
+ *
+ * Example:
+ */
+/* #define UNITY_FLOAT_PRECISION 0.001f  */
+/* #define UNITY_DOUBLE_PRECISION 0.001f */
+
+
+/* *************************** TOOLSET CUSTOMIZATION ***************************
+ * In addition to the options listed above, there are a number of other options
+ * which will come in handy to customize Unity's behavior for your specific
+ * toolchain. It is possible that you may not need to touch any of these but
+ * certain platforms, particularly those running in simulators, may need to jump
+ * through extra hoops to operate properly. These macros will help in those
+ * situations.
+ **************************************************************************** */
+
+/* By default, Unity prints its results to `stdout` as it runs. This works
+ * perfectly fine in most situations where you are using a native compiler for
+ * testing. It works on some simulators as well so long as they have `stdout`
+ * routed back to the command line. There are times, however, where the
+ * simulator will lack support for dumping results or you will want to route
+ * results elsewhere for other reasons. In these cases, you should define the
+ * `UNITY_OUTPUT_CHAR` macro. This macro accepts a single character at a time
+ * (as an `int`, since this is the parameter type of the standard C `putchar`
+ * function most commonly used). You may replace this with whatever function
+ * call you like.
+ *
+ * Example:
+ * Say you are forced to run your test suite on an embedded processor with no
+ * `stdout` option. You decide to route your test result output to a custom
+ * serial `RS232_putc()` function you wrote like thus:
+ */
+/* #define UNITY_OUTPUT_CHAR(a)    RS232_putc(a) */
+/* #define UNITY_OUTPUT_FLUSH()    RS232_config(115200,1,8,0) */
+/* #define UNITY_OUTPUT_START()    RS232_flush() */
+/* #define UNITY_OUTPUT_COMPLETE() RS232_close() */
+
+/* For some targets, Unity can make the otherwise required `setUp()` and
+ * `tearDown()` functions optional. This is a nice convenience for test writers
+ * since `setUp` and `tearDown` don't often actually _do_ anything. If you're
+ * using gcc or clang, this option is automatically defined for you. Other
+ * compilers can also support this behavior, if they support a C feature called
+ * weak functions. A weak function is a function that is compiled into your
+ * executable _unless_ a non-weak version of the same function is defined
+ * elsewhere. If a non-weak version is found, the weak version is ignored as if
+ * it never existed. If your compiler supports this feature, you can let Unity
+ * know by defining `UNITY_SUPPORT_WEAK` as the function attributes that would
+ * need to be applied to identify a function as weak. If your compiler lacks
+ * support for weak functions, you will always need to define `setUp` and
+ * `tearDown` functions (though they can be and often will be just empty). The
+ * most common options for this feature are:
+ */
+/* #define UNITY_SUPPORT_WEAK weak */
+/* #define UNITY_SUPPORT_WEAK __attribute__((weak)) */
+
+/* Some compilers require a custom attribute to be assigned to pointers, like
+ * `near` or `far`. In these cases, you can give Unity a safe default for these
+ * by defining this option with the attribute you would like.
+ *
+ * Example:
+ */
+/* #define UNITY_PTR_ATTRIBUTE __attribute__((far)) */
+/* #define UNITY_PTR_ATTRIBUTE near */
+
+#ifdef __cplusplus
+}
+#endif /* extern "C" */
+
+#endif /* UNITY_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/eclipse/error_parsers.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,26 @@
+Eclipse error parsers
+=====================
+
+These are a godsend for extracting  & quickly navigating to
+warnings & error messages from console output. Unforunately
+I don't know how to write an Eclipse plugin so you'll have
+to add them manually.
+
+To add a console parser to Eclipse, go to Window --> Preferences
+--> C/C++ --> Build --> Settings. Click on the 'Error Parsers'
+tab and then click the 'Add...' button. See the table below for
+the parser fields to add.
+
+Eclipse will only parse the console output during a build, so
+running your unit tests must be part of your build process.
+Either add this to your make/rakefile, or add it as a post-
+build step in your Eclipse project settings.
+
+
+Unity unit test error parsers
+-----------------------------
+Severity    Pattern                                 File    Line    Description
+-------------------------------------------------------------------------------
+Error       (\.+)(.*?):(\d+):(.*?):FAIL: (.*)       $2      $3      $5
+Warning     (\.+)(.*?):(\d+):(.*?):IGNORE: (.*)     $2      $3      $5
+Warning     (\.+)(.*?):(\d+):(.*?):IGNORE\s*$       $2      $3      Ignored test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/rakefile.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,48 @@
+# ==========================================
+#   Unity Project - A Test Framework for C
+#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+#   [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+HERE = File.expand_path(File.dirname(__FILE__)) + '/'
+
+require 'rake'
+require 'rake/clean'
+require 'rake/testtask'
+require HERE + 'rakefile_helper'
+
+TEMP_DIRS = [
+    File.join(HERE, 'build')
+]
+
+TEMP_DIRS.each do |dir|
+  directory(dir)
+  CLOBBER.include(dir)
+end
+
+task :prepare_for_tests => TEMP_DIRS
+
+include RakefileHelpers
+
+# Load default configuration, for now
+DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml'
+configure_toolchain(DEFAULT_CONFIG_FILE)
+
+task :unit => [:prepare_for_tests] do
+  run_tests
+end
+
+desc "Build and test Unity Framework"
+task :all => [:clean, :unit]
+task :default => [:clobber, :all]
+task :ci => [:no_color, :default]
+task :cruise => [:no_color, :default]
+
+desc "Load configuration"
+task :config, :config_file do |t, args|
+  configure_toolchain(args[:config_file])
+end
+
+task :no_color do
+  $colour_output = false
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/rakefile_helper.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,179 @@
+# ==========================================
+#   Unity Project - A Test Framework for C
+#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+#   [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+require 'yaml'
+require 'fileutils'
+require HERE+'../../auto/unity_test_summary'
+require HERE+'../../auto/generate_test_runner'
+require HERE+'../../auto/colour_reporter'
+
+module RakefileHelpers
+
+  C_EXTENSION = '.c'
+
+  def load_configuration(config_file)
+    unless ($configured)
+      $cfg_file = HERE+"../../test/targets/#{config_file}" unless (config_file =~ /[\\|\/]/)
+      $cfg = YAML.load(File.read($cfg_file))
+      $colour_output = false unless $cfg['colour']
+      $configured = true if (config_file != DEFAULT_CONFIG_FILE)
+    end
+  end
+
+  def configure_clean
+    CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil?
+  end
+
+  def configure_toolchain(config_file=DEFAULT_CONFIG_FILE)
+    config_file += '.yml' unless config_file =~ /\.yml$/
+    config_file = config_file unless config_file =~ /[\\|\/]/
+    load_configuration(config_file)
+    configure_clean
+  end
+
+  def tackit(strings)
+    if strings.is_a?(Array)
+      result = "\"#{strings.join}\""
+    else
+      result = strings
+    end
+    return result
+  end
+
+  def squash(prefix, items)
+    result = ''
+    items.each { |item| result += " #{prefix}#{tackit(item)}" }
+    return result
+  end
+
+  def build_compiler_fields
+    command  = tackit($cfg['compiler']['path'])
+    if $cfg['compiler']['defines']['items'].nil?
+      defines  = ''
+    else
+      defines  = squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar'])
+    end
+    options  = squash('', $cfg['compiler']['options'])
+    includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])
+    includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
+    return {:command => command, :defines => defines, :options => options, :includes => includes}
+  end
+
+  def compile(file, defines=[])
+    compiler = build_compiler_fields
+    unity_include = $cfg['compiler']['includes']['prefix']+'../../src'
+    cmd_str = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{unity_include} #{file} " +
+      "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}" +
+      "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}"
+    execute(cmd_str)
+  end
+
+  def build_linker_fields
+    command  = tackit($cfg['linker']['path'])
+    if $cfg['linker']['options'].nil?
+      options  = ''
+    else
+      options  = squash('', $cfg['linker']['options'])
+    end
+    if ($cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?)
+      includes = ''
+    else
+      includes = squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items'])
+    end
+    includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
+    return {:command => command, :options => options, :includes => includes}
+  end
+
+  def link_it(exe_name, obj_list)
+    linker = build_linker_fields
+    cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " +
+      (obj_list.map{|obj|"#{$cfg['linker']['object_files']['path']}#{obj} "}).join +
+      $cfg['linker']['bin_files']['prefix'] + ' ' +
+      $cfg['linker']['bin_files']['destination'] +
+      exe_name + $cfg['linker']['bin_files']['extension']
+    execute(cmd_str)
+  end
+
+  def build_simulator_fields
+    return nil if $cfg['simulator'].nil?
+    if $cfg['simulator']['path'].nil?
+      command = ''
+    else
+      command = (tackit($cfg['simulator']['path']) + ' ')
+    end
+    if $cfg['simulator']['pre_support'].nil?
+      pre_support = ''
+    else
+      pre_support = squash('', $cfg['simulator']['pre_support'])
+    end
+    if $cfg['simulator']['post_support'].nil?
+      post_support = ''
+    else
+      post_support = squash('', $cfg['simulator']['post_support'])
+    end
+    return {:command => command, :pre_support => pre_support, :post_support => post_support}
+  end
+
+  def execute(command_string, verbose=true)
+    report command_string
+    output = `#{command_string}`.chomp
+    report(output) if (verbose && !output.nil? && (output.length > 0))
+    if ($?.exitstatus != 0)
+      raise "Command failed. (Returned #{$?.exitstatus})"
+    end
+    return output
+  end
+
+  def report_summary
+    summary = UnityTestSummary.new
+    summary.set_root_path(HERE)
+    results_glob = "#{$cfg['compiler']['build_path']}*.test*"
+    results_glob.gsub!(/\\/, '/')
+    results = Dir[results_glob]
+    summary.set_targets(results)
+    summary.run
+  end
+
+  def run_tests
+    report 'Running Unity system tests...'
+
+    # Tack on TEST define for compiling unit tests
+    load_configuration($cfg_file)
+    test_defines = ['TEST']
+    $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil?
+
+    # Get a list of all source files needed
+    src_files  = Dir[HERE+'src/*.c']
+    src_files += Dir[HERE+'test/*.c']
+    src_files += Dir[HERE+'test/main/*.c']
+    src_files << '../../src/unity.c'
+
+    # Build object files
+    src_files.each { |f| compile(f, test_defines) }
+    obj_list = src_files.map {|f| File.basename(f.ext($cfg['compiler']['object_files']['extension'])) }
+
+    # Link the test executable
+    test_base = "framework_test"
+    link_it(test_base, obj_list)
+
+    # Execute unit test and generate results file
+    simulator = build_simulator_fields
+    executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension']
+    if simulator.nil?
+      cmd_str = executable + " -v -r"
+    else
+      cmd_str = "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}"
+    end
+    output = execute(cmd_str)
+    test_results = $cfg['compiler']['build_path'] + test_base
+    if output.match(/OK$/m).nil?
+      test_results += '.testfail'
+    else
+      test_results += '.testpass'
+    end
+    File.open(test_results, 'w') { |f| f.print output }
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/readme.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,9 @@
+Copyright (c) 2010 James Grenning and Contributed to Unity Project
+
+Unity Project - A Test Framework for C
+Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+[Released under MIT License. Please refer to license.txt for details]
+
+This Framework is an optional add-on to Unity.  By including unity_framework.h in place of unity.h,
+you may now work with Unity in a manner similar to CppUTest.  This framework adds the concepts of 
+test groups and gives finer control of your tests over the command line.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/src/unity_fixture.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,456 @@
+//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#include <string.h>
+#include "unity_fixture.h"
+#include "unity_internals.h"
+
+#define UNITY_RESULTS_TAGS_TEST_START   "<***UnityTest***>"
+#define UNITY_RESULTS_TAGS_TEST_END     "</***UnityTest***>"
+
+#define UNITY_RESULTS_TAGS_RESULT_START "<***UnityResult***>"
+#define UNITY_RESULTS_TAGS_RESULT_END   "</***UnityResult***>"
+
+#define UNITY_RESULTS_TAGS_IGNORE_START "<***UnityIgnoredTest***>"
+#define UNITY_RESULTS_TAGS_IGNORE_END   "</***UnityIgnoredTest***>"
+
+struct _UnityFixture UnityFixture;
+
+//If you decide to use the function pointer approach.
+//Build with -D UNITY_OUTPUT_CHAR=outputChar and include <stdio.h>
+//int (*outputChar)(int) = putchar;
+
+#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA)
+void setUp(void)    { /*does nothing*/ }
+void tearDown(void) { /*does nothing*/ }
+#endif
+
+static void announceTestRun(unsigned int runNumber)
+{
+    UnityPrint("Unity test run ");
+    UnityPrintNumberUnsigned(runNumber+1);
+    UnityPrint(" of ");
+    UnityPrintNumberUnsigned(UnityFixture.RepeatCount);
+    UNITY_PRINT_EOL();
+}
+
+int UnityMain(int argc, const char* argv[], void (*runAllTests)(void))
+{
+    int result = UnityGetCommandLineOptions(argc, argv);
+    unsigned int r;
+    if (result != 0)
+        return result;
+
+    for (r = 0; r < UnityFixture.RepeatCount; r++)
+    {
+        UnityBegin(argv[0]);
+        announceTestRun(r);
+        runAllTests();
+        UNITY_PRINT_EOL();
+        UnityEnd();
+    }
+
+    return (int)Unity.TestFailures;
+}
+
+static int selected(const char* filter, const char* name)
+{
+    if (filter == 0)
+        return 1;
+    return strstr(name, filter) ? 1 : 0;
+}
+
+static int testSelected(const char* test)
+{
+    return selected(UnityFixture.NameFilter, test);
+}
+
+static int groupSelected(const char* group)
+{
+    return selected(UnityFixture.GroupFilter, group);
+}
+
+void UnityTestRunner(unityfunction* setup,
+                     unityfunction* testBody,
+                     unityfunction* teardown,
+                     const char* printableName,
+                     const char* group,
+                     const char* name,
+                     const char* file, unsigned int line)
+{
+    if (testSelected(name) && groupSelected(group))
+    {
+        Unity.TestFile = file;
+        Unity.CurrentTestName = printableName;
+        Unity.CurrentTestLineNumber = line;
+        if (!UnityFixture.Verbose)
+            UNITY_OUTPUT_CHAR('.');
+        else
+        {
+            /* SA_PATCH: Output results using easy to parse tags. */
+            UnityPrint(UNITY_RESULTS_TAGS_TEST_START);
+            UnityPrint(printableName);
+            /* SA_PATCH: Output results using easy to parse tags. */
+            UnityPrint(UNITY_RESULTS_TAGS_TEST_END);
+           //UnityPrint(printableName);
+        }
+
+        Unity.NumberOfTests++;
+        UnityMalloc_StartTest();
+        UnityPointer_Init();
+
+        if (TEST_PROTECT())
+        {
+            setup();
+            testBody();
+        }
+        if (TEST_PROTECT())
+        {
+            teardown();
+        }
+        if (TEST_PROTECT())
+        {
+            UnityPointer_UndoAllSets();
+            if (!Unity.CurrentTestFailed)
+                UnityMalloc_EndTest();
+        }
+        UnityConcludeFixtureTest();
+    }
+}
+
+void UnityIgnoreTest(const char* printableName, const char* group, const char* name)
+{
+    if (testSelected(name) && groupSelected(group))
+    {
+        Unity.NumberOfTests++;
+        Unity.TestIgnores++;
+        if (!UnityFixture.Verbose)
+            UNITY_OUTPUT_CHAR('!');
+        else
+        {
+            /* SA_PATCH: Output results using easy to parse tags. */
+            UnityPrint(UNITY_RESULTS_TAGS_IGNORE_START);
+            UnityPrint(printableName);
+            /* SA_PATCH: Output results using easy to parse tags. */
+            UnityPrint(UNITY_RESULTS_TAGS_IGNORE_END);
+            //UnityPrint(printableName);
+            //UNITY_PRINT_EOL();
+        }
+    }
+}
+
+
+//-------------------------------------------------
+//Malloc and free stuff
+//
+#define MALLOC_DONT_FAIL -1
+static int malloc_count;
+static int malloc_fail_countdown = MALLOC_DONT_FAIL;
+
+void UnityMalloc_StartTest(void)
+{
+    malloc_count = 0;
+    malloc_fail_countdown = MALLOC_DONT_FAIL;
+}
+
+void UnityMalloc_EndTest(void)
+{
+    malloc_fail_countdown = MALLOC_DONT_FAIL;
+    if (malloc_count != 0)
+    {
+        UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "This test leaks!");
+    }
+}
+
+void UnityMalloc_MakeMallocFailAfterCount(int countdown)
+{
+    malloc_fail_countdown = countdown;
+}
+
+// These definitions are always included from unity_fixture_malloc_overrides.h
+// We undef to use them or avoid conflict with <stdlib.h> per the C standard
+#undef malloc
+#undef free
+#undef calloc
+#undef realloc
+
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+static unsigned char unity_heap[UNITY_INTERNAL_HEAP_SIZE_BYTES];
+static size_t heap_index;
+#else
+#include <stdlib.h>
+#endif
+
+typedef struct GuardBytes
+{
+    size_t size;
+    size_t guard_space;
+} Guard;
+
+
+static const char end[] = "END";
+
+void* unity_malloc(size_t size)
+{
+    char* mem;
+    Guard* guard;
+    size_t total_size = size + sizeof(Guard) + sizeof(end);
+
+    if (malloc_fail_countdown != MALLOC_DONT_FAIL)
+    {
+        if (malloc_fail_countdown == 0)
+            return NULL;
+        malloc_fail_countdown--;
+    }
+
+    if (size == 0) return NULL;
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+    if (heap_index + total_size > UNITY_INTERNAL_HEAP_SIZE_BYTES)
+    {
+        guard = NULL;
+    }
+    else
+    {
+        guard = (Guard*) &unity_heap[heap_index];
+        heap_index += total_size;
+    }
+#else
+    guard = (Guard*)UNITY_FIXTURE_MALLOC(total_size);
+#endif
+    if (guard == NULL) return NULL;
+    malloc_count++;
+    guard->size = size;
+    guard->guard_space = 0;
+    mem = (char*)&(guard[1]);
+    memcpy(&mem[size], end, sizeof(end));
+
+    return (void*)mem;
+}
+
+static int isOverrun(void* mem)
+{
+    Guard* guard = (Guard*)mem;
+    char* memAsChar = (char*)mem;
+    guard--;
+
+    return guard->guard_space != 0 || strcmp(&memAsChar[guard->size], end) != 0;
+}
+
+static void release_memory(void* mem)
+{
+    Guard* guard = (Guard*)mem;
+    guard--;
+
+    malloc_count--;
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+    if (mem == unity_heap + heap_index - guard->size - sizeof(end))
+    {
+        heap_index -= (guard->size + sizeof(Guard) + sizeof(end));
+    }
+#else
+    UNITY_FIXTURE_FREE(guard);
+#endif
+}
+
+void unity_free(void* mem)
+{
+    int overrun;
+
+    if (mem == NULL)
+    {
+        return;
+    }
+
+    overrun = isOverrun(mem);
+    release_memory(mem);
+    if (overrun)
+    {
+        UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during free()");
+    }
+}
+
+void* unity_calloc(size_t num, size_t size)
+{
+    void* mem = unity_malloc(num * size);
+    if (mem == NULL) return NULL;
+    memset(mem, 0, num * size);
+    return mem;
+}
+
+void* unity_realloc(void* oldMem, size_t size)
+{
+    Guard* guard = (Guard*)oldMem;
+    void* newMem;
+
+    if (oldMem == NULL) return unity_malloc(size);
+
+    guard--;
+    if (isOverrun(oldMem))
+    {
+        release_memory(oldMem);
+        UNITY_TEST_FAIL(Unity.CurrentTestLineNumber, "Buffer overrun detected during realloc()");
+    }
+
+    if (size == 0)
+    {
+        release_memory(oldMem);
+        return NULL;
+    }
+
+    if (guard->size >= size) return oldMem;
+
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC // Optimization if memory is expandable
+    if (oldMem == unity_heap + heap_index - guard->size - sizeof(end) &&
+        heap_index + size - guard->size <= UNITY_INTERNAL_HEAP_SIZE_BYTES)
+    {
+        release_memory(oldMem); // Not thread-safe, like unity_heap generally
+        return unity_malloc(size); // No memcpy since data is in place
+    }
+#endif
+    newMem = unity_malloc(size);
+    if (newMem == NULL) return NULL; // Do not release old memory
+    memcpy(newMem, oldMem, guard->size);
+    release_memory(oldMem);
+    return newMem;
+}
+
+
+//--------------------------------------------------------
+//Automatic pointer restoration functions
+struct PointerPair
+{
+    void** pointer;
+    void* old_value;
+};
+
+enum { MAX_POINTERS = 50 };
+static struct PointerPair pointer_store[MAX_POINTERS];
+static int pointer_index = 0;
+
+void UnityPointer_Init(void)
+{
+    pointer_index = 0;
+}
+
+void UnityPointer_Set(void** pointer, void* newValue, UNITY_LINE_TYPE line)
+{
+    if (pointer_index >= MAX_POINTERS)
+    {
+        UNITY_TEST_FAIL(line, "Too many pointers set");
+    }
+    else
+    {
+        pointer_store[pointer_index].pointer = pointer;
+        pointer_store[pointer_index].old_value = *pointer;
+        *pointer = newValue;
+        pointer_index++;
+    }
+}
+
+void UnityPointer_UndoAllSets(void)
+{
+    while (pointer_index > 0)
+    {
+        pointer_index--;
+        *(pointer_store[pointer_index].pointer) =
+            pointer_store[pointer_index].old_value;
+    }
+}
+
+int UnityGetCommandLineOptions(int argc, const char* argv[])
+{
+    int i;
+    UnityFixture.Verbose = 0;
+    UnityFixture.GroupFilter = 0;
+    UnityFixture.NameFilter = 0;
+    UnityFixture.RepeatCount = 1;
+
+    if (argc == 1)
+        return 0;
+
+    for (i = 1; i < argc; )
+    {
+        if (strcmp(argv[i], "-v") == 0)
+        {
+            UnityFixture.Verbose = 1;
+            i++;
+        }
+        else if (strcmp(argv[i], "-g") == 0)
+        {
+            i++;
+            if (i >= argc)
+                return 1;
+            UnityFixture.GroupFilter = argv[i];
+            i++;
+        }
+        else if (strcmp(argv[i], "-n") == 0)
+        {
+            i++;
+            if (i >= argc)
+                return 1;
+            UnityFixture.NameFilter = argv[i];
+            i++;
+        }
+        else if (strcmp(argv[i], "-r") == 0)
+        {
+            UnityFixture.RepeatCount = 2;
+            i++;
+            if (i < argc)
+            {
+                if (*(argv[i]) >= '0' && *(argv[i]) <= '9')
+                {
+                    unsigned int digit = 0;
+                    UnityFixture.RepeatCount = 0;
+                    while (argv[i][digit] >= '0' && argv[i][digit] <= '9')
+                    {
+                        UnityFixture.RepeatCount *= 10;
+                        UnityFixture.RepeatCount += (unsigned int)argv[i][digit++] - '0';
+                    }
+                    i++;
+                }
+            }
+        } else {
+            // ignore unknown parameter
+            i++;
+        }
+    }
+    return 0;
+}
+
+void UnityConcludeFixtureTest(void)
+{
+    if (Unity.CurrentTestIgnored)
+    {
+        Unity.TestIgnores++;
+        UNITY_PRINT_EOL();
+    }
+    else if (!Unity.CurrentTestFailed)
+    {
+        if (UnityFixture.Verbose)
+        {
+            UnityPrint(" ");
+            /* SA_PATCH: Output results using easy to parse tags. */
+            UnityPrint(UNITY_RESULTS_TAGS_RESULT_START);
+            UnityPrint("PASS");
+            /* SA_PATCH: Output results using easy to parse tags. */
+            UnityPrint(UNITY_RESULTS_TAGS_RESULT_END);
+            UNITY_OUTPUT_CHAR('\n');
+        }
+//        {
+//            UnityPrint(" PASS");
+//            UNITY_PRINT_EOL();
+//        }
+    }
+    else // Unity.CurrentTestFailed
+    {
+        Unity.TestFailures++;
+        UNITY_PRINT_EOL();
+    }
+
+    Unity.CurrentTestFailed = 0;
+    Unity.CurrentTestIgnored = 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/src/unity_fixture.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,78 @@
+//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef UNITY_FIXTURE_H_
+#define UNITY_FIXTURE_H_
+
+#include "unity.h"
+#include "unity_internals.h"
+#include "unity_fixture_malloc_overrides.h"
+#include "unity_fixture_internals.h"
+
+int UnityMain(int argc, const char* argv[], void (*runAllTests)(void));
+
+
+#define TEST_GROUP(group)\
+    static const char* TEST_GROUP_##group = #group
+
+#define TEST_SETUP(group) void TEST_##group##_SETUP(void);\
+    void TEST_##group##_SETUP(void)
+
+#define TEST_TEAR_DOWN(group) void TEST_##group##_TEAR_DOWN(void);\
+    void TEST_##group##_TEAR_DOWN(void)
+
+
+#define TEST(group, name) \
+    void TEST_##group##_##name##_(void);\
+    void TEST_##group##_##name##_run(void);\
+    void TEST_##group##_##name##_run(void)\
+    {\
+        UnityTestRunner(TEST_##group##_SETUP,\
+            TEST_##group##_##name##_,\
+            TEST_##group##_TEAR_DOWN,\
+            "TEST(" #group ", " #name ")",\
+            TEST_GROUP_##group, #name,\
+            __FILE__, __LINE__);\
+    }\
+    void  TEST_##group##_##name##_(void)
+
+#define IGNORE_TEST(group, name) \
+    void TEST_##group##_##name##_(void);\
+    void TEST_##group##_##name##_run(void);\
+    void TEST_##group##_##name##_run(void)\
+    {\
+        UnityIgnoreTest("IGNORE_TEST(" #group ", " #name ")", TEST_GROUP_##group, #name);\
+    }\
+    void TEST_##group##_##name##_(void)
+
+#define RUN_TEST_CASE(group, name) \
+    { void TEST_##group##_##name##_run(void);\
+      TEST_##group##_##name##_run(); }
+
+//This goes at the bottom of each test file or in a separate c file
+#define TEST_GROUP_RUNNER(group)\
+    void TEST_##group##_GROUP_RUNNER(void);\
+    void TEST_##group##_GROUP_RUNNER(void)
+
+//Call this from main
+#define RUN_TEST_GROUP(group)\
+    { void TEST_##group##_GROUP_RUNNER(void);\
+      TEST_##group##_GROUP_RUNNER(); }
+
+//CppUTest Compatibility Macros
+#define UT_PTR_SET(ptr, newPointerValue)               UnityPointer_Set((void**)&(ptr), (void*)(newPointerValue), __LINE__)
+#define TEST_ASSERT_POINTERS_EQUAL(expected, actual)   TEST_ASSERT_EQUAL_PTR((expected), (actual))
+#define TEST_ASSERT_BYTES_EQUAL(expected, actual)      TEST_ASSERT_EQUAL_HEX8(0xff & (expected), 0xff & (actual))
+#define FAIL(message)                                  TEST_FAIL_MESSAGE((message))
+#define CHECK(condition)                               TEST_ASSERT_TRUE((condition))
+#define LONGS_EQUAL(expected, actual)                  TEST_ASSERT_EQUAL_INT((expected), (actual))
+#define STRCMP_EQUAL(expected, actual)                 TEST_ASSERT_EQUAL_STRING((expected), (actual))
+#define DOUBLES_EQUAL(expected, actual, delta)         TEST_ASSERT_FLOAT_WITHIN(((expected), (actual), (delta))
+
+void UnityMalloc_MakeMallocFailAfterCount(int count);
+
+#endif /* UNITY_FIXTURE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/src/unity_fixture_internals.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,39 @@
+//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef UNITY_FIXTURE_INTERNALS_H_
+#define UNITY_FIXTURE_INTERNALS_H_
+
+struct _UnityFixture
+{
+    int Verbose;
+    unsigned int RepeatCount;
+    const char* NameFilter;
+    const char* GroupFilter;
+};
+extern struct _UnityFixture UnityFixture;
+
+typedef void unityfunction(void);
+void UnityTestRunner(unityfunction* setup,
+                     unityfunction* body,
+                     unityfunction* teardown,
+                     const char* printableName,
+                     const char* group,
+                     const char* name,
+                     const char* file, unsigned int line);
+
+void UnityIgnoreTest(const char* printableName, const char* group, const char* name);
+void UnityMalloc_StartTest(void);
+void UnityMalloc_EndTest(void);
+int UnityGetCommandLineOptions(int argc, const char* argv[]);
+void UnityConcludeFixtureTest(void);
+
+void UnityPointer_Set(void** ptr, void* newValue, UNITY_LINE_TYPE line);
+void UnityPointer_UndoAllSets(void);
+void UnityPointer_Init(void);
+
+#endif /* UNITY_FIXTURE_INTERNALS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/src/unity_fixture_malloc_overrides.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,46 @@
+//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef UNITY_FIXTURE_MALLOC_OVERRIDES_H_
+#define UNITY_FIXTURE_MALLOC_OVERRIDES_H_
+
+#include <stddef.h>
+
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+// Define this macro to remove the use of stdlib.h, malloc, and free.
+// Many embedded systems do not have a heap or malloc/free by default.
+// This internal unity_malloc() provides allocated memory deterministically from
+// the end of an array only, unity_free() only releases from end-of-array,
+// blocks are not coalesced, and memory not freed in LIFO order is stranded.
+    #ifndef UNITY_INTERNAL_HEAP_SIZE_BYTES
+    #define UNITY_INTERNAL_HEAP_SIZE_BYTES 256
+    #endif
+#endif
+
+// These functions are used by the Unity Fixture to allocate and release memory
+// on the heap and can be overridden with platform-specific implementations.
+// For example, when using FreeRTOS UNITY_FIXTURE_MALLOC becomes pvPortMalloc()
+// and UNITY_FIXTURE_FREE becomes vPortFree().
+#if !defined(UNITY_FIXTURE_MALLOC) || !defined(UNITY_FIXTURE_FREE)
+    #define UNITY_FIXTURE_MALLOC(size) malloc(size)
+    #define UNITY_FIXTURE_FREE(ptr)    free(ptr)
+#else
+    extern void* UNITY_FIXTURE_MALLOC(size_t size);
+    extern void UNITY_FIXTURE_FREE(void* ptr);
+#endif
+
+#define malloc  unity_malloc
+#define calloc  unity_calloc
+#define realloc unity_realloc
+#define free    unity_free
+
+void* unity_malloc(size_t size);
+void* unity_calloc(size_t num, size_t size);
+void* unity_realloc(void * oldMem, size_t size);
+void unity_free(void * mem);
+
+#endif /* UNITY_FIXTURE_MALLOC_OVERRIDES_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/test/main/AllTests.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,22 @@
+//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#include "unity_fixture.h"
+
+static void runAllTests(void)
+{
+    RUN_TEST_GROUP(UnityFixture);
+    RUN_TEST_GROUP(UnityCommandOptions);
+    RUN_TEST_GROUP(LeakDetection);
+    RUN_TEST_GROUP(InternalMalloc);
+}
+
+int main(int argc, const char* argv[])
+{
+    return UnityMain(argc, argv, runAllTests);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/test/template_fixture_tests.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,39 @@
+//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#include "unity_fixture.h"
+
+static int data = -1;
+
+TEST_GROUP(mygroup);
+
+TEST_SETUP(mygroup)
+{
+    data = 0;
+}
+
+TEST_TEAR_DOWN(mygroup)
+{
+    data = -1;
+}
+
+TEST(mygroup, test1)
+{
+    TEST_ASSERT_EQUAL_INT(0, data);
+}
+
+TEST(mygroup, test2)
+{
+    TEST_ASSERT_EQUAL_INT(0, data);
+    data = 5;
+}
+
+TEST(mygroup, test3)
+{
+    data = 7;
+    TEST_ASSERT_EQUAL_INT(7, data);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/test/unity_fixture_Test.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,533 @@
+//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#include "unity_fixture.h"
+#include "unity_output_Spy.h"
+#include <stdlib.h>
+#include <string.h>
+
+TEST_GROUP(UnityFixture);
+
+TEST_SETUP(UnityFixture)
+{
+}
+
+TEST_TEAR_DOWN(UnityFixture)
+{
+}
+
+static int* pointer1 = 0;
+static int* pointer2 = (int*)2;
+static int* pointer3 = (int*)3;
+static int int1;
+static int int2;
+static int int3;
+static int int4;
+
+TEST(UnityFixture, PointerSetting)
+{
+    TEST_ASSERT_POINTERS_EQUAL(pointer1, 0);
+    UT_PTR_SET(pointer1, &int1);
+    UT_PTR_SET(pointer2, &int2);
+    UT_PTR_SET(pointer3, &int3);
+    TEST_ASSERT_POINTERS_EQUAL(pointer1, &int1);
+    TEST_ASSERT_POINTERS_EQUAL(pointer2, &int2);
+    TEST_ASSERT_POINTERS_EQUAL(pointer3, &int3);
+    UT_PTR_SET(pointer1, &int4);
+    UnityPointer_UndoAllSets();
+    TEST_ASSERT_POINTERS_EQUAL(pointer1, 0);
+    TEST_ASSERT_POINTERS_EQUAL(pointer2, (int*)2);
+    TEST_ASSERT_POINTERS_EQUAL(pointer3, (int*)3);
+}
+
+TEST(UnityFixture, ForceMallocFail)
+{
+    void* m;
+    void* mfails;
+    UnityMalloc_MakeMallocFailAfterCount(1);
+    m = malloc(10);
+    CHECK(m);
+    mfails = malloc(10);
+    TEST_ASSERT_POINTERS_EQUAL(0, mfails);
+    free(m);
+}
+
+TEST(UnityFixture, ReallocSmallerIsUnchanged)
+{
+    void* m1 = malloc(10);
+    void* m2 = realloc(m1, 5);
+    TEST_ASSERT_POINTERS_EQUAL(m1, m2);
+    free(m2);
+}
+
+TEST(UnityFixture, ReallocSameIsUnchanged)
+{
+    void* m1 = malloc(10);
+    void* m2 = realloc(m1, 10);
+    TEST_ASSERT_POINTERS_EQUAL(m1, m2);
+    free(m2);
+}
+
+TEST(UnityFixture, ReallocLargerNeeded)
+{
+    void* m1 = malloc(10);
+    void* m2;
+    CHECK(m1);
+    strcpy((char*)m1, "123456789");
+    m2 = realloc(m1, 15);
+    // CHECK(m1 != m2); //Depends on implementation
+    STRCMP_EQUAL("123456789", m2);
+    free(m2);
+}
+
+TEST(UnityFixture, ReallocNullPointerIsLikeMalloc)
+{
+    void* m = realloc(0, 15);
+    CHECK(m != 0);
+    free(m);
+}
+
+TEST(UnityFixture, ReallocSizeZeroFreesMemAndReturnsNullPointer)
+{
+    void* m1 = malloc(10);
+    void* m2 = realloc(m1, 0);
+    TEST_ASSERT_POINTERS_EQUAL(0, m2);
+}
+
+TEST(UnityFixture, CallocFillsWithZero)
+{
+    void* m = calloc(3, sizeof(char));
+    char* s = (char*)m;
+    CHECK(m);
+    TEST_ASSERT_BYTES_EQUAL(0, s[0]);
+    TEST_ASSERT_BYTES_EQUAL(0, s[1]);
+    TEST_ASSERT_BYTES_EQUAL(0, s[2]);
+    free(m);
+}
+
+static char *p1;
+static char *p2;
+
+TEST(UnityFixture, PointerSet)
+{
+    char c1;
+    char c2;
+    char newC1;
+    char newC2;
+    p1 = &c1;
+    p2 = &c2;
+
+    UnityPointer_Init();
+    UT_PTR_SET(p1, &newC1);
+    UT_PTR_SET(p2, &newC2);
+    TEST_ASSERT_POINTERS_EQUAL(&newC1, p1);
+    TEST_ASSERT_POINTERS_EQUAL(&newC2, p2);
+    UnityPointer_UndoAllSets();
+    TEST_ASSERT_POINTERS_EQUAL(&c1, p1);
+    TEST_ASSERT_POINTERS_EQUAL(&c2, p2);
+}
+
+TEST(UnityFixture, FreeNULLSafety)
+{
+    free(NULL);
+}
+
+TEST(UnityFixture, ConcludeTestIncrementsFailCount)
+{
+    _U_UINT savedFails = Unity.TestFailures;
+    _U_UINT savedIgnores = Unity.TestIgnores;
+    UnityOutputCharSpy_Enable(1);
+    Unity.CurrentTestFailed = 1;
+    UnityConcludeFixtureTest(); // Resets TestFailed for this test to pass
+    Unity.CurrentTestIgnored = 1;
+    UnityConcludeFixtureTest(); // Resets TestIgnored
+    UnityOutputCharSpy_Enable(0);
+    TEST_ASSERT_EQUAL(savedFails + 1, Unity.TestFailures);
+    TEST_ASSERT_EQUAL(savedIgnores + 1, Unity.TestIgnores);
+    Unity.TestFailures = savedFails;
+    Unity.TestIgnores = savedIgnores;
+}
+
+//------------------------------------------------------------
+
+TEST_GROUP(UnityCommandOptions);
+
+static int savedVerbose;
+static unsigned int savedRepeat;
+static const char* savedName;
+static const char* savedGroup;
+
+TEST_SETUP(UnityCommandOptions)
+{
+    savedVerbose = UnityFixture.Verbose;
+    savedRepeat = UnityFixture.RepeatCount;
+    savedName = UnityFixture.NameFilter;
+    savedGroup = UnityFixture.GroupFilter;
+}
+
+TEST_TEAR_DOWN(UnityCommandOptions)
+{
+    UnityFixture.Verbose = savedVerbose;
+    UnityFixture.RepeatCount= savedRepeat;
+    UnityFixture.NameFilter = savedName;
+    UnityFixture.GroupFilter = savedGroup;
+}
+
+
+static const char* noOptions[] = {
+        "testrunner.exe"
+};
+
+TEST(UnityCommandOptions, DefaultOptions)
+{
+    UnityGetCommandLineOptions(1, noOptions);
+    TEST_ASSERT_EQUAL(0, UnityFixture.Verbose);
+    TEST_ASSERT_POINTERS_EQUAL(0, UnityFixture.GroupFilter);
+    TEST_ASSERT_POINTERS_EQUAL(0, UnityFixture.NameFilter);
+    TEST_ASSERT_EQUAL(1, UnityFixture.RepeatCount);
+}
+
+static const char* verbose[] = {
+        "testrunner.exe",
+        "-v"
+};
+
+TEST(UnityCommandOptions, OptionVerbose)
+{
+    TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(2, verbose));
+    TEST_ASSERT_EQUAL(1, UnityFixture.Verbose);
+}
+
+static const char* group[] = {
+        "testrunner.exe",
+        "-g", "groupname"
+};
+
+TEST(UnityCommandOptions, OptionSelectTestByGroup)
+{
+    TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, group));
+    STRCMP_EQUAL("groupname", UnityFixture.GroupFilter);
+}
+
+static const char* name[] = {
+        "testrunner.exe",
+        "-n", "testname"
+};
+
+TEST(UnityCommandOptions, OptionSelectTestByName)
+{
+    TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, name));
+    STRCMP_EQUAL("testname", UnityFixture.NameFilter);
+}
+
+static const char* repeat[] = {
+        "testrunner.exe",
+        "-r", "99"
+};
+
+TEST(UnityCommandOptions, OptionSelectRepeatTestsDefaultCount)
+{
+    TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(2, repeat));
+    TEST_ASSERT_EQUAL(2, UnityFixture.RepeatCount);
+}
+
+TEST(UnityCommandOptions, OptionSelectRepeatTestsSpecificCount)
+{
+    TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, repeat));
+    TEST_ASSERT_EQUAL(99, UnityFixture.RepeatCount);
+}
+
+static const char* multiple[] = {
+        "testrunner.exe",
+        "-v",
+        "-g", "groupname",
+        "-n", "testname",
+        "-r", "98"
+};
+
+TEST(UnityCommandOptions, MultipleOptions)
+{
+    TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(8, multiple));
+    TEST_ASSERT_EQUAL(1, UnityFixture.Verbose);
+    STRCMP_EQUAL("groupname", UnityFixture.GroupFilter);
+    STRCMP_EQUAL("testname", UnityFixture.NameFilter);
+    TEST_ASSERT_EQUAL(98, UnityFixture.RepeatCount);
+}
+
+static const char* dashRNotLast[] = {
+        "testrunner.exe",
+        "-v",
+        "-g", "gggg",
+        "-r",
+        "-n", "tttt",
+};
+
+TEST(UnityCommandOptions, MultipleOptionsDashRNotLastAndNoValueSpecified)
+{
+    TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(7, dashRNotLast));
+    TEST_ASSERT_EQUAL(1, UnityFixture.Verbose);
+    STRCMP_EQUAL("gggg", UnityFixture.GroupFilter);
+    STRCMP_EQUAL("tttt", UnityFixture.NameFilter);
+    TEST_ASSERT_EQUAL(2, UnityFixture.RepeatCount);
+}
+
+static const char* unknownCommand[] = {
+        "testrunner.exe",
+        "-v",
+        "-g", "groupname",
+        "-n", "testname",
+        "-r", "98",
+        "-z"
+};
+TEST(UnityCommandOptions, UnknownCommandIsIgnored)
+{
+    TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(9, unknownCommand));
+    TEST_ASSERT_EQUAL(1, UnityFixture.Verbose);
+    STRCMP_EQUAL("groupname", UnityFixture.GroupFilter);
+    STRCMP_EQUAL("testname", UnityFixture.NameFilter);
+    TEST_ASSERT_EQUAL(98, UnityFixture.RepeatCount);
+}
+
+TEST(UnityCommandOptions, GroupOrNameFilterWithoutStringFails)
+{
+    TEST_ASSERT_EQUAL(1, UnityGetCommandLineOptions(3, unknownCommand));
+    TEST_ASSERT_EQUAL(1, UnityGetCommandLineOptions(5, unknownCommand));
+    TEST_ASSERT_EQUAL(1, UnityMain(3, unknownCommand, NULL));
+}
+
+TEST(UnityCommandOptions, GroupFilterReallyFilters)
+{
+    _U_UINT saved = Unity.NumberOfTests;
+    TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(4, unknownCommand));
+    UnityIgnoreTest(NULL, "non-matching", NULL);
+    TEST_ASSERT_EQUAL(saved, Unity.NumberOfTests);
+}
+
+IGNORE_TEST(UnityCommandOptions, TestShouldBeIgnored)
+{
+    TEST_FAIL_MESSAGE("This test should not run!");
+}
+
+//------------------------------------------------------------
+
+TEST_GROUP(LeakDetection);
+
+TEST_SETUP(LeakDetection)
+{
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+    UnityOutputCharSpy_Create(200);
+#else
+    UnityOutputCharSpy_Create(1000);
+#endif
+}
+
+TEST_TEAR_DOWN(LeakDetection)
+{
+    UnityOutputCharSpy_Destroy();
+}
+
+#define EXPECT_ABORT_BEGIN \
+  { \
+    jmp_buf TestAbortFrame;   \
+    memcpy(TestAbortFrame, Unity.AbortFrame, sizeof(jmp_buf)); \
+    if (TEST_PROTECT()) \
+    {
+
+#define EXPECT_ABORT_END \
+    } \
+    memcpy(Unity.AbortFrame, TestAbortFrame, sizeof(jmp_buf)); \
+  }
+
+// This tricky set of defines lets us see if we are using the Spy, returns 1 if true
+#ifdef __STDC_VERSION__
+
+#if __STDC_VERSION__ >= 199901L
+#define USING_SPY_AS(a)                    EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0)
+#define ASSIGN_VALUE(a)                    VAL_##a
+#define VAL_UnityOutputCharSpy_OutputChar  0, 1
+#define EXPAND_AND_USE_2ND(a, b)           SECOND_PARAM(a, b, throwaway)
+#define SECOND_PARAM(a, b, ...)            b
+#if USING_SPY_AS(UNITY_OUTPUT_CHAR)
+  #define USING_OUTPUT_SPY // UNITY_OUTPUT_CHAR = UnityOutputCharSpy_OutputChar
+#endif
+#endif // >= 199901
+
+#else  // __STDC_VERSION__ else
+#define UnityOutputCharSpy_OutputChar 42
+#if UNITY_OUTPUT_CHAR == UnityOutputCharSpy_OutputChar // Works if no -Wundef -Werror
+  #define USING_OUTPUT_SPY
+#endif
+#undef UnityOutputCharSpy_OutputChar
+#endif // __STDC_VERSION__
+
+TEST(LeakDetection, DetectsLeak)
+{
+#ifndef USING_OUTPUT_SPY
+    TEST_IGNORE_MESSAGE("Build with '-D UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar' to enable tests");
+#else
+    void* m = malloc(10);
+    TEST_ASSERT_NOT_NULL(m);
+    UnityOutputCharSpy_Enable(1);
+    EXPECT_ABORT_BEGIN
+    UnityMalloc_EndTest();
+    EXPECT_ABORT_END
+    UnityOutputCharSpy_Enable(0);
+    Unity.CurrentTestFailed = 0;
+    CHECK(strstr(UnityOutputCharSpy_Get(), "This test leaks!"));
+    free(m);
+#endif
+}
+
+TEST(LeakDetection, BufferOverrunFoundDuringFree)
+{
+#ifndef USING_OUTPUT_SPY
+    TEST_IGNORE();
+#else
+    void* m = malloc(10);
+    char* s = (char*)m;
+    TEST_ASSERT_NOT_NULL(m);
+    s[10] = (char)0xFF;
+    UnityOutputCharSpy_Enable(1);
+    EXPECT_ABORT_BEGIN
+    free(m);
+    EXPECT_ABORT_END
+    UnityOutputCharSpy_Enable(0);
+    Unity.CurrentTestFailed = 0;
+    CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()"));
+#endif
+}
+
+TEST(LeakDetection, BufferOverrunFoundDuringRealloc)
+{
+#ifndef USING_OUTPUT_SPY
+    TEST_IGNORE();
+#else
+    void* m = malloc(10);
+    char* s = (char*)m;
+    TEST_ASSERT_NOT_NULL(m);
+    s[10] = (char)0xFF;
+    UnityOutputCharSpy_Enable(1);
+    EXPECT_ABORT_BEGIN
+    m = realloc(m, 100);
+    EXPECT_ABORT_END
+    UnityOutputCharSpy_Enable(0);
+    Unity.CurrentTestFailed = 0;
+    CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
+#endif
+}
+
+TEST(LeakDetection, BufferGuardWriteFoundDuringFree)
+{
+#ifndef USING_OUTPUT_SPY
+    TEST_IGNORE();
+#else
+    void* m = malloc(10);
+    char* s = (char*)m;
+    TEST_ASSERT_NOT_NULL(m);
+    s[-1] = (char)0x00; // Will not detect 0
+    s[-2] = (char)0x01;
+    UnityOutputCharSpy_Enable(1);
+    EXPECT_ABORT_BEGIN
+    free(m);
+    EXPECT_ABORT_END
+    UnityOutputCharSpy_Enable(0);
+    Unity.CurrentTestFailed = 0;
+    CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()"));
+#endif
+}
+
+TEST(LeakDetection, BufferGuardWriteFoundDuringRealloc)
+{
+#ifndef USING_OUTPUT_SPY
+    TEST_IGNORE();
+#else
+    void* m = malloc(10);
+    char* s = (char*)m;
+    TEST_ASSERT_NOT_NULL(m);
+    s[-1] = (char)0x0A;
+    UnityOutputCharSpy_Enable(1);
+    EXPECT_ABORT_BEGIN
+    m = realloc(m, 100);
+    EXPECT_ABORT_END
+    UnityOutputCharSpy_Enable(0);
+    Unity.CurrentTestFailed = 0;
+    CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
+#endif
+}
+
+TEST(LeakDetection, PointerSettingMax)
+{
+#ifndef USING_OUTPUT_SPY
+    TEST_IGNORE();
+#else
+    int i;
+    for (i = 0; i < 50; i++) UT_PTR_SET(pointer1, &int1);
+    UnityOutputCharSpy_Enable(1);
+    EXPECT_ABORT_BEGIN
+    UT_PTR_SET(pointer1, &int1);
+    EXPECT_ABORT_END
+    UnityOutputCharSpy_Enable(0);
+    Unity.CurrentTestFailed = 0;
+    CHECK(strstr(UnityOutputCharSpy_Get(), "Too many pointers set"));
+#endif
+}
+
+//------------------------------------------------------------
+
+TEST_GROUP(InternalMalloc);
+
+TEST_SETUP(InternalMalloc) { }
+TEST_TEAR_DOWN(InternalMalloc) { }
+
+TEST(InternalMalloc, MallocPastBufferFails)
+{
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+    void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
+    void* n = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
+    TEST_ASSERT_NOT_NULL(m);
+    TEST_ASSERT_NULL(n);
+    free(m);
+#endif
+}
+
+TEST(InternalMalloc, CallocPastBufferFails)
+{
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+    void* m = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
+    void* n = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
+    TEST_ASSERT_NOT_NULL(m);
+    TEST_ASSERT_NULL(n);
+    free(m);
+#endif
+}
+
+TEST(InternalMalloc, MallocThenReallocGrowsMemoryInPlace)
+{
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+    void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
+    void* n = realloc(m, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 9);
+    TEST_ASSERT_NOT_NULL(m);
+    TEST_ASSERT_EQUAL(m, n);
+    free(n);
+#endif
+}
+
+TEST(InternalMalloc, ReallocFailDoesNotFreeMem)
+{
+#ifdef UNITY_EXCLUDE_STDLIB_MALLOC
+    void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
+    void* n1 = malloc(10);
+    void* out_of_mem = realloc(n1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
+    void* n2 = malloc(10);
+    TEST_ASSERT_NOT_NULL(m);
+    TEST_ASSERT_NULL(out_of_mem);
+    TEST_ASSERT_NOT_EQUAL(n2, n1);
+    free(n2);
+    free(n1);
+    free(m);
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/test/unity_fixture_TestRunner.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,57 @@
+//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#include "unity_fixture.h"
+
+TEST_GROUP_RUNNER(UnityFixture)
+{
+    RUN_TEST_CASE(UnityFixture, PointerSetting);
+    RUN_TEST_CASE(UnityFixture, ForceMallocFail);
+    RUN_TEST_CASE(UnityFixture, ReallocSmallerIsUnchanged);
+    RUN_TEST_CASE(UnityFixture, ReallocSameIsUnchanged);
+    RUN_TEST_CASE(UnityFixture, ReallocLargerNeeded);
+    RUN_TEST_CASE(UnityFixture, ReallocNullPointerIsLikeMalloc);
+    RUN_TEST_CASE(UnityFixture, ReallocSizeZeroFreesMemAndReturnsNullPointer);
+    RUN_TEST_CASE(UnityFixture, CallocFillsWithZero);
+    RUN_TEST_CASE(UnityFixture, PointerSet);
+    RUN_TEST_CASE(UnityFixture, FreeNULLSafety);
+    RUN_TEST_CASE(UnityFixture, ConcludeTestIncrementsFailCount);
+}
+
+TEST_GROUP_RUNNER(UnityCommandOptions)
+{
+    RUN_TEST_CASE(UnityCommandOptions, DefaultOptions);
+    RUN_TEST_CASE(UnityCommandOptions, OptionVerbose);
+    RUN_TEST_CASE(UnityCommandOptions, OptionSelectTestByGroup);
+    RUN_TEST_CASE(UnityCommandOptions, OptionSelectTestByName);
+    RUN_TEST_CASE(UnityCommandOptions, OptionSelectRepeatTestsDefaultCount);
+    RUN_TEST_CASE(UnityCommandOptions, OptionSelectRepeatTestsSpecificCount);
+    RUN_TEST_CASE(UnityCommandOptions, MultipleOptions);
+    RUN_TEST_CASE(UnityCommandOptions, MultipleOptionsDashRNotLastAndNoValueSpecified);
+    RUN_TEST_CASE(UnityCommandOptions, UnknownCommandIsIgnored);
+    RUN_TEST_CASE(UnityCommandOptions, GroupOrNameFilterWithoutStringFails);
+    RUN_TEST_CASE(UnityCommandOptions, GroupFilterReallyFilters);
+    RUN_TEST_CASE(UnityCommandOptions, TestShouldBeIgnored);
+}
+
+TEST_GROUP_RUNNER(LeakDetection)
+{
+    RUN_TEST_CASE(LeakDetection, DetectsLeak);
+    RUN_TEST_CASE(LeakDetection, BufferOverrunFoundDuringFree);
+    RUN_TEST_CASE(LeakDetection, BufferOverrunFoundDuringRealloc);
+    RUN_TEST_CASE(LeakDetection, BufferGuardWriteFoundDuringFree);
+    RUN_TEST_CASE(LeakDetection, BufferGuardWriteFoundDuringRealloc);
+    RUN_TEST_CASE(LeakDetection, PointerSettingMax);
+}
+
+TEST_GROUP_RUNNER(InternalMalloc)
+{
+    RUN_TEST_CASE(InternalMalloc, MallocPastBufferFails);
+    RUN_TEST_CASE(InternalMalloc, CallocPastBufferFails);
+    RUN_TEST_CASE(InternalMalloc, MallocThenReallocGrowsMemoryInPlace);
+    RUN_TEST_CASE(InternalMalloc, ReallocFailDoesNotFreeMem);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/test/unity_output_Spy.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,57 @@
+//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+
+#include "unity_output_Spy.h"
+#include "unity_fixture.h"
+
+#include <stdio.h>
+#include <string.h>
+
+static int size;
+static int count;
+static char* buffer;
+static int spy_enable;
+
+void UnityOutputCharSpy_Create(int s)
+{
+    size = (s > 0) ? s : 0;
+    count = 0;
+    spy_enable = 0;
+    buffer = malloc((size_t)size);
+    TEST_ASSERT_NOT_NULL_MESSAGE(buffer, "Internal malloc failed in Spy Create():" __FILE__);
+    memset(buffer, 0, (size_t)size);
+}
+
+void UnityOutputCharSpy_Destroy(void)
+{
+    size = 0;
+    free(buffer);
+}
+
+void UnityOutputCharSpy_OutputChar(int c)
+{
+    if (spy_enable)
+    {
+        if (count < (size-1))
+            buffer[count++] = (char)c;
+    }
+    else
+    {
+        putchar(c);
+    }
+}
+
+const char * UnityOutputCharSpy_Get(void)
+{
+    return buffer;
+}
+
+void UnityOutputCharSpy_Enable(int enable)
+{
+    spy_enable = enable;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/extras/fixture/test/unity_output_Spy.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,17 @@
+//- Copyright (c) 2010 James Grenning and Contributed to Unity Project
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef D_unity_output_Spy_H
+#define D_unity_output_Spy_H
+
+void UnityOutputCharSpy_Create(int s);
+void UnityOutputCharSpy_Destroy(void);
+void UnityOutputCharSpy_OutputChar(int c);
+const char * UnityOutputCharSpy_Get(void);
+void UnityOutputCharSpy_Enable(int enable);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/release/build.info	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+119
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/release/version.info	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+2.3.2
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/src/unity.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1320 @@
+/* =========================================================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+============================================================================ */
+
+#include "unity.h"
+#include <stddef.h>
+
+/* If omitted from header, declare overrideable prototypes here so they're ready for use */
+#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION
+void UNITY_OUTPUT_CHAR(int);
+#endif
+
+/* Helpful macros for us to use here */
+#define UNITY_FAIL_AND_BAIL   { Unity.CurrentTestFailed  = 1; longjmp(Unity.AbortFrame, 1); }
+#define UNITY_IGNORE_AND_BAIL { Unity.CurrentTestIgnored = 1; longjmp(Unity.AbortFrame, 1); }
+
+/* return prematurely if we are already in failure or ignore state */
+#define UNITY_SKIP_EXECUTION  { if ((Unity.CurrentTestFailed != 0) || (Unity.CurrentTestIgnored != 0)) {return;} }
+
+struct _Unity Unity;
+
+static const char UnityStrOk[]                     = "OK";
+static const char UnityStrPass[]                   = "PASS";
+static const char UnityStrFail[]                   = "FAIL";
+static const char UnityStrIgnore[]                 = "IGNORE";
+static const char UnityStrNull[]                   = "NULL";
+static const char UnityStrSpacer[]                 = ". ";
+static const char UnityStrExpected[]               = " Expected ";
+static const char UnityStrWas[]                    = " Was ";
+static const char UnityStrElement[]                = " Element ";
+static const char UnityStrByte[]                   = " Byte ";
+static const char UnityStrMemory[]                 = " Memory Mismatch.";
+static const char UnityStrDelta[]                  = " Values Not Within Delta ";
+static const char UnityStrPointless[]              = " You Asked Me To Compare Nothing, Which Was Pointless.";
+static const char UnityStrNullPointerForExpected[] = " Expected pointer to be NULL";
+static const char UnityStrNullPointerForActual[]   = " Actual pointer was NULL";
+static const char UnityStrNot[]                    = "Not ";
+static const char UnityStrInf[]                    = "Infinity";
+static const char UnityStrNegInf[]                 = "Negative Infinity";
+static const char UnityStrNaN[]                    = "NaN";
+static const char UnityStrDet[]                    = "Determinate";
+static const char UnityStrInvalidFloatTrait[]      = "Invalid Float Trait";
+const char UnityStrErrFloat[]                      = "Unity Floating Point Disabled";
+const char UnityStrErrDouble[]                     = "Unity Double Precision Disabled";
+const char UnityStrErr64[]                         = "Unity 64-bit Support Disabled";
+static const char UnityStrBreaker[]                = "-----------------------";
+static const char UnityStrResultsTests[]           = " Tests ";
+static const char UnityStrResultsFailures[]        = " Failures ";
+static const char UnityStrResultsIgnored[]         = " Ignored ";
+static const char UnityStrDetail1Name[]            = UNITY_DETAIL1_NAME " ";
+static const char UnityStrDetail2Name[]            = " " UNITY_DETAIL2_NAME " ";
+
+#ifdef UNITY_FLOAT_NEEDS_ZERO
+/* Dividing by these constants produces +/- infinity.
+ * The rationale is given in UnityAssertFloatIsInf's body. */
+static const _UF f_zero = 0.0f;
+#endif
+
+/* compiler-generic print formatting masks */
+static const _U_UINT UnitySizeMask[] =
+{
+    255u,         /* 0xFF */
+    65535u,       /* 0xFFFF */
+    65535u,
+    4294967295u,  /* 0xFFFFFFFF */
+    4294967295u,
+    4294967295u,
+    4294967295u
+#ifdef UNITY_SUPPORT_64
+    ,0xFFFFFFFFFFFFFFFF
+#endif
+};
+
+/*-----------------------------------------------
+ * Pretty Printers & Test Result Output Handlers
+ *-----------------------------------------------*/
+
+void UnityPrint(const char* string)
+{
+    const char* pch = string;
+
+    if (pch != NULL)
+    {
+        while (*pch)
+        {
+            /* printable characters plus CR & LF are printed */
+            if ((*pch <= 126) && (*pch >= 32))
+            {
+                UNITY_OUTPUT_CHAR(*pch);
+            }
+            /* write escaped carriage returns */
+            else if (*pch == 13)
+            {
+                UNITY_OUTPUT_CHAR('\\');
+                UNITY_OUTPUT_CHAR('r');
+            }
+            /* write escaped line feeds */
+            else if (*pch == 10)
+            {
+                UNITY_OUTPUT_CHAR('\\');
+                UNITY_OUTPUT_CHAR('n');
+            }
+            /* unprintable characters are shown as codes */
+            else
+            {
+                UNITY_OUTPUT_CHAR('\\');
+                UnityPrintNumberHex((_U_UINT)*pch, 2);
+            }
+            pch++;
+        }
+    }
+}
+
+void UnityPrintLen(const char* string, const _UU32 length);
+void UnityPrintLen(const char* string, const _UU32 length)
+{
+    const char* pch = string;
+
+    if (pch != NULL)
+    {
+        while (*pch && (_UU32)(pch - string) < length)
+        {
+            /* printable characters plus CR & LF are printed */
+            if ((*pch <= 126) && (*pch >= 32))
+            {
+                UNITY_OUTPUT_CHAR(*pch);
+            }
+            /* write escaped carriage returns */
+            else if (*pch == 13)
+            {
+                UNITY_OUTPUT_CHAR('\\');
+                UNITY_OUTPUT_CHAR('r');
+            }
+            /* write escaped line feeds */
+            else if (*pch == 10)
+            {
+                UNITY_OUTPUT_CHAR('\\');
+                UNITY_OUTPUT_CHAR('n');
+            }
+            /* unprintable characters are shown as codes */
+            else
+            {
+                UNITY_OUTPUT_CHAR('\\');
+                UnityPrintNumberHex((_U_UINT)*pch, 2);
+            }
+            pch++;
+        }
+    }
+}
+
+/*-----------------------------------------------*/
+void UnityPrintNumberByStyle(const _U_SINT number, const UNITY_DISPLAY_STYLE_T style)
+{
+    if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+    {
+        UnityPrintNumber(number);
+    }
+    else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT)
+    {
+        UnityPrintNumberUnsigned(  (_U_UINT)number  &  UnitySizeMask[((_U_UINT)style & (_U_UINT)0x0F) - 1]  );
+    }
+    else
+    {
+        UnityPrintNumberHex((_U_UINT)number, (char)((style & 0x000F) << 1));
+    }
+}
+
+/*-----------------------------------------------*/
+void UnityPrintNumber(const _U_SINT number_to_print)
+{
+    _U_UINT number = (_U_UINT)number_to_print;
+
+    if (number_to_print < 0)
+    {
+        /* A negative number, including MIN negative */
+        UNITY_OUTPUT_CHAR('-');
+        number = (_U_UINT)(-number_to_print);
+    }
+    UnityPrintNumberUnsigned(number);
+}
+
+/*-----------------------------------------------
+ * basically do an itoa using as little ram as possible */
+void UnityPrintNumberUnsigned(const _U_UINT number)
+{
+    _U_UINT divisor = 1;
+
+    /* figure out initial divisor */
+    while (number / divisor > 9)
+    {
+        divisor *= 10;
+    }
+
+    /* now mod and print, then divide divisor */
+    do
+    {
+        UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10)));
+        divisor /= 10;
+    }
+    while (divisor > 0);
+}
+
+/*-----------------------------------------------*/
+void UnityPrintNumberHex(const _U_UINT number, const char nibbles_to_print)
+{
+    _U_UINT nibble;
+    char nibbles = nibbles_to_print;
+    UNITY_OUTPUT_CHAR('0');
+    UNITY_OUTPUT_CHAR('x');
+
+    while (nibbles > 0)
+    {
+        nibble = (number >> (--nibbles << 2)) & 0x0000000F;
+        if (nibble <= 9)
+        {
+            UNITY_OUTPUT_CHAR((char)('0' + nibble));
+        }
+        else
+        {
+            UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble));
+        }
+    }
+}
+
+/*-----------------------------------------------*/
+void UnityPrintMask(const _U_UINT mask, const _U_UINT number)
+{
+    _U_UINT current_bit = (_U_UINT)1 << (UNITY_INT_WIDTH - 1);
+    _US32 i;
+
+    for (i = 0; i < UNITY_INT_WIDTH; i++)
+    {
+        if (current_bit & mask)
+        {
+            if (current_bit & number)
+            {
+                UNITY_OUTPUT_CHAR('1');
+            }
+            else
+            {
+                UNITY_OUTPUT_CHAR('0');
+            }
+        }
+        else
+        {
+            UNITY_OUTPUT_CHAR('X');
+        }
+        current_bit = current_bit >> 1;
+    }
+}
+
+/*-----------------------------------------------*/
+#ifdef UNITY_FLOAT_VERBOSE
+#include <stdio.h>
+
+#ifndef UNITY_VERBOSE_NUMBER_MAX_LENGTH
+# ifdef UNITY_DOUBLE_VERBOSE
+#  define UNITY_VERBOSE_NUMBER_MAX_LENGTH 317
+# else
+#  define UNITY_VERBOSE_NUMBER_MAX_LENGTH 47
+# endif
+#endif
+
+void UnityPrintFloat(_UF number)
+{
+    char TempBuffer[UNITY_VERBOSE_NUMBER_MAX_LENGTH + 1];
+    snprintf(TempBuffer, sizeof(TempBuffer), "%.6f", number);
+    UnityPrint(TempBuffer);
+}
+#endif
+
+/*-----------------------------------------------*/
+
+void UnityPrintFail(void);
+void UnityPrintFail(void)
+{
+    UnityPrint(UnityStrFail);
+}
+
+void UnityPrintOk(void);
+void UnityPrintOk(void)
+{
+    UnityPrint(UnityStrOk);
+}
+
+/*-----------------------------------------------*/
+static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line);
+static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line)
+{
+#ifndef UNITY_FIXTURES
+    UnityPrint(file);
+    UNITY_OUTPUT_CHAR(':');
+    UnityPrintNumber((_U_SINT)line);
+    UNITY_OUTPUT_CHAR(':');
+    UnityPrint(Unity.CurrentTestName);
+    UNITY_OUTPUT_CHAR(':');
+#else
+    UNITY_UNUSED(file);
+    UNITY_UNUSED(line);
+#endif
+}
+
+/* SA_PATCH: Make failures more noticable. */
+static void UnityPrintVisibleFailure(void);
+static void UnityPrintVisibleFailure(void)
+{
+    UNITY_OUTPUT_CHAR('\n');
+    UnityPrint("===!!!===> ");
+    /* SA_PATCH: Output results using easy to parse tags. */
+    UnityPrint(UNITY_RESULTS_TAGS_RESULT_START);
+    UnityPrint(UnityStrFail);
+    /* SA_PATCH: Output results using easy to parse tags. */
+    UnityPrint(UNITY_RESULTS_TAGS_RESULT_END);
+    UnityPrint(" <===!!!===");
+}
+/*-----------------------------------------------*/
+static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line);
+static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line)
+{
+#ifndef UNITY_FIXTURES
+    UnityTestResultsBegin(Unity.TestFile, line);
+#else
+    UNITY_UNUSED(line);
+#endif
+    /* SA_PATCH: Make failures more noticable. */
+    UnityPrintVisibleFailure();
+    //UnityPrint(UnityStrFail);
+    UNITY_OUTPUT_CHAR(':');
+}
+
+/*-----------------------------------------------*/
+void UnityConcludeTest(void)
+{
+    if (Unity.CurrentTestIgnored)
+    {
+        Unity.TestIgnores++;
+    }
+    else if (!Unity.CurrentTestFailed)
+    {
+        UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber);
+        UnityPrint(UnityStrPass);
+    }
+    else
+    {
+        Unity.TestFailures++;
+    }
+
+    Unity.CurrentTestFailed = 0;
+    Unity.CurrentTestIgnored = 0;
+    UNITY_PRINT_EOL();
+    UNITY_FLUSH_CALL();
+}
+
+/*-----------------------------------------------*/
+static void UnityAddMsgIfSpecified(const char* msg);
+static void UnityAddMsgIfSpecified(const char* msg)
+{
+    if (msg)
+    {
+        UnityPrint(UnityStrSpacer);
+#ifndef UNITY_EXCLUDE_DETAILS
+        if (Unity.CurrentDetail1)
+        {
+            UnityPrint(UnityStrDetail1Name);
+            UnityPrint(Unity.CurrentDetail1);
+            if (Unity.CurrentDetail2)
+            {
+                UnityPrint(UnityStrDetail2Name);
+                UnityPrint(Unity.CurrentDetail2);
+            }
+            UnityPrint(UnityStrSpacer);
+        }
+#endif
+        UnityPrint(msg);
+    }
+}
+
+/*-----------------------------------------------*/
+static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual);
+static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual)
+{
+    UnityPrint(UnityStrExpected);
+    if (expected != NULL)
+    {
+        UNITY_OUTPUT_CHAR('\'');
+        UnityPrint(expected);
+        UNITY_OUTPUT_CHAR('\'');
+    }
+    else
+    {
+      UnityPrint(UnityStrNull);
+    }
+    UnityPrint(UnityStrWas);
+    if (actual != NULL)
+    {
+        UNITY_OUTPUT_CHAR('\'');
+        UnityPrint(actual);
+        UNITY_OUTPUT_CHAR('\'');
+    }
+    else
+    {
+      UnityPrint(UnityStrNull);
+    }
+}
+
+/*-----------------------------------------------*/
+static void UnityPrintExpectedAndActualStringsLen(const char* expected, const char* actual, const _UU32 length)
+{
+    UnityPrint(UnityStrExpected);
+    if (expected != NULL)
+    {
+        UNITY_OUTPUT_CHAR('\'');
+        UnityPrintLen(expected, length);
+        UNITY_OUTPUT_CHAR('\'');
+    }
+    else
+    {
+      UnityPrint(UnityStrNull);
+    }
+    UnityPrint(UnityStrWas);
+    if (actual != NULL)
+    {
+        UNITY_OUTPUT_CHAR('\'');
+        UnityPrintLen(actual, length);
+        UNITY_OUTPUT_CHAR('\'');
+    }
+    else
+    {
+      UnityPrint(UnityStrNull);
+    }
+}
+
+
+
+/*-----------------------------------------------
+ * Assertion & Control Helpers
+ *-----------------------------------------------*/
+
+static int UnityCheckArraysForNull(UNITY_INTERNAL_PTR expected, UNITY_INTERNAL_PTR actual, const UNITY_LINE_TYPE lineNumber, const char* msg)
+{
+    /* return true if they are both NULL */
+    if ((expected == NULL) && (actual == NULL))
+        return 1;
+
+    /* throw error if just expected is NULL */
+    if (expected == NULL)
+    {
+        UnityTestResultsFailBegin(lineNumber);
+        UnityPrint(UnityStrNullPointerForExpected);
+        UnityAddMsgIfSpecified(msg);
+        UNITY_FAIL_AND_BAIL;
+    }
+
+    /* throw error if just actual is NULL */
+    if (actual == NULL)
+    {
+        UnityTestResultsFailBegin(lineNumber);
+        UnityPrint(UnityStrNullPointerForActual);
+        UnityAddMsgIfSpecified(msg);
+        UNITY_FAIL_AND_BAIL;
+    }
+
+    /* return false if neither is NULL */
+    return 0;
+}
+
+/*-----------------------------------------------
+ * Assertion Functions
+ *-----------------------------------------------*/
+
+void UnityAssertBits(const _U_SINT mask,
+                     const _U_SINT expected,
+                     const _U_SINT actual,
+                     const char* msg,
+                     const UNITY_LINE_TYPE lineNumber)
+{
+    UNITY_SKIP_EXECUTION;
+
+    if ((mask & expected) != (mask & actual))
+    {
+        UnityTestResultsFailBegin(lineNumber);
+        UnityPrint(UnityStrExpected);
+        UnityPrintMask((_U_UINT)mask, (_U_UINT)expected);
+        UnityPrint(UnityStrWas);
+        UnityPrintMask((_U_UINT)mask, (_U_UINT)actual);
+        UnityAddMsgIfSpecified(msg);
+        UNITY_FAIL_AND_BAIL;
+    }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualNumber(const _U_SINT expected,
+                            const _U_SINT actual,
+                            const char* msg,
+                            const UNITY_LINE_TYPE lineNumber,
+                            const UNITY_DISPLAY_STYLE_T style)
+{
+    UNITY_SKIP_EXECUTION;
+
+    if (expected != actual)
+    {
+        UnityTestResultsFailBegin(lineNumber);
+        UnityPrint(UnityStrExpected);
+        UnityPrintNumberByStyle(expected, style);
+        UnityPrint(UnityStrWas);
+        UnityPrintNumberByStyle(actual, style);
+        UnityAddMsgIfSpecified(msg);
+        UNITY_FAIL_AND_BAIL;
+    }
+}
+
+#define UnityPrintPointlessAndBail()       \
+{                                          \
+    UnityTestResultsFailBegin(lineNumber); \
+    UnityPrint(UnityStrPointless);         \
+    UnityAddMsgIfSpecified(msg);           \
+    UNITY_FAIL_AND_BAIL; }
+
+/*-----------------------------------------------*/
+void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
+                              UNITY_INTERNAL_PTR actual,
+                              const _UU32 num_elements,
+                              const char* msg,
+                              const UNITY_LINE_TYPE lineNumber,
+                              const UNITY_DISPLAY_STYLE_T style)
+{
+    _UU32 elements = num_elements;
+    UNITY_INTERNAL_PTR ptr_exp = (UNITY_INTERNAL_PTR)expected;
+    UNITY_INTERNAL_PTR ptr_act = (UNITY_INTERNAL_PTR)actual;
+
+    UNITY_SKIP_EXECUTION;
+
+    if (elements == 0)
+    {
+        UnityPrintPointlessAndBail();
+    }
+
+    if (UnityCheckArraysForNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg) == 1)
+        return;
+
+    /* If style is UNITY_DISPLAY_STYLE_INT, we'll fall into the default case rather than the INT16 or INT32 (etc) case
+     * as UNITY_DISPLAY_STYLE_INT includes a flag for UNITY_DISPLAY_RANGE_AUTO, which the width-specific
+     * variants do not. Therefore remove this flag. */
+    switch(style & (UNITY_DISPLAY_STYLE_T)(~UNITY_DISPLAY_RANGE_AUTO))
+    {
+        case UNITY_DISPLAY_STYLE_HEX8:
+        case UNITY_DISPLAY_STYLE_INT8:
+        case UNITY_DISPLAY_STYLE_UINT8:
+            while (elements--)
+            {
+                if (*(UNITY_PTR_ATTRIBUTE const _US8*)ptr_exp != *(UNITY_PTR_ATTRIBUTE const _US8*)ptr_act)
+                {
+                    UnityTestResultsFailBegin(lineNumber);
+                    UnityPrint(UnityStrElement);
+                    UnityPrintNumberUnsigned(num_elements - elements - 1);
+                    UnityPrint(UnityStrExpected);
+                    UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US8*)ptr_exp, style);
+                    UnityPrint(UnityStrWas);
+                    UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US8*)ptr_act, style);
+                    UnityAddMsgIfSpecified(msg);
+                    UNITY_FAIL_AND_BAIL;
+                }
+                ptr_exp = (UNITY_INTERNAL_PTR)((_UP)ptr_exp + 1);
+                ptr_act = (UNITY_INTERNAL_PTR)((_UP)ptr_act + 1);
+            }
+            break;
+        case UNITY_DISPLAY_STYLE_HEX16:
+        case UNITY_DISPLAY_STYLE_INT16:
+        case UNITY_DISPLAY_STYLE_UINT16:
+            while (elements--)
+            {
+                if (*(UNITY_PTR_ATTRIBUTE const _US16*)ptr_exp != *(UNITY_PTR_ATTRIBUTE const _US16*)ptr_act)
+                {
+                    UnityTestResultsFailBegin(lineNumber);
+                    UnityPrint(UnityStrElement);
+                    UnityPrintNumberUnsigned(num_elements - elements - 1);
+                    UnityPrint(UnityStrExpected);
+                    UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US16*)ptr_exp, style);
+                    UnityPrint(UnityStrWas);
+                    UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US16*)ptr_act, style);
+                    UnityAddMsgIfSpecified(msg);
+                    UNITY_FAIL_AND_BAIL;
+                }
+                ptr_exp = (UNITY_INTERNAL_PTR)((_UP)ptr_exp + 2);
+                ptr_act = (UNITY_INTERNAL_PTR)((_UP)ptr_act + 2);
+            }
+            break;
+#ifdef UNITY_SUPPORT_64
+        case UNITY_DISPLAY_STYLE_HEX64:
+        case UNITY_DISPLAY_STYLE_INT64:
+        case UNITY_DISPLAY_STYLE_UINT64:
+            while (elements--)
+            {
+                if (*(UNITY_PTR_ATTRIBUTE const _US64*)ptr_exp != *(UNITY_PTR_ATTRIBUTE const _US64*)ptr_act)
+                {
+                    UnityTestResultsFailBegin(lineNumber);
+                    UnityPrint(UnityStrElement);
+                    UnityPrintNumberUnsigned(num_elements - elements - 1);
+                    UnityPrint(UnityStrExpected);
+                    UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US64*)ptr_exp, style);
+                    UnityPrint(UnityStrWas);
+                    UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US64*)ptr_act, style);
+                    UnityAddMsgIfSpecified(msg);
+                    UNITY_FAIL_AND_BAIL;
+                }
+                ptr_exp = (UNITY_INTERNAL_PTR)((_UP)ptr_exp + 8);
+                ptr_act = (UNITY_INTERNAL_PTR)((_UP)ptr_act + 8);
+            }
+            break;
+#endif
+        default:
+            while (elements--)
+            {
+                if (*(UNITY_PTR_ATTRIBUTE const _US32*)ptr_exp != *(UNITY_PTR_ATTRIBUTE const _US32*)ptr_act)
+                {
+                    UnityTestResultsFailBegin(lineNumber);
+                    UnityPrint(UnityStrElement);
+                    UnityPrintNumberUnsigned(num_elements - elements - 1);
+                    UnityPrint(UnityStrExpected);
+                    UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US32*)ptr_exp, style);
+                    UnityPrint(UnityStrWas);
+                    UnityPrintNumberByStyle(*(UNITY_PTR_ATTRIBUTE const _US32*)ptr_act, style);
+                    UnityAddMsgIfSpecified(msg);
+                    UNITY_FAIL_AND_BAIL;
+                }
+                ptr_exp = (UNITY_INTERNAL_PTR)((_UP)ptr_exp + 4);
+                ptr_act = (UNITY_INTERNAL_PTR)((_UP)ptr_act + 4);
+            }
+            break;
+    }
+}
+
+/*-----------------------------------------------*/
+#ifndef UNITY_EXCLUDE_FLOAT
+void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const _UF* expected,
+                                UNITY_PTR_ATTRIBUTE const _UF* actual,
+                                const _UU32 num_elements,
+                                const char* msg,
+                                const UNITY_LINE_TYPE lineNumber)
+{
+    _UU32 elements = num_elements;
+    UNITY_PTR_ATTRIBUTE const _UF* ptr_expected = expected;
+    UNITY_PTR_ATTRIBUTE const _UF* ptr_actual = actual;
+    _UF diff, tol;
+
+    UNITY_SKIP_EXECUTION;
+
+    if (elements == 0)
+    {
+        UnityPrintPointlessAndBail();
+    }
+
+    if (UnityCheckArraysForNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg) == 1)
+        return;
+
+    while (elements--)
+    {
+        diff = *ptr_expected - *ptr_actual;
+        if (diff < 0.0f)
+            diff = 0.0f - diff;
+        tol = UNITY_FLOAT_PRECISION * *ptr_expected;
+        if (tol < 0.0f)
+            tol = 0.0f - tol;
+
+        /* This first part of this condition will catch any NaN or Infinite values */
+        if (isnan(diff) || isinf(diff) || (diff > tol))
+        {
+            UnityTestResultsFailBegin(lineNumber);
+            UnityPrint(UnityStrElement);
+            UnityPrintNumberUnsigned(num_elements - elements - 1);
+#ifdef UNITY_FLOAT_VERBOSE
+            UnityPrint(UnityStrExpected);
+            UnityPrintFloat(*ptr_expected);
+            UnityPrint(UnityStrWas);
+            UnityPrintFloat(*ptr_actual);
+#else
+            UnityPrint(UnityStrDelta);
+#endif
+            UnityAddMsgIfSpecified(msg);
+            UNITY_FAIL_AND_BAIL;
+        }
+        ptr_expected++;
+        ptr_actual++;
+    }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertFloatsWithin(const _UF delta,
+                             const _UF expected,
+                             const _UF actual,
+                             const char* msg,
+                             const UNITY_LINE_TYPE lineNumber)
+{
+    _UF diff = actual - expected;
+    _UF pos_delta = delta;
+
+    UNITY_SKIP_EXECUTION;
+
+    if (diff < 0.0f)
+    {
+        diff = 0.0f - diff;
+    }
+    if (pos_delta < 0.0f)
+    {
+        pos_delta = 0.0f - pos_delta;
+    }
+
+    /* This first part of this condition will catch any NaN or Infinite values */
+    if (isnan(diff) || isinf(diff) || (pos_delta < diff))
+    {
+        UnityTestResultsFailBegin(lineNumber);
+#ifdef UNITY_FLOAT_VERBOSE
+        UnityPrint(UnityStrExpected);
+        UnityPrintFloat(expected);
+        UnityPrint(UnityStrWas);
+        UnityPrintFloat(actual);
+#else
+        UnityPrint(UnityStrDelta);
+#endif
+        UnityAddMsgIfSpecified(msg);
+        UNITY_FAIL_AND_BAIL;
+    }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertFloatSpecial(const _UF actual,
+                             const char* msg,
+                             const UNITY_LINE_TYPE lineNumber,
+                             const UNITY_FLOAT_TRAIT_T style)
+{
+    const char* trait_names[] = { UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet };
+    _U_SINT should_be_trait   = ((_U_SINT)style & 1);
+    _U_SINT is_trait          = !should_be_trait;
+    _U_SINT trait_index       = (_U_SINT)(style >> 1);
+
+    UNITY_SKIP_EXECUTION;
+
+    switch(style)
+    {
+        /* To determine Inf / Neg Inf, we compare to an Inf / Neg Inf value we create on the fly
+         * We are using a variable to hold the zero value because some compilers complain about dividing by zero otherwise */
+        case UNITY_FLOAT_IS_INF:
+        case UNITY_FLOAT_IS_NOT_INF:
+            is_trait = isinf(actual) & ispos(actual);
+            break;
+        case UNITY_FLOAT_IS_NEG_INF:
+        case UNITY_FLOAT_IS_NOT_NEG_INF:
+            is_trait = isinf(actual) & isneg(actual);
+            break;
+
+        /* NaN is the only floating point value that does NOT equal itself. Therefore if Actual == Actual, then it is NOT NaN. */
+        case UNITY_FLOAT_IS_NAN:
+        case UNITY_FLOAT_IS_NOT_NAN:
+            is_trait = isnan(actual);
+            break;
+
+        /* A determinate number is non infinite and not NaN. (therefore the opposite of the two above) */
+        case UNITY_FLOAT_IS_DET:
+        case UNITY_FLOAT_IS_NOT_DET:
+            if (isinf(actual) | isnan(actual))
+                is_trait = 0;
+            else
+                is_trait = 1;
+            break;
+
+        default:
+            trait_index = 0;
+            trait_names[0] = UnityStrInvalidFloatTrait;
+            break;
+    }
+
+    if (is_trait != should_be_trait)
+    {
+        UnityTestResultsFailBegin(lineNumber);
+        UnityPrint(UnityStrExpected);
+        if (!should_be_trait)
+            UnityPrint(UnityStrNot);
+        UnityPrint(trait_names[trait_index]);
+        UnityPrint(UnityStrWas);
+#ifdef UNITY_FLOAT_VERBOSE
+        UnityPrintFloat(actual);
+#else
+        if (should_be_trait)
+            UnityPrint(UnityStrNot);
+        UnityPrint(trait_names[trait_index]);
+#endif
+        UnityAddMsgIfSpecified(msg);
+        UNITY_FAIL_AND_BAIL;
+    }
+}
+
+#endif /* not UNITY_EXCLUDE_FLOAT */
+
+/*-----------------------------------------------*/
+#ifndef UNITY_EXCLUDE_DOUBLE
+void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const _UD* expected,
+                                 UNITY_PTR_ATTRIBUTE const _UD* actual,
+                                 const _UU32 num_elements,
+                                 const char* msg,
+                                 const UNITY_LINE_TYPE lineNumber)
+{
+    _UU32 elements = num_elements;
+    UNITY_PTR_ATTRIBUTE const _UD* ptr_expected = expected;
+    UNITY_PTR_ATTRIBUTE const _UD* ptr_actual = actual;
+    _UD diff, tol;
+
+    UNITY_SKIP_EXECUTION;
+
+    if (elements == 0)
+    {
+        UnityPrintPointlessAndBail();
+    }
+
+    if (UnityCheckArraysForNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg) == 1)
+        return;
+
+    while (elements--)
+    {
+        diff = *ptr_expected - *ptr_actual;
+        if (diff < 0.0)
+          diff = 0.0 - diff;
+        tol = UNITY_DOUBLE_PRECISION * *ptr_expected;
+        if (tol < 0.0)
+            tol = 0.0 - tol;
+
+        /* This first part of this condition will catch any NaN or Infinite values */
+        if (isnan(diff) || isinf(diff) || (diff > tol))
+        {
+            UnityTestResultsFailBegin(lineNumber);
+            UnityPrint(UnityStrElement);
+            UnityPrintNumberUnsigned(num_elements - elements - 1);
+#ifdef UNITY_DOUBLE_VERBOSE
+            UnityPrint(UnityStrExpected);
+            UnityPrintFloat((float)(*ptr_expected));
+            UnityPrint(UnityStrWas);
+            UnityPrintFloat((float)(*ptr_actual));
+#else
+            UnityPrint(UnityStrDelta);
+#endif
+            UnityAddMsgIfSpecified(msg);
+            UNITY_FAIL_AND_BAIL;
+        }
+        ptr_expected++;
+        ptr_actual++;
+    }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertDoublesWithin(const _UD delta,
+                              const _UD expected,
+                              const _UD actual,
+                              const char* msg,
+                              const UNITY_LINE_TYPE lineNumber)
+{
+    _UD diff = actual - expected;
+    _UD pos_delta = delta;
+
+    UNITY_SKIP_EXECUTION;
+
+    if (diff < 0.0)
+    {
+        diff = 0.0 - diff;
+    }
+    if (pos_delta < 0.0)
+    {
+        pos_delta = 0.0 - pos_delta;
+    }
+
+    /* This first part of this condition will catch any NaN or Infinite values */
+    if (isnan(diff) || isinf(diff) || (pos_delta < diff))
+    {
+        UnityTestResultsFailBegin(lineNumber);
+#ifdef UNITY_DOUBLE_VERBOSE
+        UnityPrint(UnityStrExpected);
+        UnityPrintFloat((float)expected);
+        UnityPrint(UnityStrWas);
+        UnityPrintFloat((float)actual);
+#else
+        UnityPrint(UnityStrDelta);
+#endif
+        UnityAddMsgIfSpecified(msg);
+        UNITY_FAIL_AND_BAIL;
+    }
+}
+
+/*-----------------------------------------------*/
+
+void UnityAssertDoubleSpecial(const _UD actual,
+                              const char* msg,
+                              const UNITY_LINE_TYPE lineNumber,
+                              const UNITY_FLOAT_TRAIT_T style)
+{
+    const char* trait_names[] = { UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet };
+    _U_SINT should_be_trait   = ((_U_SINT)style & 1);
+    _U_SINT is_trait          = !should_be_trait;
+    _U_SINT trait_index       = (_U_SINT)(style >> 1);
+
+    UNITY_SKIP_EXECUTION;
+
+     switch(style)
+    {
+        /* To determine Inf / Neg Inf, we compare to an Inf / Neg Inf value we create on the fly
+         * We are using a variable to hold the zero value because some compilers complain about dividing by zero otherwise */
+        case UNITY_FLOAT_IS_INF:
+        case UNITY_FLOAT_IS_NOT_INF:
+            is_trait = isinf(actual) & ispos(actual);
+            break;
+        case UNITY_FLOAT_IS_NEG_INF:
+        case UNITY_FLOAT_IS_NOT_NEG_INF:
+            is_trait = isinf(actual) & isneg(actual);
+            break;
+
+        /* NaN is the only floating point value that does NOT equal itself. Therefore if Actual == Actual, then it is NOT NaN. */
+        case UNITY_FLOAT_IS_NAN:
+        case UNITY_FLOAT_IS_NOT_NAN:
+            is_trait = isnan(actual);
+            break;
+
+        /* A determinate number is non infinite and not NaN. (therefore the opposite of the two above) */
+        case UNITY_FLOAT_IS_DET:
+        case UNITY_FLOAT_IS_NOT_DET:
+            if (isinf(actual) | isnan(actual))
+                is_trait = 0;
+            else
+                is_trait = 1;
+            break;
+
+        default:
+            trait_index = 0;
+            trait_names[0] = UnityStrInvalidFloatTrait;
+            break;
+    }
+
+    if (is_trait != should_be_trait)
+    {
+        UnityTestResultsFailBegin(lineNumber);
+        UnityPrint(UnityStrExpected);
+        if (!should_be_trait)
+            UnityPrint(UnityStrNot);
+        UnityPrint(trait_names[trait_index]);
+        UnityPrint(UnityStrWas);
+#ifdef UNITY_DOUBLE_VERBOSE
+        UnityPrintFloat(actual);
+#else
+        if (should_be_trait)
+            UnityPrint(UnityStrNot);
+        UnityPrint(trait_names[trait_index]);
+#endif
+        UnityAddMsgIfSpecified(msg);
+        UNITY_FAIL_AND_BAIL;
+    }
+}
+
+
+#endif /* not UNITY_EXCLUDE_DOUBLE */
+
+/*-----------------------------------------------*/
+void UnityAssertNumbersWithin( const _U_UINT delta,
+                               const _U_SINT expected,
+                               const _U_SINT actual,
+                               const char* msg,
+                               const UNITY_LINE_TYPE lineNumber,
+                               const UNITY_DISPLAY_STYLE_T style)
+{
+    UNITY_SKIP_EXECUTION;
+
+    if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT)
+    {
+        if (actual > expected)
+            Unity.CurrentTestFailed = ((_U_UINT)(actual - expected) > delta);
+        else
+            Unity.CurrentTestFailed = ((_U_UINT)(expected - actual) > delta);
+    }
+    else
+    {
+        if ((_U_UINT)actual > (_U_UINT)expected)
+            Unity.CurrentTestFailed = ((_U_UINT)(actual - expected) > delta);
+        else
+            Unity.CurrentTestFailed = ((_U_UINT)(expected - actual) > delta);
+    }
+
+    if (Unity.CurrentTestFailed)
+    {
+        UnityTestResultsFailBegin(lineNumber);
+        UnityPrint(UnityStrDelta);
+        UnityPrintNumberByStyle((_U_SINT)delta, style);
+        UnityPrint(UnityStrExpected);
+        UnityPrintNumberByStyle(expected, style);
+        UnityPrint(UnityStrWas);
+        UnityPrintNumberByStyle(actual, style);
+        UnityAddMsgIfSpecified(msg);
+        UNITY_FAIL_AND_BAIL;
+    }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualString(const char* expected,
+                            const char* actual,
+                            const char* msg,
+                            const UNITY_LINE_TYPE lineNumber)
+{
+    _UU32 i;
+
+    UNITY_SKIP_EXECUTION;
+
+    /* if both pointers not null compare the strings */
+    if (expected && actual)
+    {
+        for (i = 0; expected[i] || actual[i]; i++)
+        {
+            if (expected[i] != actual[i])
+            {
+                Unity.CurrentTestFailed = 1;
+                break;
+            }
+        }
+    }
+    else
+    { /* handle case of one pointers being null (if both null, test should pass) */
+        if (expected != actual)
+        {
+            Unity.CurrentTestFailed = 1;
+        }
+    }
+
+    if (Unity.CurrentTestFailed)
+    {
+      UnityTestResultsFailBegin(lineNumber);
+      UnityPrintExpectedAndActualStrings(expected, actual);
+      UnityAddMsgIfSpecified(msg);
+      UNITY_FAIL_AND_BAIL;
+    }
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualStringLen(const char* expected,
+                            const char* actual,
+                            const _UU32 length,
+                            const char* msg,
+                            const UNITY_LINE_TYPE lineNumber)
+{
+    _UU32 i;
+
+    UNITY_SKIP_EXECUTION;
+
+    /* if both pointers not null compare the strings */
+    if (expected && actual)
+    {
+        for (i = 0; (expected[i] || actual[i]) && i < length; i++)
+        {
+            if (expected[i] != actual[i])
+            {
+                Unity.CurrentTestFailed = 1;
+                break;
+            }
+        }
+    }
+    else
+    { /* handle case of one pointers being null (if both null, test should pass) */
+        if (expected != actual)
+        {
+            Unity.CurrentTestFailed = 1;
+        }
+    }
+
+    if (Unity.CurrentTestFailed)
+    {
+      UnityTestResultsFailBegin(lineNumber);
+      UnityPrintExpectedAndActualStringsLen(expected, actual, length);
+      UnityAddMsgIfSpecified(msg);
+      UNITY_FAIL_AND_BAIL;
+    }
+}
+
+
+/*-----------------------------------------------*/
+void UnityAssertEqualStringArray( const char** expected,
+                                  const char** actual,
+                                  const _UU32 num_elements,
+                                  const char* msg,
+                                  const UNITY_LINE_TYPE lineNumber)
+{
+    _UU32 i, j = 0;
+
+    UNITY_SKIP_EXECUTION;
+
+    /* if no elements, it's an error */
+    if (num_elements == 0)
+    {
+        UnityPrintPointlessAndBail();
+    }
+
+    if (UnityCheckArraysForNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg) == 1)
+        return;
+
+    do
+    {
+        /* if both pointers not null compare the strings */
+        if (expected[j] && actual[j])
+        {
+            for (i = 0; expected[j][i] || actual[j][i]; i++)
+            {
+                if (expected[j][i] != actual[j][i])
+                {
+                    Unity.CurrentTestFailed = 1;
+                    break;
+                }
+            }
+        }
+        else
+        { /* handle case of one pointers being null (if both null, test should pass) */
+            if (expected[j] != actual[j])
+            {
+                Unity.CurrentTestFailed = 1;
+            }
+        }
+
+        if (Unity.CurrentTestFailed)
+        {
+            UnityTestResultsFailBegin(lineNumber);
+            if (num_elements > 1)
+            {
+                UnityPrint(UnityStrElement);
+                UnityPrintNumberUnsigned(j);
+            }
+            UnityPrintExpectedAndActualStrings((const char*)(expected[j]), (const char*)(actual[j]));
+            UnityAddMsgIfSpecified(msg);
+            UNITY_FAIL_AND_BAIL;
+        }
+    } while (++j < num_elements);
+}
+
+/*-----------------------------------------------*/
+void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected,
+                             UNITY_INTERNAL_PTR actual,
+                             const _UU32 length,
+                             const _UU32 num_elements,
+                             const char* msg,
+                             const UNITY_LINE_TYPE lineNumber)
+{
+    UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected;
+    UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual;
+    _UU32 elements = num_elements;
+    _UU32 bytes;
+
+    UNITY_SKIP_EXECUTION;
+
+    if ((elements == 0) || (length == 0))
+    {
+        UnityPrintPointlessAndBail();
+    }
+
+    if (UnityCheckArraysForNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg) == 1)
+        return;
+
+    while (elements--)
+    {
+        /* /////////////////////////////////// */
+        bytes = length;
+        while (bytes--)
+        {
+            if (*ptr_exp != *ptr_act)
+            {
+                UnityTestResultsFailBegin(lineNumber);
+                UnityPrint(UnityStrMemory);
+                if (num_elements > 1)
+                {
+                    UnityPrint(UnityStrElement);
+                    UnityPrintNumberUnsigned(num_elements - elements - 1);
+                }
+                UnityPrint(UnityStrByte);
+                UnityPrintNumberUnsigned(length - bytes - 1);
+                UnityPrint(UnityStrExpected);
+                UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8);
+                UnityPrint(UnityStrWas);
+                UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8);
+                UnityAddMsgIfSpecified(msg);
+                UNITY_FAIL_AND_BAIL;
+            }
+            ptr_exp = (UNITY_INTERNAL_PTR)((_UP)ptr_exp + 1);
+            ptr_act = (UNITY_INTERNAL_PTR)((_UP)ptr_act + 1);
+        }
+        /* /////////////////////////////////// */
+
+    }
+}
+
+/*-----------------------------------------------
+ * Control Functions
+ *-----------------------------------------------*/
+
+void UnityFail(const char* msg, const UNITY_LINE_TYPE line)
+{
+   UNITY_SKIP_EXECUTION;
+
+    UnityTestResultsBegin(Unity.TestFile, line);
+    /* SA_PATCH: Make failures more noticable. */
+    UnityPrintVisibleFailure();
+    //UnityPrintFail();
+    if (msg != NULL)
+    {
+        UNITY_OUTPUT_CHAR(':');
+
+#ifndef UNITY_EXCLUDE_DETAILS
+        if (Unity.CurrentDetail1)
+        {
+            UnityPrint(UnityStrDetail1Name);
+            UnityPrint(Unity.CurrentDetail1);
+            if (Unity.CurrentDetail2)
+            {
+                UnityPrint(UnityStrDetail2Name);
+                UnityPrint(Unity.CurrentDetail2);
+            }
+            UnityPrint(UnityStrSpacer);
+        }
+#endif
+        if (msg[0] != ' ')
+        {
+            UNITY_OUTPUT_CHAR(' ');
+        }
+        UnityPrint(msg);
+    }
+
+    UNITY_FAIL_AND_BAIL;
+}
+
+/*-----------------------------------------------*/
+void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line)
+{
+    UNITY_SKIP_EXECUTION;
+
+    UnityTestResultsBegin(Unity.TestFile, line);
+    UnityPrint(UnityStrIgnore);
+    if (msg != NULL)
+    {
+      UNITY_OUTPUT_CHAR(':');
+      UNITY_OUTPUT_CHAR(' ');
+      UnityPrint(msg);
+    }
+    UNITY_IGNORE_AND_BAIL;
+}
+
+/*-----------------------------------------------*/
+#if defined(UNITY_WEAK_ATTRIBUTE)
+    UNITY_WEAK_ATTRIBUTE void setUp(void) { }
+    UNITY_WEAK_ATTRIBUTE void tearDown(void) { }
+#elif defined(UNITY_WEAK_PRAGMA)
+#   pragma weak setUp
+    void setUp(void) { }
+#   pragma weak tearDown
+    void tearDown(void) { }
+#endif
+/*-----------------------------------------------*/
+void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum)
+{
+    Unity.CurrentTestName = FuncName;
+    Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum;
+    Unity.NumberOfTests++;
+    UNITY_CLR_DETAILS();
+    if (TEST_PROTECT())
+    {
+        setUp();
+        Func();
+    }
+    if (TEST_PROTECT() && !(Unity.CurrentTestIgnored))
+    {
+        tearDown();
+    }
+    UnityConcludeTest();
+}
+
+/*-----------------------------------------------*/
+void UnityBegin(const char* filename)
+{
+    Unity.TestFile = filename;
+    Unity.CurrentTestName = NULL;
+    Unity.CurrentTestLineNumber = 0;
+    Unity.NumberOfTests = 0;
+    Unity.TestFailures = 0;
+    Unity.TestIgnores = 0;
+    Unity.CurrentTestFailed = 0;
+    Unity.CurrentTestIgnored = 0;
+
+    UNITY_CLR_DETAILS();
+    UNITY_OUTPUT_START();
+}
+
+/*-----------------------------------------------*/
+int UnityEnd(void)
+{
+    UNITY_PRINT_EOL();
+    UnityPrint(UnityStrBreaker);
+    UNITY_PRINT_EOL();
+    UnityPrintNumber((_U_SINT)(Unity.NumberOfTests));
+    UnityPrint(UnityStrResultsTests);
+    UnityPrintNumber((_U_SINT)(Unity.TestFailures));
+    UnityPrint(UnityStrResultsFailures);
+    UnityPrintNumber((_U_SINT)(Unity.TestIgnores));
+    UnityPrint(UnityStrResultsIgnored);
+    UNITY_PRINT_EOL();
+    if (Unity.TestFailures == 0U)
+    {
+        UnityPrintOk();
+    }
+    else
+    {
+        UnityPrintFail();
+#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL
+        UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D');
+#endif
+    }
+    UNITY_PRINT_EOL();
+    UNITY_FLUSH_CALL();
+    UNITY_OUTPUT_COMPLETE();
+    return (int)(Unity.TestFailures);
+}
+
+/*-----------------------------------------------*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/src/unity.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,291 @@
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef UNITY_FRAMEWORK_H
+#define UNITY_FRAMEWORK_H
+#define UNITY
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#define UNITY_SUPPORT_64
+#include "unity_internals.h"
+
+void setUp(void);
+void tearDown(void);
+
+/*-------------------------------------------------------
+ * Configuration Options
+ *-------------------------------------------------------
+ * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above.
+
+ * Integers/longs/pointers
+ *     - Unity attempts to automatically discover your integer sizes
+ *       - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in <stdint.h>
+ *       - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in <limits.h>
+ *       - define UNITY_EXCLUDE_SIZEOF to stop attempting to use sizeof in macros
+ *     - If you cannot use the automatic methods above, you can force Unity by using these options:
+ *       - define UNITY_SUPPORT_64
+ *       - define UNITY_INT_WIDTH
+ *       - UNITY_LONG_WIDTH
+ *       - UNITY_POINTER_WIDTH
+
+ * Floats
+ *     - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons
+ *     - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT
+ *     - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats
+ *     - define UNITY_FLOAT_VERBOSE to print floating point values in errors (uses sprintf)
+ *     - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons
+ *     - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default)
+ *     - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE
+ *     - define UNITY_DOUBLE_TYPE to specify something other than double
+ *     - define UNITY_DOUBLE_VERBOSE to print floating point values in errors (uses sprintf)
+ *     - define UNITY_VERBOSE_NUMBER_MAX_LENGTH to change maximum length of printed numbers (used by sprintf)
+
+ * Output
+ *     - by default, Unity prints to standard out with putchar.  define UNITY_OUTPUT_CHAR(a) with a different function if desired
+ *     - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure
+
+ * Optimization
+ *     - by default, line numbers are stored in unsigned shorts.  Define UNITY_LINE_TYPE with a different type if your files are huge
+ *     - by default, test and failure counters are unsigned shorts.  Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests.
+
+ * Test Cases
+ *     - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script
+
+ * Parameterized Tests
+ *     - you'll want to create a define of TEST_CASE(...) which basically evaluates to nothing
+
+ *-------------------------------------------------------
+ * Basic Fail and Ignore
+ *-------------------------------------------------------*/
+
+#define TEST_FAIL_MESSAGE(message)                                                                 UNITY_TEST_FAIL(__LINE__, (message))
+#define TEST_FAIL()                                                                                UNITY_TEST_FAIL(__LINE__, NULL)
+#define TEST_IGNORE_MESSAGE(message)                                                               UNITY_TEST_IGNORE(__LINE__, (message))
+#define TEST_IGNORE()                                                                              UNITY_TEST_IGNORE(__LINE__, NULL)
+#define TEST_ONLY()
+
+/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails.
+ * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */
+#define TEST_PASS()                                                                                longjmp(Unity.AbortFrame, 1)
+
+/*-------------------------------------------------------
+ * Test Asserts (simple)
+ *-------------------------------------------------------*/
+
+/* Boolean */
+#define TEST_ASSERT(condition)                                                                     UNITY_TEST_ASSERT(       (condition), __LINE__, " Expression Evaluated To FALSE")
+#define TEST_ASSERT_TRUE(condition)                                                                UNITY_TEST_ASSERT(       (condition), __LINE__, " Expected TRUE Was FALSE")
+#define TEST_ASSERT_UNLESS(condition)                                                              UNITY_TEST_ASSERT(      !(condition), __LINE__, " Expression Evaluated To TRUE")
+#define TEST_ASSERT_FALSE(condition)                                                               UNITY_TEST_ASSERT(      !(condition), __LINE__, " Expected FALSE Was TRUE")
+#define TEST_ASSERT_NULL(pointer)                                                                  UNITY_TEST_ASSERT_NULL(    (pointer), __LINE__, " Expected NULL")
+#define TEST_ASSERT_NOT_NULL(pointer)                                                              UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL")
+
+/* Integers (of all sizes) */
+#define TEST_ASSERT_EQUAL_INT(expected, actual)                                                    UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT8(expected, actual)                                                   UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT16(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT32(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT64(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL(expected, actual)                                                        UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_NOT_EQUAL(expected, actual)                                                    UNITY_TEST_ASSERT(((expected) !=  (actual)), __LINE__, " Expected Not-Equal")
+#define TEST_ASSERT_EQUAL_UINT(expected, actual)                                                   UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT8(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT16(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT32(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT64(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX(expected, actual)                                                    UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX8(expected, actual)                                                   UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX16(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX32(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX64(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BITS(mask, expected, actual)                                                   UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BITS_HIGH(mask, actual)                                                        UNITY_TEST_ASSERT_BITS((mask), (_UU32)(-1), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BITS_LOW(mask, actual)                                                         UNITY_TEST_ASSERT_BITS((mask), (_UU32)(0), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BIT_HIGH(bit, actual)                                                          UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(-1), (actual), __LINE__, NULL)
+#define TEST_ASSERT_BIT_LOW(bit, actual)                                                           UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(0), (actual), __LINE__, NULL)
+
+/* Integer Ranges (of all sizes) */
+#define TEST_ASSERT_INT_WITHIN(delta, expected, actual)                                            UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual)                                           UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual)                                           UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual)                                            UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual)                                           UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+
+/* Structs and Strings */
+#define TEST_ASSERT_EQUAL_PTR(expected, actual)                                                    UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_STRING(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len)                                        UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len)                                            UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL)
+
+/* Arrays */
+#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements)                               UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements)                                UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements)                        UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL)
+
+/* Floating Point (If Enabled) */
+#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual)                                          UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_FLOAT(expected, actual)                                                  UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements)                              UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_INF(actual)                                                           UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual)                                                       UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NAN(actual)                                                           UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual)                                                   UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual)                                                       UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual)                                                   UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual)                                                       UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual)                                               UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
+
+/* Double (If Enabled) */
+#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual)                                         UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual)                                                 UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL)
+#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements)                             UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_INF(actual)                                                          UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual)                                                      UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NAN(actual)                                                          UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual)                                                  UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual)                                                      UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual)                                                  UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual)                                                      UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL)
+#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual)                                              UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL)
+
+/*-------------------------------------------------------
+ * Test Asserts (with additional messages)
+ *-------------------------------------------------------*/
+
+/* Boolean */
+#define TEST_ASSERT_MESSAGE(condition, message)                                                    UNITY_TEST_ASSERT(       (condition), __LINE__, (message))
+#define TEST_ASSERT_TRUE_MESSAGE(condition, message)                                               UNITY_TEST_ASSERT(       (condition), __LINE__, (message))
+#define TEST_ASSERT_UNLESS_MESSAGE(condition, message)                                             UNITY_TEST_ASSERT(      !(condition), __LINE__, (message))
+#define TEST_ASSERT_FALSE_MESSAGE(condition, message)                                              UNITY_TEST_ASSERT(      !(condition), __LINE__, (message))
+#define TEST_ASSERT_NULL_MESSAGE(pointer, message)                                                 UNITY_TEST_ASSERT_NULL(    (pointer), __LINE__, (message))
+#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message)                                             UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message))
+
+/* Integers (of all sizes) */
+#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message)                                  UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message)                                       UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT(((expected) !=  (actual)), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message)                                  UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message)                                  UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message)                                  UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message)                                       UNITY_TEST_ASSERT_BITS((mask), (_UU32)(-1), (actual), __LINE__, (message))
+#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message)                                        UNITY_TEST_ASSERT_BITS((mask), (_UU32)(0), (actual), __LINE__, (message))
+#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message)                                         UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(-1), (actual), __LINE__, (message))
+#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message)                                          UNITY_TEST_ASSERT_BITS(((_UU32)1 << (bit)), (_UU32)(0), (actual), __LINE__, (message))
+
+/* Integer Ranges (of all sizes) */
+#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message)                           UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message)                          UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message)                          UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message)                           UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message)                          UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message))
+
+/* Structs and Strings */
+#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message)                                   UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message)                       UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message)                           UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message))
+
+/* Arrays */
+#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message)              UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message)               UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message)       UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message))
+
+/* Floating Point (If Enabled) */
+#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message)                         UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message)                                 UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message)             UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message)                                          UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message)                                      UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message)                                          UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message)                                  UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message)                                      UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message)                                  UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message)                                      UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message)                              UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message))
+
+/* Double (If Enabled) */
+#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message)                        UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message)                                UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message))
+#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message)            UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message)                                         UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message)                                     UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message)                                         UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message)                                 UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message)                                     UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message)                                 UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message)                                     UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message))
+#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message)                             UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message))
+
+/* end of UNITY_FRAMEWORK_H */
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/src/unity_internals.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,794 @@
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#ifndef UNITY_INTERNALS_H
+#define UNITY_INTERNALS_H
+
+#ifdef UNITY_INCLUDE_CONFIG_H
+//#include "unity_config.h"
+#endif
+
+#include <setjmp.h>
+
+/* Unity Attempts to Auto-Detect Integer Types
+ * Attempt 1: UINT_MAX, ULONG_MAX, etc in <stdint.h>
+ * Attempt 2: UINT_MAX, ULONG_MAX, etc in <limits.h>
+ * Attempt 3: Deduced from sizeof() macros */
+#ifndef UNITY_EXCLUDE_STDINT_H
+#include <stdint.h>
+#endif
+
+#ifndef UNITY_EXCLUDE_LIMITS_H
+#include <limits.h>
+#endif
+
+#ifndef UNITY_EXCLUDE_SIZEOF
+#ifndef UINT_MAX
+#define UINT_MAX     (sizeof(unsigned int) * 256 - 1)
+#endif
+#ifndef ULONG_MAX
+#define ULONG_MAX    (sizeof(unsigned long) * 256 - 1)
+#endif
+#ifndef UINTPTR_MAX
+/* apparently this is not a constant expression: (sizeof(unsigned int *) * 256 - 1) so we have to just let this fall through */
+#endif
+#endif
+
+#ifndef UNITY_EXCLUDE_MATH_H
+#include <math.h>
+#endif
+
+/*-------------------------------------------------------
+ * Guess Widths If Not Specified
+ *-------------------------------------------------------*/
+
+/* Determine the size of an int, if not already specificied.
+ * We cannot use sizeof(int), because it is not yet defined
+ * at this stage in the trnslation of the C program.
+ * Therefore, infer it from UINT_MAX if possible. */
+#ifndef UNITY_INT_WIDTH
+  #ifdef UINT_MAX
+    #if (UINT_MAX == 0xFFFF)
+      #define UNITY_INT_WIDTH (16)
+    #elif (UINT_MAX == 0xFFFFFFFF)
+      #define UNITY_INT_WIDTH (32)
+    #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF)
+      #define UNITY_INT_WIDTH (64)
+    #endif
+  #endif
+#endif
+#ifndef UNITY_INT_WIDTH
+  #define UNITY_INT_WIDTH (32)
+#endif
+
+/* Determine the size of a long, if not already specified,
+ * by following the process used above to define
+ * UNITY_INT_WIDTH. */
+#ifndef UNITY_LONG_WIDTH
+  #ifdef ULONG_MAX
+    #if (ULONG_MAX == 0xFFFF)
+      #define UNITY_LONG_WIDTH (16)
+    #elif (ULONG_MAX == 0xFFFFFFFF)
+      #define UNITY_LONG_WIDTH (32)
+    #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF)
+      #define UNITY_LONG_WIDTH (64)
+    #endif
+  #endif
+#endif
+#ifndef UNITY_LONG_WIDTH
+  #define UNITY_LONG_WIDTH (32)
+#endif
+
+/* Determine the size of a pointer, if not already specified,
+ * by following the process used above to define
+ * UNITY_INT_WIDTH. */
+#ifndef UNITY_POINTER_WIDTH
+  #ifdef UINTPTR_MAX
+    #if (UINTPTR_MAX+0 <= 0xFFFF)
+      #define UNITY_POINTER_WIDTH (16)
+    #elif (UINTPTR_MAX+0 <= 0xFFFFFFFF)
+      #define UNITY_POINTER_WIDTH (32)
+    #elif (UINTPTR_MAX+0 <= 0xFFFFFFFFFFFFFFFF)
+      #define UNITY_POINTER_WIDTH (64)
+    #endif
+  #endif
+#endif
+#ifndef UNITY_POINTER_WIDTH
+  #ifdef INTPTR_MAX
+    #if (INTPTR_MAX+0 <= 0x7FFF)
+      #define UNITY_POINTER_WIDTH (16)
+    #elif (INTPTR_MAX+0 <= 0x7FFFFFFF)
+      #define UNITY_POINTER_WIDTH (32)
+    #elif (INTPTR_MAX+0 <= 0x7FFFFFFFFFFFFFFF)
+      #define UNITY_POINTER_WIDTH (64)
+    #endif
+  #endif
+#endif
+#ifndef UNITY_POINTER_WIDTH
+  #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH
+#endif
+
+/*-------------------------------------------------------
+ * Int Support (Define types based on detected sizes)
+ *-------------------------------------------------------*/
+
+#if (UNITY_INT_WIDTH == 32)
+    typedef unsigned char   _UU8;
+    typedef unsigned short  _UU16;
+    typedef unsigned int    _UU32;
+    typedef signed char     _US8;
+    typedef signed short    _US16;
+    typedef signed int      _US32;
+#elif (UNITY_INT_WIDTH == 16)
+    typedef unsigned char   _UU8;
+    typedef unsigned int    _UU16;
+    typedef unsigned long   _UU32;
+    typedef signed char     _US8;
+    typedef signed int      _US16;
+    typedef signed long     _US32;
+#else
+    #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported)
+#endif
+
+/*-------------------------------------------------------
+ * 64-bit Support
+ *-------------------------------------------------------*/
+
+#ifndef UNITY_SUPPORT_64
+#if UNITY_LONG_WIDTH > 32
+#define UNITY_SUPPORT_64
+#endif
+#endif
+#ifndef UNITY_SUPPORT_64
+#if UNITY_POINTER_WIDTH > 32
+#define UNITY_SUPPORT_64
+#endif
+#endif
+
+#ifndef UNITY_SUPPORT_64
+
+/* No 64-bit Support */
+typedef _UU32 _U_UINT;
+typedef _US32 _U_SINT;
+
+#else
+
+/* 64-bit Support */
+#if (UNITY_LONG_WIDTH == 32)
+    typedef unsigned long long _UU64;
+    typedef signed long long   _US64;
+#elif (UNITY_LONG_WIDTH == 64)
+    typedef unsigned long      _UU64;
+    typedef signed long        _US64;
+#else
+    #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported)
+#endif
+typedef _UU64 _U_UINT;
+typedef _US64 _U_SINT;
+
+#endif
+
+/*-------------------------------------------------------
+ * Pointer Support
+ *-------------------------------------------------------*/
+
+#if (UNITY_POINTER_WIDTH == 32)
+    typedef _UU32 _UP;
+#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32
+#elif (UNITY_POINTER_WIDTH == 64)
+    typedef _UU64 _UP;
+#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64
+#elif (UNITY_POINTER_WIDTH == 16)
+    typedef _UU16 _UP;
+#define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16
+#else
+    #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported)
+#endif
+
+#ifndef UNITY_PTR_ATTRIBUTE
+#define UNITY_PTR_ATTRIBUTE
+#endif
+
+#ifndef UNITY_INTERNAL_PTR
+#define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void*
+/* #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const _UU8* */
+#endif
+
+/*-------------------------------------------------------
+ * Float Support
+ *-------------------------------------------------------*/
+
+#ifdef UNITY_EXCLUDE_FLOAT
+
+/* No Floating Point Support */
+#undef UNITY_INCLUDE_FLOAT
+#undef UNITY_FLOAT_PRECISION
+#undef UNITY_FLOAT_TYPE
+#undef UNITY_FLOAT_VERBOSE
+
+#else
+
+#ifndef UNITY_INCLUDE_FLOAT
+#define UNITY_INCLUDE_FLOAT
+#endif
+
+/* Floating Point Support */
+#ifndef UNITY_FLOAT_PRECISION
+#define UNITY_FLOAT_PRECISION (0.00001f)
+#endif
+#ifndef UNITY_FLOAT_TYPE
+#define UNITY_FLOAT_TYPE float
+#endif
+typedef UNITY_FLOAT_TYPE _UF;
+
+#ifndef isinf
+#define isinf(n) (((1.0f / f_zero) == n) ? 1 : 0) || (((-1.0f / f_zero) == n) ? 1 : 0)
+#define UNITY_FLOAT_NEEDS_ZERO
+#endif
+
+#ifndef isnan
+#define isnan(n) ((n != n) ? 1 : 0)
+#endif
+
+#ifndef isneg
+#define isneg(n) ((n < 0.0f) ? 1 : 0)
+#endif
+
+#ifndef ispos
+#define ispos(n) ((n > 0.0f) ? 1 : 0)
+#endif
+
+#endif
+
+/*-------------------------------------------------------
+ * Double Float Support
+ *-------------------------------------------------------*/
+
+/* unlike FLOAT, we DON'T include by default */
+#ifndef UNITY_EXCLUDE_DOUBLE
+#ifndef UNITY_INCLUDE_DOUBLE
+#define UNITY_EXCLUDE_DOUBLE
+#endif
+#endif
+
+#ifdef UNITY_EXCLUDE_DOUBLE
+
+/* No Floating Point Support */
+#undef UNITY_DOUBLE_PRECISION
+#undef UNITY_DOUBLE_TYPE
+#undef UNITY_DOUBLE_VERBOSE
+
+#ifdef UNITY_INCLUDE_DOUBLE
+#undef UNITY_INCLUDE_DOUBLE
+#endif
+
+#else
+
+/* Double Floating Point Support */
+#ifndef UNITY_DOUBLE_PRECISION
+#define UNITY_DOUBLE_PRECISION (1e-12f)
+#endif
+#ifndef UNITY_DOUBLE_TYPE
+#define UNITY_DOUBLE_TYPE double
+#endif
+typedef UNITY_DOUBLE_TYPE _UD;
+
+#endif
+
+#ifdef UNITY_DOUBLE_VERBOSE
+#ifndef UNITY_FLOAT_VERBOSE
+#define UNITY_FLOAT_VERBOSE
+#endif
+#endif
+
+/*-------------------------------------------------------
+ * Output Method: stdout (DEFAULT)
+ *-------------------------------------------------------*/
+#ifndef UNITY_OUTPUT_CHAR
+/* Default to using putchar, which is defined in stdio.h */
+#include <stdio.h>
+#define UNITY_OUTPUT_CHAR(a) (void)putchar(a)
+#else
+  /* If defined as something else, make sure we declare it here so it's ready for use */
+  #ifndef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION
+extern void UNITY_OUTPUT_CHAR(int);
+  #endif
+#endif
+
+#ifndef UNITY_OUTPUT_FLUSH
+/* Default to using fflush, which is defined in stdio.h */
+#include <stdio.h>
+#define UNITY_OUTPUT_FLUSH (void)fflush(stdout)
+#else
+  /* If defined as something else, make sure we declare it here so it's ready for use */
+  #ifndef UNITY_OMIT_OUTPUT_FLUSH_HEADER_DECLARATION
+extern void UNITY_OUTPUT_FLUSH(void);
+  #endif
+#endif
+
+#ifndef UNITY_OUTPUT_FLUSH
+#define UNITY_FLUSH_CALL()
+#else
+#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH
+#endif
+
+#ifndef UNITY_PRINT_EOL
+#define UNITY_PRINT_EOL()    UNITY_OUTPUT_CHAR('\n')
+#endif
+
+#ifndef UNITY_OUTPUT_START
+#define UNITY_OUTPUT_START()
+#endif
+
+#ifndef UNITY_OUTPUT_COMPLETE
+#define UNITY_OUTPUT_COMPLETE()
+#endif
+
+/*-------------------------------------------------------
+ * Footprint
+ *-------------------------------------------------------*/
+
+#ifndef UNITY_LINE_TYPE
+#define UNITY_LINE_TYPE _U_UINT
+#endif
+
+#ifndef UNITY_COUNTER_TYPE
+#define UNITY_COUNTER_TYPE _U_UINT
+#endif
+
+/*-------------------------------------------------------
+ * Language Features Available
+ *-------------------------------------------------------*/
+#if !defined(UNITY_WEAK_ATTRIBUTE) && !defined(UNITY_WEAK_PRAGMA)
+#   ifdef __GNUC__ /* includes clang */
+#       if !(defined(__WIN32__) && defined(__clang__))
+#           define UNITY_WEAK_ATTRIBUTE __attribute__((weak))
+#       endif
+#   endif
+#endif
+
+#ifdef UNITY_NO_WEAK
+#   undef UNITY_WEAK_ATTRIBUTE
+#   undef UNITY_WEAK_PRAGMA
+#endif
+
+
+/*-------------------------------------------------------
+ * Internal Structs Needed
+ *-------------------------------------------------------*/
+
+typedef void (*UnityTestFunction)(void);
+
+#define UNITY_DISPLAY_RANGE_INT  (0x10)
+#define UNITY_DISPLAY_RANGE_UINT (0x20)
+#define UNITY_DISPLAY_RANGE_HEX  (0x40)
+#define UNITY_DISPLAY_RANGE_AUTO (0x80)
+
+typedef enum
+{
+#if (UNITY_INT_WIDTH == 16)
+    UNITY_DISPLAY_STYLE_INT      = 2 + UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO,
+#elif (UNITY_INT_WIDTH  == 32)
+    UNITY_DISPLAY_STYLE_INT      = 4 + UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO,
+#elif (UNITY_INT_WIDTH  == 64)
+    UNITY_DISPLAY_STYLE_INT      = 8 + UNITY_DISPLAY_RANGE_INT + UNITY_DISPLAY_RANGE_AUTO,
+#endif
+    UNITY_DISPLAY_STYLE_INT8     = 1 + UNITY_DISPLAY_RANGE_INT,
+    UNITY_DISPLAY_STYLE_INT16    = 2 + UNITY_DISPLAY_RANGE_INT,
+    UNITY_DISPLAY_STYLE_INT32    = 4 + UNITY_DISPLAY_RANGE_INT,
+#ifdef UNITY_SUPPORT_64
+    UNITY_DISPLAY_STYLE_INT64    = 8 + UNITY_DISPLAY_RANGE_INT,
+#endif
+
+#if (UNITY_INT_WIDTH == 16)
+    UNITY_DISPLAY_STYLE_UINT     = 2 + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO,
+#elif (UNITY_INT_WIDTH  == 32)
+    UNITY_DISPLAY_STYLE_UINT     = 4 + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO,
+#elif (UNITY_INT_WIDTH  == 64)
+    UNITY_DISPLAY_STYLE_UINT     = 8 + UNITY_DISPLAY_RANGE_UINT + UNITY_DISPLAY_RANGE_AUTO,
+#endif
+    UNITY_DISPLAY_STYLE_UINT8    = 1 + UNITY_DISPLAY_RANGE_UINT,
+    UNITY_DISPLAY_STYLE_UINT16   = 2 + UNITY_DISPLAY_RANGE_UINT,
+    UNITY_DISPLAY_STYLE_UINT32   = 4 + UNITY_DISPLAY_RANGE_UINT,
+#ifdef UNITY_SUPPORT_64
+    UNITY_DISPLAY_STYLE_UINT64   = 8 + UNITY_DISPLAY_RANGE_UINT,
+#endif
+    UNITY_DISPLAY_STYLE_HEX8     = 1 + UNITY_DISPLAY_RANGE_HEX,
+    UNITY_DISPLAY_STYLE_HEX16    = 2 + UNITY_DISPLAY_RANGE_HEX,
+    UNITY_DISPLAY_STYLE_HEX32    = 4 + UNITY_DISPLAY_RANGE_HEX,
+#ifdef UNITY_SUPPORT_64
+    UNITY_DISPLAY_STYLE_HEX64    = 8 + UNITY_DISPLAY_RANGE_HEX,
+#endif
+    UNITY_DISPLAY_STYLE_UNKNOWN
+} UNITY_DISPLAY_STYLE_T;
+
+#ifndef UNITY_EXCLUDE_FLOAT
+typedef enum _UNITY_FLOAT_TRAIT_T
+{
+    UNITY_FLOAT_IS_NOT_INF       = 0,
+    UNITY_FLOAT_IS_INF,
+    UNITY_FLOAT_IS_NOT_NEG_INF,
+    UNITY_FLOAT_IS_NEG_INF,
+    UNITY_FLOAT_IS_NOT_NAN,
+    UNITY_FLOAT_IS_NAN,
+    UNITY_FLOAT_IS_NOT_DET,
+    UNITY_FLOAT_IS_DET,
+    UNITY_FLOAT_INVALID_TRAIT
+} UNITY_FLOAT_TRAIT_T;
+#endif
+
+struct _Unity
+{
+    const char* TestFile;
+    const char* CurrentTestName;
+#ifndef UNITY_EXCLUDE_DETAILS
+    const char* CurrentDetail1;
+    const char* CurrentDetail2;
+#endif
+    UNITY_LINE_TYPE CurrentTestLineNumber;
+    UNITY_COUNTER_TYPE NumberOfTests;
+    UNITY_COUNTER_TYPE TestFailures;
+    UNITY_COUNTER_TYPE TestIgnores;
+    UNITY_COUNTER_TYPE CurrentTestFailed;
+    UNITY_COUNTER_TYPE CurrentTestIgnored;
+    jmp_buf AbortFrame;
+};
+
+extern struct _Unity Unity;
+
+/*-------------------------------------------------------
+ * Test Suite Management
+ *-------------------------------------------------------*/
+
+void UnityBegin(const char* filename);
+int  UnityEnd(void);
+void UnityConcludeTest(void);
+void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum);
+
+/*-------------------------------------------------------
+ * Details Support
+ *-------------------------------------------------------*/
+
+#ifdef UNITY_EXCLUDE_DETAILS
+#define UNITY_CLR_DETAILS()
+#define UNITY_SET_DETAIL(d1)
+#define UNITY_SET_DETAILS(d1,d2)
+#else
+#define UNITY_CLR_DETAILS()      { Unity.CurrentDetail1 = 0;   Unity.CurrentDetail2 = 0;  }
+#define UNITY_SET_DETAIL(d1)     { Unity.CurrentDetail1 = d1;  Unity.CurrentDetail2 = 0;  }
+#define UNITY_SET_DETAILS(d1,d2) { Unity.CurrentDetail1 = d1;  Unity.CurrentDetail2 = d2; }
+
+#ifndef UNITY_DETAIL1_NAME
+#define UNITY_DETAIL1_NAME "Function"
+#endif
+
+#ifndef UNITY_DETAIL2_NAME
+#define UNITY_DETAIL2_NAME "Argument"
+#endif
+#endif
+
+/*-------------------------------------------------------
+ * Test Output
+ *-------------------------------------------------------*/
+
+void UnityPrint(const char* string);
+void UnityPrintMask(const _U_UINT mask, const _U_UINT number);
+void UnityPrintNumberByStyle(const _U_SINT number, const UNITY_DISPLAY_STYLE_T style);
+void UnityPrintNumber(const _U_SINT number);
+void UnityPrintNumberUnsigned(const _U_UINT number);
+void UnityPrintNumberHex(const _U_UINT number, const char nibbles);
+
+#ifdef UNITY_FLOAT_VERBOSE
+void UnityPrintFloat(const _UF number);
+#endif
+
+/*-------------------------------------------------------
+ * Test Assertion Fuctions
+ *-------------------------------------------------------
+ *  Use the macros below this section instead of calling
+ *  these directly. The macros have a consistent naming
+ *  convention and will pull in file and line information
+ *  for you. */
+
+void UnityAssertEqualNumber(const _U_SINT expected,
+                            const _U_SINT actual,
+                            const char* msg,
+                            const UNITY_LINE_TYPE lineNumber,
+                            const UNITY_DISPLAY_STYLE_T style);
+
+void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected,
+                              UNITY_INTERNAL_PTR actual,
+                              const _UU32 num_elements,
+                              const char* msg,
+                              const UNITY_LINE_TYPE lineNumber,
+                              const UNITY_DISPLAY_STYLE_T style);
+
+void UnityAssertBits(const _U_SINT mask,
+                     const _U_SINT expected,
+                     const _U_SINT actual,
+                     const char* msg,
+                     const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualString(const char* expected,
+                            const char* actual,
+                            const char* msg,
+                            const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualStringLen(const char* expected,
+                            const char* actual,
+                            const _UU32 length,
+                            const char* msg,
+                            const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualStringArray( const char** expected,
+                                  const char** actual,
+                                  const _UU32 num_elements,
+                                  const char* msg,
+                                  const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected,
+                             UNITY_INTERNAL_PTR actual,
+                             const _UU32 length,
+                             const _UU32 num_elements,
+                             const char* msg,
+                             const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertNumbersWithin(const _U_UINT delta,
+                              const _U_SINT expected,
+                              const _U_SINT actual,
+                              const char* msg,
+                              const UNITY_LINE_TYPE lineNumber,
+                              const UNITY_DISPLAY_STYLE_T style);
+
+void UnityFail(const char* message, const UNITY_LINE_TYPE line);
+
+void UnityIgnore(const char* message, const UNITY_LINE_TYPE line);
+
+#ifndef UNITY_EXCLUDE_FLOAT
+void UnityAssertFloatsWithin(const _UF delta,
+                             const _UF expected,
+                             const _UF actual,
+                             const char* msg,
+                             const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualFloatArray(UNITY_PTR_ATTRIBUTE const _UF* expected,
+                                UNITY_PTR_ATTRIBUTE const _UF* actual,
+                                const _UU32 num_elements,
+                                const char* msg,
+                                const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertFloatSpecial(const _UF actual,
+                             const char* msg,
+                             const UNITY_LINE_TYPE lineNumber,
+                             const UNITY_FLOAT_TRAIT_T style);
+#endif
+
+#ifndef UNITY_EXCLUDE_DOUBLE
+void UnityAssertDoublesWithin(const _UD delta,
+                              const _UD expected,
+                              const _UD actual,
+                              const char* msg,
+                              const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertEqualDoubleArray(UNITY_PTR_ATTRIBUTE const _UD* expected,
+                                 UNITY_PTR_ATTRIBUTE const _UD* actual,
+                                 const _UU32 num_elements,
+                                 const char* msg,
+                                 const UNITY_LINE_TYPE lineNumber);
+
+void UnityAssertDoubleSpecial(const _UD actual,
+                              const char* msg,
+                              const UNITY_LINE_TYPE lineNumber,
+                              const UNITY_FLOAT_TRAIT_T style);
+#endif
+
+/*-------------------------------------------------------
+ * Error Strings We Might Need
+ *-------------------------------------------------------*/
+
+extern const char UnityStrErrFloat[];
+extern const char UnityStrErrDouble[];
+extern const char UnityStrErr64[];
+
+/*-------------------------------------------------------
+ * Test Running Macros
+ *-------------------------------------------------------*/
+
+#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0)
+
+#define TEST_ABORT() {longjmp(Unity.AbortFrame, 1);}
+
+/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */
+#ifndef RUN_TEST
+#ifdef __STDC_VERSION__
+#if __STDC_VERSION__ >= 199901L
+#define RUN_TEST(...) UnityDefaultTestRun(RUN_TEST_FIRST(__VA_ARGS__), RUN_TEST_SECOND(__VA_ARGS__))
+#define RUN_TEST_FIRST(...) RUN_TEST_FIRST_HELPER(__VA_ARGS__, throwaway)
+#define RUN_TEST_FIRST_HELPER(first, ...) (first), #first
+#define RUN_TEST_SECOND(...) RUN_TEST_SECOND_HELPER(__VA_ARGS__, __LINE__, throwaway)
+#define RUN_TEST_SECOND_HELPER(first, second, ...) (second)
+#endif
+#endif
+#endif
+
+/* If we can't do the tricky version, we'll just have to require them to always include the line number */
+#ifndef RUN_TEST
+#ifdef CMOCK
+#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num)
+#else
+#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__)
+#endif
+#endif
+
+#define TEST_LINE_NUM (Unity.CurrentTestLineNumber)
+#define TEST_IS_IGNORED (Unity.CurrentTestIgnored)
+#define UNITY_NEW_TEST(a) \
+    Unity.CurrentTestName = (a); \
+    Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \
+    Unity.NumberOfTests++;
+
+#ifndef UNITY_BEGIN
+#define UNITY_BEGIN() UnityBegin(__FILE__)
+#endif
+
+#ifndef UNITY_END
+#define UNITY_END() UnityEnd()
+#endif
+
+#define UNITY_UNUSED(x) (void)(sizeof(x))
+
+/*-------------------------------------------------------
+ * Basic Fail and Ignore
+ *-------------------------------------------------------*/
+
+#define UNITY_TEST_FAIL(line, message)   UnityFail(   (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line))
+
+/*-------------------------------------------------------
+ * Test Asserts
+ *-------------------------------------------------------*/
+
+#define UNITY_TEST_ASSERT(condition, line, message)                                              if (condition) {} else {UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message));}
+#define UNITY_TEST_ASSERT_NULL(pointer, line, message)                                           UNITY_TEST_ASSERT(((pointer) == NULL),  (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message)                                       UNITY_TEST_ASSERT(((pointer) != NULL),  (UNITY_LINE_TYPE)(line), (message))
+
+#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message)                             UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message)                            UnityAssertEqualNumber((_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message)                           UnityAssertEqualNumber((_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message)                           UnityAssertEqualNumber((_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message)                            UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message)                           UnityAssertEqualNumber((_U_SINT)(_UU8 )(expected), (_U_SINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message)                          UnityAssertEqualNumber((_U_SINT)(_UU16)(expected), (_U_SINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message)                          UnityAssertEqualNumber((_U_SINT)(_UU32)(expected), (_U_SINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message)                            UnityAssertEqualNumber((_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message)                           UnityAssertEqualNumber((_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message)                           UnityAssertEqualNumber((_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message)                            UnityAssertBits((_U_SINT)(mask), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line))
+
+#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message)                     UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message)                    UnityAssertNumbersWithin((_UU8 )(delta), (_U_SINT)(_US8 )(expected), (_U_SINT)(_US8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((_UU16)(delta), (_U_SINT)(_US16)(expected), (_U_SINT)(_US16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((_UU32)(delta), (_U_SINT)(_US32)(expected), (_U_SINT)(_US32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message)                    UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((_UU8 )(delta), (_U_SINT)(_U_UINT)(_UU8 )(expected), (_U_SINT)(_U_UINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message)                  UnityAssertNumbersWithin((_UU16)(delta), (_U_SINT)(_U_UINT)(_UU16)(expected), (_U_SINT)(_U_UINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message)                  UnityAssertNumbersWithin((_UU32)(delta), (_U_SINT)(_U_UINT)(_UU32)(expected), (_U_SINT)(_U_UINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message)                    UnityAssertNumbersWithin((_UU8 )(delta), (_U_SINT)(_U_UINT)(_UU8 )(expected), (_U_SINT)(_U_UINT)(_UU8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((_UU16)(delta), (_U_SINT)(_U_UINT)(_UU16)(expected), (_U_SINT)(_U_UINT)(_UU16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((_UU32)(delta), (_U_SINT)(_U_UINT)(_UU32)(expected), (_U_SINT)(_U_UINT)(_UU32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+
+#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message)                             UnityAssertEqualNumber((_U_SINT)(_UP)(expected), (_U_SINT)(_UP)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER)
+#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message)                          UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message)                 UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (_UU32)(len), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message)                     UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(len), 1, (message), (UNITY_LINE_TYPE)(line))
+
+#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message)         UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT)
+#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8)
+#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16)
+#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32)
+#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT)
+#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8)
+#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message)      UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16)
+#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message)      UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32)
+#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message)        UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8)
+#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16)
+#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32)
+#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message)         UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(_UP*)(expected), (UNITY_INTERNAL_PTR)(_UP*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER)
+#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message)      UnityAssertEqualStringArray((const char**)(expected), (const char**)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(len), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line))
+
+#ifdef UNITY_SUPPORT_64
+#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message)                           UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message)                          UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message)                           UnityAssertEqualNumber((_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message)      UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64)
+#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message)                  UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64)
+#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message)                   UnityAssertNumbersWithin((delta), (_U_SINT)(expected), (_U_SINT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64)
+#else
+#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message)                           UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message)                          UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message)                           UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message)       UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message)      UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message)       UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message)                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message)                  UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message)                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64)
+#endif
+
+#ifdef UNITY_EXCLUDE_FLOAT
+#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message)                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message)                           UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message)       UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message)                                    UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message)                                UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message)                                    UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message)                            UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message)                                UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message)                            UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message)                                UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message)                        UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat)
+#else
+#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message)                   UnityAssertFloatsWithin((_UF)(delta), (_UF)(expected), (_UF)(actual), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message)                           UNITY_TEST_ASSERT_FLOAT_WITHIN((_UF)(expected) * (_UF)UNITY_FLOAT_PRECISION, (_UF)(expected), (_UF)(actual), (UNITY_LINE_TYPE)(line), (message))
+#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message)       UnityAssertEqualFloatArray((_UF*)(expected), (_UF*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)(line))
+#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message)                                    UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message)                                UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message)                                    UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN)
+#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message)                            UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message)                                UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message)                            UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message)                                UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN)
+#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message)                        UnityAssertFloatSpecial((_UF)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET)
+#endif
+
+#ifdef UNITY_EXCLUDE_DOUBLE
+#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message)                  UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message)                          UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message)      UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message)                                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message)                               UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message)                                   UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message)                           UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message)                               UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message)                           UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message)                               UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message)                       UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble)
+#else
+#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message)                  UnityAssertDoublesWithin((_UD)(delta), (_UD)(expected), (_UD)(actual), (message), (UNITY_LINE_TYPE)line)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message)                          UNITY_TEST_ASSERT_DOUBLE_WITHIN((_UD)(expected) * (_UD)UNITY_DOUBLE_PRECISION, (_UD)expected, (_UD)actual, (UNITY_LINE_TYPE)(line), message)
+#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message)      UnityAssertEqualDoubleArray((_UD*)(expected), (_UD*)(actual), (_UU32)(num_elements), (message), (UNITY_LINE_TYPE)line)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message)                                   UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message)                               UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message)                                   UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message)                           UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message)                               UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message)                           UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message)                               UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN)
+#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message)                       UnityAssertDoubleSpecial((_UD)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET)
+#endif
+
+/*
+ * SA_PATCH: Output results using easy to parse tags.
+ * These tags are used when sending out verbose Unity output ("-v").
+ * They wrap each of the important data pieces, and allow parsing of the results by an
+ * external tool.
+ * The tags are always printed - this isn't configurable.
+ */
+#define UNITY_RESULTS_TAGS_TEST_START   "<***UnityTest***>"
+#define UNITY_RESULTS_TAGS_TEST_END     "</***UnityTest***>"
+
+#define UNITY_RESULTS_TAGS_RESULT_START "<***UnityResult***>"
+#define UNITY_RESULTS_TAGS_RESULT_END   "</***UnityResult***>"
+
+#define UNITY_RESULTS_TAGS_IGNORE_START "<***UnityIgnoredTest***>"
+#define UNITY_RESULTS_TAGS_IGNORE_END   "</***UnityIgnoredTest***>"
+
+/* End of UNITY_INTERNALS_H */
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_cmd.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,61 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  if (TEST_PROTECT()) \
+  { \
+    CEXCEPTION_T e; \
+    Try { \
+      setUp(); \
+      TestFunc(); \
+    } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+  } \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  tearDown();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("testdata/testsample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+  RUN_TEST(test_TheThirdThingToTest, 53);
+  RUN_TEST(test_TheFourthThingToTest, 58);
+
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_def.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,57 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+  } \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  tearDown();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("testdata/testsample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+  RUN_TEST(test_TheThirdThingToTest, 53);
+  RUN_TEST(test_TheFourthThingToTest, 58);
+
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_head1.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,55 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+  } \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "testsample_head1.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  tearDown();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("testdata/testsample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+  RUN_TEST(test_TheThirdThingToTest, 53);
+  RUN_TEST(test_TheFourthThingToTest, 58);
+
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_head1.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,15 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+#ifndef _TESTSAMPLE_HEAD1_H
+#define _TESTSAMPLE_HEAD1_H
+
+#include "unity.h"
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+void test_TheFirstThingToTest(void);
+void test_TheSecondThingToTest(void);
+void test_TheThirdThingToTest(void);
+void test_TheFourthThingToTest(void);
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_cmd.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,80 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  CMock_Init(); \
+  UNITY_CLR_DETAILS(); \
+  if (TEST_PROTECT()) \
+  { \
+    CEXCEPTION_T e; \
+    Try { \
+      setUp(); \
+      TestFunc(); \
+    } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+    CMock_Verify(); \
+  } \
+  CMock_Destroy(); \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+  Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+  Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+  Mockstanky_Destroy();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  CMock_Verify();
+  CMock_Destroy();
+  tearDown();
+  CMock_Init();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("testdata/mocksample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+
+  CMock_Guts_MemFreeFinal();
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_def.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,76 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  CMock_Init(); \
+  UNITY_CLR_DETAILS(); \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+    CMock_Verify(); \
+  } \
+  CMock_Destroy(); \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+  Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+  Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+  Mockstanky_Destroy();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  CMock_Verify();
+  CMock_Destroy();
+  tearDown();
+  CMock_Init();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("testdata/mocksample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+
+  CMock_Guts_MemFreeFinal();
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_head1.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,75 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  CMock_Init(); \
+  UNITY_CLR_DETAILS(); \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+    CMock_Verify(); \
+  } \
+  CMock_Destroy(); \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "testsample_mock_head1.h"
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+  Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+  Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+  Mockstanky_Destroy();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  CMock_Verify();
+  CMock_Destroy();
+  tearDown();
+  CMock_Init();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("testdata/mocksample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+
+  CMock_Guts_MemFreeFinal();
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_head1.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,13 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+#ifndef _TESTSAMPLE_MOCK_HEAD1_H
+#define _TESTSAMPLE_MOCK_HEAD1_H
+
+#include "unity.h"
+#include "cmock.h"
+#include "funky.h"
+#include <setjmp.h>
+
+void test_TheFirstThingToTest(void);
+void test_TheSecondThingToTest(void);
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_new1.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,89 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  CMock_Init(); \
+  UNITY_CLR_DETAILS(); \
+  if (TEST_PROTECT()) \
+  { \
+    CEXCEPTION_T e; \
+    Try { \
+      setUp(); \
+      TestFunc(); \
+    } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+    CMock_Verify(); \
+  } \
+  CMock_Destroy(); \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "one.h"
+#include "two.h"
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+int GlobalExpectCount;
+int GlobalVerifyOrder;
+char* GlobalOrderError;
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+  GlobalExpectCount = 0;
+  GlobalVerifyOrder = 0;
+  GlobalOrderError = NULL;
+  Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+  Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+  Mockstanky_Destroy();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  CMock_Verify();
+  CMock_Destroy();
+  tearDown();
+  CMock_Init();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("testdata/mocksample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+
+  CMock_Guts_MemFreeFinal();
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_new2.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,89 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  CMock_Init(); \
+  UNITY_CLR_DETAILS(); \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+    CMock_Verify(); \
+  } \
+  CMock_Destroy(); \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+  Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+  Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+  Mockstanky_Destroy();
+}
+
+/*=======Suite Setup=====*/
+static int suite_setup(void)
+{
+a_custom_setup();
+}
+
+/*=======Suite Teardown=====*/
+static int suite_teardown(int num_failures)
+{
+a_custom_teardown();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  CMock_Verify();
+  CMock_Destroy();
+  tearDown();
+  CMock_Init();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  suite_setup();
+  UnityBegin("testdata/mocksample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+
+  CMock_Guts_MemFreeFinal();
+  return suite_teardown(UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_param.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,77 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST_NO_ARGS
+#define RUN_TEST(TestFunc, TestLineNum, ...) \
+{ \
+  Unity.CurrentTestName = #TestFunc "(" #__VA_ARGS__ ")"; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  CMock_Init(); \
+  UNITY_CLR_DETAILS(); \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(__VA_ARGS__); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+    CMock_Verify(); \
+  } \
+  CMock_Destroy(); \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+  Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+  Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+  Mockstanky_Destroy();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  CMock_Verify();
+  CMock_Destroy();
+  tearDown();
+  CMock_Init();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("testdata/mocksample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21, RUN_TEST_NO_ARGS);
+  RUN_TEST(test_TheSecondThingToTest, 43, RUN_TEST_NO_ARGS);
+
+  CMock_Guts_MemFreeFinal();
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_run1.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,89 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  CMock_Init(); \
+  UNITY_CLR_DETAILS(); \
+  if (TEST_PROTECT()) \
+  { \
+    CEXCEPTION_T e; \
+    Try { \
+      setUp(); \
+      TestFunc(); \
+    } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+    CMock_Verify(); \
+  } \
+  CMock_Destroy(); \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "one.h"
+#include "two.h"
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+int GlobalExpectCount;
+int GlobalVerifyOrder;
+char* GlobalOrderError;
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+  GlobalExpectCount = 0;
+  GlobalVerifyOrder = 0;
+  GlobalOrderError = NULL;
+  Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+  Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+  Mockstanky_Destroy();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  CMock_Verify();
+  CMock_Destroy();
+  tearDown();
+  CMock_Init();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("testdata/mocksample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+
+  CMock_Guts_MemFreeFinal();
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_run2.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,89 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  CMock_Init(); \
+  UNITY_CLR_DETAILS(); \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+    CMock_Verify(); \
+  } \
+  CMock_Destroy(); \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+  Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+  Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+  Mockstanky_Destroy();
+}
+
+/*=======Suite Setup=====*/
+static int suite_setup(void)
+{
+a_custom_setup();
+}
+
+/*=======Suite Teardown=====*/
+static int suite_teardown(int num_failures)
+{
+a_custom_teardown();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  CMock_Verify();
+  CMock_Destroy();
+  tearDown();
+  CMock_Init();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  suite_setup();
+  UnityBegin("testdata/mocksample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+
+  CMock_Guts_MemFreeFinal();
+  return suite_teardown(UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_mock_yaml.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,90 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  CMock_Init(); \
+  UNITY_CLR_DETAILS(); \
+  if (TEST_PROTECT()) \
+  { \
+    CEXCEPTION_T e; \
+    Try { \
+      setUp(); \
+      TestFunc(); \
+    } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+    CMock_Verify(); \
+  } \
+  CMock_Destroy(); \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include "cmock.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "two.h"
+#include "three.h"
+#include <four.h>
+#include "funky.h"
+#include <setjmp.h>
+#include "Mockstanky.h"
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+
+
+/*=======Mock Management=====*/
+static void CMock_Init(void)
+{
+  Mockstanky_Init();
+}
+static void CMock_Verify(void)
+{
+  Mockstanky_Verify();
+}
+static void CMock_Destroy(void)
+{
+  Mockstanky_Destroy();
+}
+
+/*=======Suite Setup=====*/
+static int suite_setup(void)
+{
+a_yaml_setup();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  CMock_Verify();
+  CMock_Destroy();
+  tearDown();
+  CMock_Init();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  suite_setup();
+  UnityBegin("testdata/mocksample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+
+  CMock_Guts_MemFreeFinal();
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_new1.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,67 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  if (TEST_PROTECT()) \
+  { \
+    CEXCEPTION_T e; \
+    Try { \
+      setUp(); \
+      TestFunc(); \
+    } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+  } \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "one.h"
+#include "two.h"
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+int GlobalExpectCount;
+int GlobalVerifyOrder;
+char* GlobalOrderError;
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  tearDown();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("testdata/testsample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+  RUN_TEST(test_TheThirdThingToTest, 53);
+  RUN_TEST(test_TheFourthThingToTest, 58);
+
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_new2.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,70 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+  } \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Suite Setup=====*/
+static int suite_setup(void)
+{
+a_custom_setup();
+}
+
+/*=======Suite Teardown=====*/
+static int suite_teardown(int num_failures)
+{
+a_custom_teardown();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  tearDown();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  suite_setup();
+  UnityBegin("testdata/testsample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+  RUN_TEST(test_TheThirdThingToTest, 53);
+  RUN_TEST(test_TheFourthThingToTest, 58);
+
+  return suite_teardown(UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_param.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,58 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST_NO_ARGS
+#define RUN_TEST(TestFunc, TestLineNum, ...) \
+{ \
+  Unity.CurrentTestName = #TestFunc "(" #__VA_ARGS__ ")"; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(__VA_ARGS__); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+  } \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  tearDown();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("testdata/testsample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21, RUN_TEST_NO_ARGS);
+  RUN_TEST(test_TheSecondThingToTest, 43, RUN_TEST_NO_ARGS);
+  RUN_TEST(test_TheThirdThingToTest, 53, RUN_TEST_NO_ARGS);
+  RUN_TEST(test_TheFourthThingToTest, 58, RUN_TEST_NO_ARGS);
+
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_run1.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,67 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  if (TEST_PROTECT()) \
+  { \
+    CEXCEPTION_T e; \
+    Try { \
+      setUp(); \
+      TestFunc(); \
+    } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+  } \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "one.h"
+#include "two.h"
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+int GlobalExpectCount;
+int GlobalVerifyOrder;
+char* GlobalOrderError;
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  tearDown();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  UnityBegin("testdata/testsample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+  RUN_TEST(test_TheThirdThingToTest, 53);
+  RUN_TEST(test_TheFourthThingToTest, 58);
+
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_run2.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,70 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  if (TEST_PROTECT()) \
+  { \
+      setUp(); \
+      TestFunc(); \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+  } \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Suite Setup=====*/
+static int suite_setup(void)
+{
+a_custom_setup();
+}
+
+/*=======Suite Teardown=====*/
+static int suite_teardown(int num_failures)
+{
+a_custom_teardown();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  tearDown();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  suite_setup();
+  UnityBegin("testdata/testsample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+  RUN_TEST(test_TheThirdThingToTest, 53);
+  RUN_TEST(test_TheFourthThingToTest, 58);
+
+  return suite_teardown(UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/expectdata/testsample_yaml.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,71 @@
+/* AUTOGENERATED FILE. DO NOT EDIT. */
+
+/*=======Test Runner Used To Run Each Test Below=====*/
+#define RUN_TEST(TestFunc, TestLineNum) \
+{ \
+  Unity.CurrentTestName = #TestFunc; \
+  Unity.CurrentTestLineNumber = TestLineNum; \
+  Unity.NumberOfTests++; \
+  if (TEST_PROTECT()) \
+  { \
+    CEXCEPTION_T e; \
+    Try { \
+      setUp(); \
+      TestFunc(); \
+    } Catch(e) { TEST_ASSERT_EQUAL_HEX32_MESSAGE(CEXCEPTION_NONE, e, "Unhandled Exception!"); } \
+  } \
+  if (TEST_PROTECT() && !TEST_IS_IGNORED) \
+  { \
+    tearDown(); \
+  } \
+  UnityConcludeTest(); \
+}
+
+/*=======Automagically Detected Files To Include=====*/
+#include "unity.h"
+#include <setjmp.h>
+#include <stdio.h>
+#include "CException.h"
+#include "two.h"
+#include "three.h"
+#include <four.h>
+#include "funky.h"
+#include "stanky.h"
+#include <setjmp.h>
+
+/*=======External Functions This Runner Calls=====*/
+extern void setUp(void);
+extern void tearDown(void);
+extern void test_TheFirstThingToTest(void);
+extern void test_TheSecondThingToTest(void);
+extern void test_TheThirdThingToTest(void);
+extern void test_TheFourthThingToTest(void);
+
+
+/*=======Suite Setup=====*/
+static int suite_setup(void)
+{
+a_yaml_setup();
+}
+
+/*=======Test Reset Option=====*/
+void resetTest(void);
+void resetTest(void)
+{
+  tearDown();
+  setUp();
+}
+
+
+/*=======MAIN=====*/
+int main(void)
+{
+  suite_setup();
+  UnityBegin("testdata/testsample.c");
+  RUN_TEST(test_TheFirstThingToTest, 21);
+  RUN_TEST(test_TheSecondThingToTest, 43);
+  RUN_TEST(test_TheThirdThingToTest, 53);
+  RUN_TEST(test_TheFourthThingToTest, 58);
+
+  return (UnityEnd());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/rakefile	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,60 @@
+# ==========================================
+#   Unity Project - A Test Framework for C
+#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+#   [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+UNITY_ROOT = File.expand_path(File.dirname(__FILE__)) + '/'
+
+require 'rake'
+require 'rake/clean'
+require UNITY_ROOT + 'rakefile_helper'
+
+TEMP_DIRS = [
+	File.join(UNITY_ROOT, 'build')
+]
+
+TEMP_DIRS.each do |dir|
+  directory(dir)
+  CLOBBER.include(dir)
+end
+
+task :prepare_for_tests => TEMP_DIRS
+
+include RakefileHelpers
+
+# Load proper GCC as defult configuration
+DEFAULT_CONFIG_FILE = 'gcc_auto_stdint.yml'
+configure_toolchain(DEFAULT_CONFIG_FILE)
+
+desc "Test unity with its own unit tests"
+task :unit => [:prepare_for_tests] do
+  run_tests get_unit_test_files
+end
+
+desc "Test unity's helper scripts"
+task :scripts => [:prepare_for_tests] do
+  Dir['tests/test_*.rb'].each do |scriptfile|
+    require "./"+scriptfile
+  end
+end
+
+desc "Generate test summary"
+task :summary do
+  report_summary
+end
+
+desc "Build and test Unity"
+task :all => [:clean, :prepare_for_tests, :scripts, :unit, :summary]
+task :default => [:clobber, :all]
+task :ci => [:no_color, :default]
+task :cruise => [:no_color, :default]
+
+desc "Load configuration"
+task :config, :config_file do |t, args|
+  configure_toolchain(args[:config_file])
+end
+
+task :no_color do
+  $colour_output = false
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/rakefile_helper.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,255 @@
+# ==========================================
+#   Unity Project - A Test Framework for C
+#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+#   [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+require 'yaml'
+require 'fileutils'
+require UNITY_ROOT + '../auto/unity_test_summary'
+require UNITY_ROOT + '../auto/generate_test_runner'
+require UNITY_ROOT + '../auto/colour_reporter'
+
+module RakefileHelpers
+
+  C_EXTENSION = '.c'
+
+  def load_configuration(config_file)
+    unless ($configured)
+      $cfg_file = "targets/#{config_file}" unless (config_file =~ /[\\|\/]/)
+      $cfg = YAML.load(File.read($cfg_file))
+      $colour_output = false unless $cfg['colour']
+      $configured = true if (config_file != DEFAULT_CONFIG_FILE)
+    end
+  end
+
+  def configure_clean
+    CLEAN.include($cfg['compiler']['build_path'] + '*.*') unless $cfg['compiler']['build_path'].nil?
+  end
+
+  def configure_toolchain(config_file=DEFAULT_CONFIG_FILE)
+    config_file += '.yml' unless config_file =~ /\.yml$/
+    config_file = config_file unless config_file =~ /[\\|\/]/
+    load_configuration(config_file)
+    configure_clean
+  end
+
+  def get_unit_test_files
+    path = $cfg['compiler']['unit_tests_path'] + 'test*' + C_EXTENSION
+    path.gsub!(/\\/, '/')
+    FileList.new(path)
+  end
+
+  def get_local_include_dirs
+    include_dirs = $cfg['compiler']['includes']['items'].dup
+    include_dirs.delete_if {|dir| dir.is_a?(Array)}
+    return include_dirs
+  end
+
+  def extract_headers(filename)
+    includes = []
+    lines = File.readlines(filename)
+    lines.each do |line|
+      m = line.match(/^\s*#include\s+\"\s*(.+\.[hH])\s*\"/)
+      if not m.nil?
+        includes << m[1]
+      end
+    end
+    return includes
+  end
+
+  def find_source_file(header, paths)
+    paths.each do |dir|
+      src_file = dir + header.ext(C_EXTENSION)
+      if (File.exists?(src_file))
+        return src_file
+      end
+    end
+    return nil
+  end
+
+  def tackit(strings)
+    if strings.is_a?(Array)
+      result = "\"#{strings.join}\""
+    else
+      result = strings
+    end
+    return result
+  end
+
+  def squash(prefix, items)
+    result = ''
+    items.each { |item| result += " #{prefix}#{tackit(item)}" }
+    return result
+  end
+
+  def should(behave, &block)
+    if block
+      puts "Should " + behave
+      yield block
+    else
+      puts "UNIMPLEMENTED CASE: Should #{behave}"
+    end
+  end
+
+  def build_compiler_fields
+    command  = tackit($cfg['compiler']['path'])
+    if $cfg['compiler']['defines']['items'].nil?
+      defines  = ''
+    else
+      defines  = squash($cfg['compiler']['defines']['prefix'], $cfg['compiler']['defines']['items'] + ['UNITY_OUTPUT_CHAR=putcharSpy'])
+    end
+    options  = squash('', $cfg['compiler']['options'])
+    includes = squash($cfg['compiler']['includes']['prefix'], $cfg['compiler']['includes']['items'])
+    includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
+    return {:command => command, :defines => defines, :options => options, :includes => includes}
+  end
+
+  def compile(file, defines=[])
+    compiler = build_compiler_fields
+    cmd_str  = "#{compiler[:command]}#{compiler[:defines]}#{compiler[:options]}#{compiler[:includes]} #{file} " +
+               "#{$cfg['compiler']['object_files']['prefix']}#{$cfg['compiler']['object_files']['destination']}"
+    obj_file = "#{File.basename(file, C_EXTENSION)}#{$cfg['compiler']['object_files']['extension']}"
+    execute(cmd_str + obj_file)
+    return obj_file
+  end
+
+  def build_linker_fields
+    command  = tackit($cfg['linker']['path'])
+    if $cfg['linker']['options'].nil?
+      options  = ''
+    else
+      options  = squash('', $cfg['linker']['options'])
+    end
+    if ($cfg['linker']['includes'].nil? || $cfg['linker']['includes']['items'].nil?)
+      includes = ''
+    else
+      includes = squash($cfg['linker']['includes']['prefix'], $cfg['linker']['includes']['items'])
+    end
+    includes = includes.gsub(/\\ /, ' ').gsub(/\\\"/, '"').gsub(/\\$/, '') # Remove trailing slashes (for IAR)
+    return {:command => command, :options => options, :includes => includes}
+  end
+
+  def link_it(exe_name, obj_list)
+    linker = build_linker_fields
+    cmd_str = "#{linker[:command]}#{linker[:options]}#{linker[:includes]} " +
+      (obj_list.map{|obj|"#{$cfg['linker']['object_files']['path']}#{obj} "}).join +
+      $cfg['linker']['bin_files']['prefix'] + ' ' +
+      $cfg['linker']['bin_files']['destination'] +
+      exe_name + $cfg['linker']['bin_files']['extension']
+    execute(cmd_str)
+  end
+
+  def build_simulator_fields
+    return nil if $cfg['simulator'].nil?
+    if $cfg['simulator']['path'].nil?
+      command = ''
+    else
+      command = (tackit($cfg['simulator']['path']) + ' ')
+    end
+    if $cfg['simulator']['pre_support'].nil?
+      pre_support = ''
+    else
+      pre_support = squash('', $cfg['simulator']['pre_support'])
+    end
+    if $cfg['simulator']['post_support'].nil?
+      post_support = ''
+    else
+      post_support = squash('', $cfg['simulator']['post_support'])
+    end
+    return {:command => command, :pre_support => pre_support, :post_support => post_support}
+  end
+
+  def execute(command_string, verbose=true)
+    report command_string
+    output = `#{command_string}`.chomp
+    report(output) if (verbose && !output.nil? && (output.length > 0))
+    if $?.exitstatus != 0
+      raise "Command failed. (Returned #{$?.exitstatus})"
+    end
+    return output
+  end
+
+  def report_summary
+    summary = UnityTestSummary.new
+    summary.set_root_path(UNITY_ROOT)
+    results_glob = "#{$cfg['compiler']['build_path']}*.test*"
+    results_glob.gsub!(/\\/, '/')
+    results = Dir[results_glob]
+    summary.set_targets(results)
+    report summary.run
+  end
+
+  def run_tests(test_files)
+    report 'Running Unity system tests...'
+
+    # Tack on TEST define for compiling unit tests
+    load_configuration($cfg_file)
+    test_defines = ['TEST']
+    $cfg['compiler']['defines']['items'] = [] if $cfg['compiler']['defines']['items'].nil?
+    $cfg['compiler']['defines']['items'] << 'TEST'
+
+    include_dirs = get_local_include_dirs
+
+    # Build and execute each unit test
+    test_files.each do |test|
+      obj_list = []
+
+      if !$cfg['compiler']['aux_sources'].nil?
+        $cfg['compiler']['aux_sources'].each do |aux|
+          obj_list << compile(aux, test_defines)
+        end
+      end
+
+      # Detect dependencies and build required modules
+      extract_headers(test).each do |header|
+        # Compile corresponding source file if it exists
+        src_file = find_source_file(header, include_dirs)
+        if !src_file.nil?
+          obj_list << compile(src_file, test_defines)
+        end
+      end
+
+      # Build the test runner (generate if configured to do so)
+      test_base = File.basename(test, C_EXTENSION)
+
+      runner_name = test_base + '_Runner.c'
+      runner_path = ''
+
+      if $cfg['compiler']['runner_path'].nil?
+        runner_path = $cfg['compiler']['build_path'] + runner_name
+      else
+        runner_path = $cfg['compiler']['runner_path'] + runner_name
+      end
+
+      options = $cfg[:unity]
+      options[:use_param_tests] = (test =~ /parameterized/) ? true : false
+      UnityTestRunnerGenerator.new(options).run(test, runner_path)
+      obj_list << compile(runner_path, test_defines)
+
+      # Build the test module
+      obj_list << compile(test, test_defines)
+
+      # Link the test executable
+      link_it(test_base, obj_list)
+
+      # Execute unit test and generate results file
+      simulator = build_simulator_fields
+      executable = $cfg['linker']['bin_files']['destination'] + test_base + $cfg['linker']['bin_files']['extension']
+      if simulator.nil?
+        cmd_str = executable
+      else
+        cmd_str = "#{simulator[:command]} #{simulator[:pre_support]} #{executable} #{simulator[:post_support]}"
+      end
+      output = execute(cmd_str)
+      test_results = $cfg['compiler']['build_path'] + test_base
+      if output.match(/OK$/m).nil?
+        test_results += '.testfail'
+      else
+        test_results += '.testpass'
+      end
+      File.open(test_results, 'w') { |f| f.print output }
+
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/testdata/mocksample.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,51 @@
+// This is just a sample test file to be used to test the generator script
+#ifndef TEST_SAMPLE_H
+#define TEST_SAMPLE_H
+
+#include <setjmp.h>
+#include "unity.h"
+#include "funky.h"
+#include "Mockstanky.h"
+
+void setUp(void)
+{
+  CustomSetupStuff();
+}
+
+void tearDown(void)
+{
+  CustomTeardownStuff
+}
+
+//Yup, nice comment
+void test_TheFirstThingToTest(void)
+{
+    TEST_ASSERT(1);
+
+    TEST_ASSERT_TRUE(1);
+}
+
+/*
+void test_ShouldBeIgnored(void)
+{
+    DoesStuff();
+}
+*/
+
+//void test_ShouldAlsoNotBeTested(void)
+//{
+//    Call_An_Expect();
+//    
+//    CallAFunction();
+//    test_CallAFunctionThatLooksLikeATest();
+//}
+
+void test_TheSecondThingToTest(void)
+{
+    Call_An_Expect();
+    
+    CallAFunction();
+    test_CallAFunctionThatLooksLikeATest();
+}
+
+#endif //TEST_SAMPLE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/testdata/testsample.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,68 @@
+// This is just a sample test file to be used to test the generator script
+#ifndef TEST_SAMPLE_H
+#define TEST_SAMPLE_H
+
+#include <setjmp.h>
+#include "unity.h"
+#include "funky.h"
+#include "stanky.h"
+
+void setUp(void)
+{
+  CustomSetupStuff();
+}
+
+void tearDown(void)
+{
+  CustomTeardownStuff
+}
+
+//Yup, nice comment
+void test_TheFirstThingToTest(void)
+{
+    TEST_ASSERT(1);
+
+    TEST_ASSERT_TRUE(1);
+}
+
+/*
+void test_ShouldBeIgnored(void)
+{
+    DoesStuff();
+}
+*/
+
+//void test_ShouldAlsoNotBeTested(void)
+//{
+//    Call_An_Expect();
+//
+//    CallAFunction();
+//    test_CallAFunctionThatLooksLikeATest();
+//}
+
+void test_TheSecondThingToTest(void)
+{
+    uint8_t* crazyString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n";
+
+    Call_An_Expect();
+
+    CallAFunction();
+    test_CallAFunctionThatLooksLikeATest();
+}
+
+void test_TheThirdThingToTest(void)
+{
+    CallAFunction();
+}
+
+void test_TheFourthThingToTest(void)
+{
+    uint8_t* anotherString = "GET / HTTP/1.1\r\nHost: 127.0.0.1:8081\r\nConnection: keep-alive\r\nCache-Control: no-cache\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36\r\nPostman-Token: 768c7149-c3fb-f704-71a2-63918d9195b2\r\nAccept: */*\r\nAccept-Encoding: gzip, deflate, sdch\r\nAccept-Language: en-GB,en-US;q=0.8,en;q=0.6\r\n\r\n";
+
+    Call_An_Expect();
+
+    CallAFunction();
+    test_CallAFunctionThatLooksLikeATest();
+}
+
+#endif //TEST_SAMPLE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/tests/test_generate_test_runner.rb	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,102 @@
+# ==========================================
+#   CMock Project - Automatic Mock Generation for C
+#   Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+#   [Released under MIT License. Please refer to license.txt for details]
+# ==========================================
+
+require '../auto/generate_test_runner.rb'
+
+TEST_FILE = 'testdata/testsample.c'
+TEST_MOCK = 'testdata/mocksample.c'
+OUT_FILE  = 'build/testsample_'
+EXP_FILE  = 'expectdata/testsample_'
+
+$generate_test_runner_failures = 0
+
+def verify_output_equal(subtest)
+  expected = File.read(EXP_FILE + subtest + '.c').gsub(/\r\n/,"\n")
+  actual   = File.read(OUT_FILE + subtest + '.c').gsub(/\r\n/,"\n")
+  if (expected != actual)
+    report("    #{subtest}:FAIL")
+    $generate_test_runner_failures += 1
+  else
+    report("    #{subtest}:PASS")
+  end
+end
+
+should "GenerateARunnerByCreatingRunnerWithOptions" do
+  sets = { 'def'  => nil,
+           'new1' => { :plugins => [:cexception], :includes => ['one.h', 'two.h'], :enforce_strict_ordering => true },
+           'new2' => { :plugins => [:ignore], :suite_setup => "a_custom_setup();", :suite_teardown => "a_custom_teardown();" }
+  }
+
+  sets.each_pair do |subtest, options|
+    UnityTestRunnerGenerator.new(options).run(TEST_FILE, OUT_FILE + subtest + '.c')
+    verify_output_equal(subtest)
+    UnityTestRunnerGenerator.new(options).run(TEST_MOCK, OUT_FILE + 'mock_' + subtest + '.c')
+    verify_output_equal('mock_' + subtest)
+  end
+end
+
+should "GenerateARunnerAlongWithAHeaderIfSpecified" do
+  sets = { 'head1' => { :header_file => "#{OUT_FILE}head1.h" } }
+  sets.each_pair do |subtest, options|
+    UnityTestRunnerGenerator.new(options).run(TEST_FILE, OUT_FILE + subtest + '.c')
+    verify_output_equal(subtest)
+  end
+
+  sets = { 'head1' => { :header_file => "#{OUT_FILE}mock_head1.h" } }
+  sets.each_pair do |subtest, options|
+    UnityTestRunnerGenerator.new(options).run(TEST_MOCK, OUT_FILE + 'mock_' + subtest + '.c')
+    verify_output_equal('mock_' + subtest)
+  end
+end
+
+should "GenerateARunnerByRunningRunnerWithOptions" do
+  sets = { 'run1' => { :plugins => [:cexception], :includes => ['one.h', 'two.h'], :enforce_strict_ordering => true },
+           'run2' => { :plugins => [:ignore], :suite_setup => "a_custom_setup();", :suite_teardown => "a_custom_teardown();" }
+  }
+
+  sets.each_pair do |subtest, options|
+    UnityTestRunnerGenerator.new.run(TEST_FILE, OUT_FILE + subtest + '.c', options)
+    verify_output_equal(subtest)
+    UnityTestRunnerGenerator.new.run(TEST_MOCK, OUT_FILE + 'mock_' + subtest + '.c', options)
+    verify_output_equal('mock_' + subtest)
+  end
+end
+
+should "GenerateARunnerByPullingYamlOptions" do
+  subtest = 'yaml'
+  cmdstr = "ruby ../auto/generate_test_runner.rb testdata/sample.yml \"#{TEST_FILE}\" \"#{OUT_FILE + subtest + '.c'}\""
+  `#{cmdstr}`
+  verify_output_equal(subtest)
+
+  cmdstr = "ruby ../auto/generate_test_runner.rb testdata/sample.yml \"#{TEST_MOCK}\" \"#{OUT_FILE + 'mock_' + subtest + '.c'}\""
+  `#{cmdstr}`
+  verify_output_equal('mock_' + subtest)
+end
+
+should "GenerateARunnerByPullingCommandlineOptions" do
+  subtest = 'cmd'
+  cmdstr = "ruby ../auto/generate_test_runner.rb -cexception \"#{TEST_FILE}\" \"#{OUT_FILE + subtest + '.c'}\""
+  `#{cmdstr}`
+  verify_output_equal(subtest)
+
+  cmdstr = "ruby ../auto/generate_test_runner.rb -cexception \"#{TEST_MOCK}\" \"#{OUT_FILE + 'mock_' + subtest + '.c'}\""
+  `#{cmdstr}`
+  verify_output_equal('mock_' + subtest)
+end
+
+should "GenerateARunnerThatUsesParameterizedTests" do
+  sets = { 'param'  => { :plugins => [:ignore], :use_param_tests => true }
+  }
+
+  sets.each_pair do |subtest, options|
+    UnityTestRunnerGenerator.new(options).run(TEST_FILE, OUT_FILE + subtest + '.c')
+    verify_output_equal(subtest)
+    UnityTestRunnerGenerator.new(options).run(TEST_MOCK, OUT_FILE + 'mock_' + subtest + '.c')
+    verify_output_equal('mock_' + subtest)
+  end
+end
+
+raise "There were #{$generate_test_runner_failures.to_s} failures while testing generate_test_runner.rb" if ($generate_test_runner_failures > 0)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/tests/testparameterized.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,104 @@
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#include <setjmp.h>
+#include <stdio.h>
+#include "unity.h"
+
+void putcharSpy(int c) { (void)putchar(c);} // include passthrough for linking tests
+
+#define TEST_CASE(...)
+
+#define EXPECT_ABORT_BEGIN \
+    if (TEST_PROTECT())    \
+    {
+
+#define VERIFY_FAILS_END                                                       \
+    }                                                                          \
+    Unity.CurrentTestFailed = (Unity.CurrentTestFailed == 1) ? 0 : 1;          \
+    if (Unity.CurrentTestFailed == 1) {                                        \
+      SetToOneMeanWeAlreadyCheckedThisGuy = 1;                                 \
+      UnityPrint("[[[[ Previous Test Should Have Failed But Did Not ]]]]");    \
+      UNITY_OUTPUT_CHAR('\n');                                                 \
+    }
+
+#define VERIFY_IGNORES_END                                                     \
+    }                                                                          \
+    Unity.CurrentTestFailed = (Unity.CurrentTestIgnored == 1) ? 0 : 1;         \
+    Unity.CurrentTestIgnored = 0;                                              \
+    if (Unity.CurrentTestFailed == 1) {                                        \
+      SetToOneMeanWeAlreadyCheckedThisGuy = 1;                                 \
+      UnityPrint("[[[[ Previous Test Should Have Ignored But Did Not ]]]]");   \
+      UNITY_OUTPUT_CHAR('\n');                                                 \
+    }
+
+int SetToOneToFailInTearDown;
+int SetToOneMeanWeAlreadyCheckedThisGuy;
+
+void setUp(void)
+{
+  SetToOneToFailInTearDown = 0;
+  SetToOneMeanWeAlreadyCheckedThisGuy = 0;
+}
+
+void tearDown(void)
+{
+  if (SetToOneToFailInTearDown == 1)
+    TEST_FAIL_MESSAGE("<= Failed in tearDown");
+  if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0))
+  {
+    UnityPrint("[[[[ Previous Test Should Have Passed But Did Not ]]]]");
+    UNITY_OUTPUT_CHAR('\n');
+  }
+}
+
+TEST_CASE(0)
+TEST_CASE(44)
+TEST_CASE((90)+9)
+void test_TheseShouldAllPass(int Num)
+{
+    TEST_ASSERT_TRUE(Num < 100);
+}
+
+TEST_CASE(3)
+TEST_CASE(77)
+TEST_CASE( (99) + 1 - (1))
+void test_TheseShouldAllFail(int Num)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_TRUE(Num > 100);
+    VERIFY_FAILS_END
+}
+
+TEST_CASE(1)
+TEST_CASE(44)
+TEST_CASE(99)
+TEST_CASE(98)
+void test_TheseAreEveryOther(int Num)
+{
+    if (Num & 1)
+    {
+        EXPECT_ABORT_BEGIN
+        TEST_ASSERT_TRUE(Num > 100);
+        VERIFY_FAILS_END
+    }
+    else
+    {
+        TEST_ASSERT_TRUE(Num < 100);
+    }
+}
+
+void test_NormalPassesStillWork(void)
+{
+    TEST_ASSERT_TRUE(1);
+}
+
+void test_NormalFailsStillWork(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_TRUE(0);
+    VERIFY_FAILS_END
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Test/Unity/test/tests/testunity.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,3804 @@
+/* ==========================================
+    Unity Project - A Test Framework for C
+    Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
+    [Released under MIT License. Please refer to license.txt for details]
+========================================== */
+
+#include <setjmp.h>
+#include "unity.h"
+#include <string.h>
+
+// Dividing by these constants produces +/- infinity.
+// The rationale is given in UnityAssertFloatIsInf's body.
+#ifndef UNITY_EXCLUDE_FLOAT
+static const _UF f_zero = 0.0f;
+#endif
+
+#ifndef UNITY_EXCLUDE_DOUBLE
+static const _UD d_zero = 0.0;
+#endif
+
+#define EXPECT_ABORT_BEGIN \
+    if (TEST_PROTECT())    \
+    {
+
+#define VERIFY_FAILS_END                                                       \
+    }                                                                          \
+    Unity.CurrentTestFailed = (Unity.CurrentTestFailed == 1) ? 0 : 1;          \
+    if (Unity.CurrentTestFailed == 1) {                                        \
+      SetToOneMeanWeAlreadyCheckedThisGuy = 1;                                 \
+      UnityPrintNumberUnsigned(Unity.CurrentTestLineNumber);                   \
+      UNITY_OUTPUT_CHAR(':');                                                  \
+      UnityPrint(Unity.CurrentTestName);                                       \
+      UnityPrint("[[[[ Previous Test Should Have Failed But Did Not ]]]]");    \
+      UNITY_OUTPUT_CHAR('\n');                                                 \
+    }
+
+#define VERIFY_IGNORES_END                                                     \
+    }                                                                          \
+    Unity.CurrentTestFailed = (Unity.CurrentTestIgnored == 1) ? 0 : 1;         \
+    Unity.CurrentTestIgnored = 0;                                              \
+    if (Unity.CurrentTestFailed == 1) {                                        \
+      SetToOneMeanWeAlreadyCheckedThisGuy = 1;                                 \
+      UnityPrint("[[[[ Previous Test Should Have Ignored But Did Not ]]]]");   \
+      UNITY_OUTPUT_CHAR('\n');                                                 \
+    }
+
+static int SetToOneToFailInTearDown;
+static int SetToOneMeanWeAlreadyCheckedThisGuy;
+
+void setUp(void)
+{
+  SetToOneToFailInTearDown = 0;
+  SetToOneMeanWeAlreadyCheckedThisGuy = 0;
+}
+
+void tearDown(void)
+{
+  if (SetToOneToFailInTearDown == 1)
+    TEST_FAIL_MESSAGE("<= Failed in tearDown");
+  if ((SetToOneMeanWeAlreadyCheckedThisGuy == 0) && (Unity.CurrentTestFailed > 0))
+  {
+    UnityPrint("[[[[ Previous Test Should Have Passed But Did Not ]]]]");
+    UNITY_OUTPUT_CHAR('\n');
+  }
+}
+
+void testUnitySizeInitializationReminder(void)
+{
+    /* This test ensures that sizeof(struct _Unity) doesn't change. If this
+     * test breaks, go look at the initialization of the Unity global variable
+     * in unity.c and make sure we're filling in the proper fields. */
+    const char* message = "Unexpected size for _Unity struct. Please check that "
+                     "the initialization of the Unity symbol in unity.c is "
+                     "still correct.";
+
+    /* Define a structure with all the same fields as `struct _Unity`. */
+#ifdef UNITY_EXCLUDE_DETAILS
+    struct {
+        const char* TestFile;
+        const char* CurrentTestName;
+        UNITY_LINE_TYPE CurrentTestLineNumber;
+        UNITY_COUNTER_TYPE NumberOfTests;
+        UNITY_COUNTER_TYPE TestFailures;
+        UNITY_COUNTER_TYPE TestIgnores;
+        UNITY_COUNTER_TYPE CurrentTestFailed;
+        UNITY_COUNTER_TYPE CurrentTestIgnored;
+        jmp_buf AbortFrame;
+    } _Expected_Unity;
+#else
+    struct {
+        const char* TestFile;
+        const char* CurrentTestName;
+        const char* CurrentDetails1;
+        const char* CurrentDetails2;
+        UNITY_LINE_TYPE CurrentTestLineNumber;
+        UNITY_COUNTER_TYPE NumberOfTests;
+        UNITY_COUNTER_TYPE TestFailures;
+        UNITY_COUNTER_TYPE TestIgnores;
+        UNITY_COUNTER_TYPE CurrentTestFailed;
+        UNITY_COUNTER_TYPE CurrentTestIgnored;
+        jmp_buf AbortFrame;
+    } _Expected_Unity;
+#endif
+
+    /* Compare our fake structure's size to the actual structure's size. They
+     * should be the same.
+     *
+     * This accounts for alignment, padding, and packing issues that might come
+     * up between different architectures. */
+    TEST_ASSERT_EQUAL_MESSAGE(sizeof(_Expected_Unity), sizeof(Unity), message);
+}
+
+void testPassShouldEndImmediatelyWithPass(void)
+{
+    TEST_PASS();
+    TEST_FAIL_MESSAGE("We should have passed already and finished this test");
+}
+
+void testTrue(void)
+{
+    TEST_ASSERT(1);
+
+    TEST_ASSERT_TRUE(1);
+}
+
+void testFalse(void)
+{
+    TEST_ASSERT_FALSE(0);
+
+    TEST_ASSERT_UNLESS(0);
+}
+
+void testPreviousPass(void)
+{
+    TEST_ASSERT_EQUAL_INT(0U, Unity.TestFailures);
+}
+
+void testNotVanilla(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT(0);
+    VERIFY_FAILS_END
+}
+
+void testNotTrue(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_TRUE(0);
+    VERIFY_FAILS_END
+}
+
+void testNotFalse(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_FALSE(1);
+    VERIFY_FAILS_END
+}
+
+void testNotUnless(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UNLESS(1);
+    VERIFY_FAILS_END
+}
+
+void testNotNotEqual(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_NOT_EQUAL(10, 10);
+    VERIFY_FAILS_END
+}
+
+void testFail(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_FAIL_MESSAGE("Expected for testing");
+    VERIFY_FAILS_END
+}
+
+void testIsNull(void)
+{
+    char* ptr1 = NULL;
+    const char* ptr2 = "hello";
+
+    TEST_ASSERT_NULL(ptr1);
+    TEST_ASSERT_NOT_NULL(ptr2);
+}
+
+void testIsNullShouldFailIfNot(void)
+{
+    const char* ptr1 = "hello";
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_NULL(ptr1);
+    VERIFY_FAILS_END
+}
+
+void testNotNullShouldFailIfNULL(void)
+{
+    char* ptr1 = NULL;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_NOT_NULL(ptr1);
+    VERIFY_FAILS_END
+}
+
+void testIgnore(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_IGNORE();
+    TEST_FAIL_MESSAGE("This should not be reached");
+    VERIFY_IGNORES_END
+}
+
+void testIgnoreMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_IGNORE_MESSAGE("This is an expected TEST_IGNORE_MESSAGE string!");
+    TEST_FAIL_MESSAGE("This should not be reached");
+    VERIFY_IGNORES_END
+}
+
+void testNotEqualInts(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT(3982, 3983);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualInt8s(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT8(-127, -126);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualInt16s(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT16(-16383, -16382);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualInt32s(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT32(-2147483647, -2147483648); //use largest 32 bit negative to test printability
+    VERIFY_FAILS_END
+}
+
+void testNotEqualBits(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_BITS(0xFF00, 0x5555, 0x5A55);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualUInts(void)
+{
+    _UU16 v0, v1;
+
+    v0 = 9000;
+    v1 = 9001;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT(v0, v1);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualUInt8s(void)
+{
+    _UU8 v0, v1;
+
+    v0 = 254;
+    v1 = 255;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT8(v0, v1);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualUInt16s(void)
+{
+    _UU16 v0, v1;
+
+    v0 = 65535;
+    v1 = 65534;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT16(v0, v1);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualUInt32s(void)
+{
+    _UU32 v0, v1;
+
+    v0 = 4294967295;
+    v1 = 4294967294;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT32(v0, v1);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHex8s(void)
+{
+    _UU8 v0, v1;
+
+    v0 = 0x23;
+    v1 = 0x22;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX8(v0, v1);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHex8sIfSigned(void)
+{
+    _US8 v0, v1;
+
+    v0 = -2;
+    v1 = 2;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX8(v0, v1);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHex16s(void)
+{
+    _UU16 v0, v1;
+
+    v0 = 0x1234;
+    v1 = 0x1235;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX16(v0, v1);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHex16sIfSigned(void)
+{
+    _US16 v0, v1;
+
+    v0 = -1024;
+    v1 = -1028;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX16(v0, v1);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHex32s(void)
+{
+    _UU32 v0, v1;
+
+    v0 = 900000;
+    v1 = 900001;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX32(v0, v1);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHex32sIfSigned(void)
+{
+    _US32 v0, v1;
+
+    v0 = -900000;
+    v1 = 900001;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX32(v0, v1);
+    VERIFY_FAILS_END
+}
+
+void testEqualInts(void)
+{
+    int v0, v1;
+    int *p0, *p1;
+
+    v0 = 19467;
+    v1 = 19467;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_INT(1837, 1837);
+    TEST_ASSERT_EQUAL_INT(-27365, -27365);
+    TEST_ASSERT_EQUAL_INT(v0, v1);
+    TEST_ASSERT_EQUAL_INT(19467, v1);
+    TEST_ASSERT_EQUAL_INT(v0, 19467);
+    TEST_ASSERT_EQUAL_INT(*p0, v1);
+    TEST_ASSERT_EQUAL_INT(*p0, *p1);
+    TEST_ASSERT_EQUAL_INT(*p0, 19467);
+}
+
+void testEqualInt8s(void)
+{
+    _US8 v0, v1;
+    _US8 *p0, *p1;
+
+    v0 = 0x22;
+    v1 = 0x22;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_INT8(0x22, 0x22);
+    TEST_ASSERT_EQUAL_INT8(v0, v1);
+    TEST_ASSERT_EQUAL_INT8(0x22, v1);
+    TEST_ASSERT_EQUAL_INT8(v0, 0x22);
+    TEST_ASSERT_EQUAL_INT8(*p0, v1);
+    TEST_ASSERT_EQUAL_INT8(*p0, *p1);
+    TEST_ASSERT_EQUAL_INT8(*p0, 0x22);
+}
+
+void testEqualInt8sWhenThereAreDifferencesOutside8Bits(void)
+{
+    TEST_ASSERT_EQUAL_INT8(0x321,0x421);
+    TEST_ASSERT_EQUAL_INT8(0xFF21,0x0021);
+}
+
+void testEqualInt16s(void)
+{
+    _US16 v0, v1;
+    _US16 *p0, *p1;
+
+    v0 = 0x7876;
+    v1 = 0x7876;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_INT16(0x7876, 0x7876);
+    TEST_ASSERT_EQUAL_INT16(v0, v1);
+    TEST_ASSERT_EQUAL_INT16(0x7876, v1);
+    TEST_ASSERT_EQUAL_INT16(v0, 0x7876);
+    TEST_ASSERT_EQUAL_INT16(*p0, v1);
+    TEST_ASSERT_EQUAL_INT16(*p0, *p1);
+    TEST_ASSERT_EQUAL_INT16(*p0, 0x7876);
+}
+
+void testEqualInt16sNegatives(void)
+{
+    _US16 v0, v1;
+    _US16 *p0, *p1;
+
+    v0 = -7876;
+    v1 = -7876;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_INT16(-7876, -7876);
+    TEST_ASSERT_EQUAL_INT16(v0, v1);
+    TEST_ASSERT_EQUAL_INT16(-7876, v1);
+    TEST_ASSERT_EQUAL_INT16(v0, -7876);
+    TEST_ASSERT_EQUAL_INT16(*p0, v1);
+    TEST_ASSERT_EQUAL_INT16(*p0, *p1);
+    TEST_ASSERT_EQUAL_INT16(*p0, -7876);
+}
+
+void testEqualInt16sWhenThereAreDifferencesOutside16Bits(void)
+{
+    TEST_ASSERT_EQUAL_INT16(0x54321,0x64321);
+    TEST_ASSERT_EQUAL_INT16(0xFFFF4321,0x00004321);
+}
+
+void testEqualInt32s(void)
+{
+    _US32 v0, v1;
+    _US32 *p0, *p1;
+
+    v0 = 0x78760000;
+    v1 = 0x78760000;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_INT32(0x78760000, 0x78760000);
+    TEST_ASSERT_EQUAL_INT32(v0, v1);
+    TEST_ASSERT_EQUAL_INT32(0x78760000, v1);
+    TEST_ASSERT_EQUAL_INT32(v0, 0x78760000);
+    TEST_ASSERT_EQUAL_INT32(*p0, v1);
+    TEST_ASSERT_EQUAL_INT32(*p0, *p1);
+    TEST_ASSERT_EQUAL_INT32(*p0, 0x78760000);
+}
+
+void testEqualInt32sNegatives(void)
+{
+    _US32 v0, v1;
+    _US32 *p0, *p1;
+
+    v0 = -123456789;
+    v1 = -123456789;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_INT32(-123456789, -123456789);
+    TEST_ASSERT_EQUAL_INT32(v0, v1);
+    TEST_ASSERT_EQUAL_INT32(-123456789, v1);
+    TEST_ASSERT_EQUAL_INT32(v0, -123456789);
+    TEST_ASSERT_EQUAL_INT32(*p0, v1);
+    TEST_ASSERT_EQUAL_INT32(*p0, *p1);
+    TEST_ASSERT_EQUAL_INT32(*p0, -123456789);
+}
+
+
+void testEqualUints(void)
+{
+    unsigned int v0, v1;
+    unsigned int *p0, *p1;
+
+    v0 = 19467;
+    v1 = 19467;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_UINT(1837, 1837);
+    TEST_ASSERT_EQUAL_UINT(v0, v1);
+    TEST_ASSERT_EQUAL_UINT(19467, v1);
+    TEST_ASSERT_EQUAL_UINT(v0, 19467);
+    TEST_ASSERT_EQUAL_UINT(*p0, v1);
+    TEST_ASSERT_EQUAL_UINT(*p0, *p1);
+    TEST_ASSERT_EQUAL_UINT(*p0, 19467);
+    TEST_ASSERT_EQUAL_UINT(60872u, 60872u);
+}
+
+
+void testEqualUint8s(void)
+{
+    _UU8 v0, v1;
+    _UU8 *p0, *p1;
+
+    v0 = 0x22;
+    v1 = 0x22;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_UINT8(0x22, 0x22);
+    TEST_ASSERT_EQUAL_UINT8(v0, v1);
+    TEST_ASSERT_EQUAL_UINT8(0x22, v1);
+    TEST_ASSERT_EQUAL_UINT8(v0, 0x22);
+    TEST_ASSERT_EQUAL_UINT8(*p0, v1);
+    TEST_ASSERT_EQUAL_UINT8(*p0, *p1);
+    TEST_ASSERT_EQUAL_UINT8(*p0, 0x22);
+}
+
+void testEqualUint8sWhenThereAreDifferencesOutside8Bits(void)
+{
+    TEST_ASSERT_EQUAL_UINT8(0x321,0x421);
+    TEST_ASSERT_EQUAL_UINT8(0xFF21,0x0021);
+}
+
+void testEqualUint16s(void)
+{
+    _UU16 v0, v1;
+    _UU16 *p0, *p1;
+
+    v0 = 0x9876;
+    v1 = 0x9876;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_UINT16(0x9876, 0x9876);
+    TEST_ASSERT_EQUAL_UINT16(v0, v1);
+    TEST_ASSERT_EQUAL_UINT16(0x9876, v1);
+    TEST_ASSERT_EQUAL_UINT16(v0, 0x9876);
+    TEST_ASSERT_EQUAL_UINT16(*p0, v1);
+    TEST_ASSERT_EQUAL_UINT16(*p0, *p1);
+    TEST_ASSERT_EQUAL_UINT16(*p0, 0x9876);
+}
+
+void testEqualUint16sWhenThereAreDifferencesOutside16Bits(void)
+{
+    TEST_ASSERT_EQUAL_UINT16(0x54321,0x64321);
+    TEST_ASSERT_EQUAL_UINT16(0xFFFF4321,0x00004321);
+}
+
+void testEqualUint32s(void)
+{
+    _UU32 v0, v1;
+    _UU32 *p0, *p1;
+
+    v0 = 0x98760000;
+    v1 = 0x98760000;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_UINT32(0x98760000, 0x98760000);
+    TEST_ASSERT_EQUAL_UINT32(v0, v1);
+    TEST_ASSERT_EQUAL_UINT32(0x98760000, v1);
+    TEST_ASSERT_EQUAL_UINT32(v0, 0x98760000);
+    TEST_ASSERT_EQUAL_UINT32(*p0, v1);
+    TEST_ASSERT_EQUAL_UINT32(*p0, *p1);
+    TEST_ASSERT_EQUAL_UINT32(*p0, 0x98760000);
+}
+
+void testNotEqual(void)
+{
+    TEST_ASSERT_NOT_EQUAL(0, 1);
+    TEST_ASSERT_NOT_EQUAL(1, 0);
+    TEST_ASSERT_NOT_EQUAL(100, 101);
+    TEST_ASSERT_NOT_EQUAL(0, -1);
+    TEST_ASSERT_NOT_EQUAL(65535, -65535);
+    TEST_ASSERT_NOT_EQUAL(75, 900);
+    TEST_ASSERT_NOT_EQUAL(-100, -101);
+}
+
+void testEqualHex8s(void)
+{
+    _UU8 v0, v1;
+    _UU8 *p0, *p1;
+
+    v0 = 0x22;
+    v1 = 0x22;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_HEX8(0x22, 0x22);
+    TEST_ASSERT_EQUAL_HEX8(v0, v1);
+    TEST_ASSERT_EQUAL_HEX8(0x22, v1);
+    TEST_ASSERT_EQUAL_HEX8(v0, 0x22);
+    TEST_ASSERT_EQUAL_HEX8(*p0, v1);
+    TEST_ASSERT_EQUAL_HEX8(*p0, *p1);
+    TEST_ASSERT_EQUAL_HEX8(*p0, 0x22);
+}
+
+void testEqualHex8sWhenThereAreDifferencesOutside8Bits(void)
+{
+    TEST_ASSERT_EQUAL_HEX8(0x321,0x421);
+    TEST_ASSERT_EQUAL_HEX8(0xFF21,0x0021);
+}
+
+void testEqualHex8sNegatives(void)
+{
+    _UU8 v0, v1;
+    _UU8 *p0, *p1;
+
+    v0 = 0xDD;
+    v1 = 0xDD;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_HEX8(0xDD, 0xDD);
+    TEST_ASSERT_EQUAL_HEX8(v0, v1);
+    TEST_ASSERT_EQUAL_HEX8(0xDD, v1);
+    TEST_ASSERT_EQUAL_HEX8(v0, 0xDD);
+    TEST_ASSERT_EQUAL_HEX8(*p0, v1);
+    TEST_ASSERT_EQUAL_HEX8(*p0, *p1);
+    TEST_ASSERT_EQUAL_HEX8(*p0, 0xDD);
+}
+
+void testEqualHex16s(void)
+{
+    _UU16 v0, v1;
+    _UU16 *p0, *p1;
+
+    v0 = 0x9876;
+    v1 = 0x9876;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_HEX16(0x9876, 0x9876);
+    TEST_ASSERT_EQUAL_HEX16(v0, v1);
+    TEST_ASSERT_EQUAL_HEX16(0x9876, v1);
+    TEST_ASSERT_EQUAL_HEX16(v0, 0x9876);
+    TEST_ASSERT_EQUAL_HEX16(*p0, v1);
+    TEST_ASSERT_EQUAL_HEX16(*p0, *p1);
+    TEST_ASSERT_EQUAL_HEX16(*p0, 0x9876);
+}
+
+void testEqualHex16sWhenThereAreDifferencesOutside16Bits(void)
+{
+    TEST_ASSERT_EQUAL_HEX16(0x54321,0x64321);
+    TEST_ASSERT_EQUAL_HEX16(0xFFFF4321,0x00004321);
+}
+
+void testEqualHex32s(void)
+{
+    _UU32 v0, v1;
+    _UU32 *p0, *p1;
+
+    v0 = 0x98765432ul;
+    v1 = 0x98765432ul;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_HEX32(0x98765432ul, 0x98765432ul);
+    TEST_ASSERT_EQUAL_HEX32(v0, v1);
+    TEST_ASSERT_EQUAL_HEX32(0x98765432ul, v1);
+    TEST_ASSERT_EQUAL_HEX32(v0, 0x98765432ul);
+    TEST_ASSERT_EQUAL_HEX32(*p0, v1);
+    TEST_ASSERT_EQUAL_HEX32(*p0, *p1);
+    TEST_ASSERT_EQUAL_HEX32(*p0, 0x98765432ul);
+}
+
+void testEqualBits(void)
+{
+    _UU32 v0 = 0xFF55AA00;
+    _UU32 v1 = 0x55550000;
+
+    TEST_ASSERT_BITS(v1, v0, 0x55550000);
+    TEST_ASSERT_BITS(v1, v0, 0xFF55CC00);
+    TEST_ASSERT_BITS(0xFFFFFFFF, v0, 0xFF55AA00);
+    TEST_ASSERT_BITS(0xFFFFFFFF, v0, v0);
+    TEST_ASSERT_BITS(0xF0F0F0F0, v0, 0xFC5DAE0F);
+    TEST_ASSERT_BITS_HIGH(v1, v0);
+    TEST_ASSERT_BITS_LOW(0x000055FF, v0);
+    TEST_ASSERT_BIT_HIGH(30, v0);
+    TEST_ASSERT_BIT_LOW(5, v0);
+}
+
+void testNotEqualBitHigh(void)
+{
+    _UU32 v0 = 0x7F55AA00;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_BIT_HIGH(31, v0);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualBitLow(void)
+{
+    _UU32 v0 = 0xFF55AA00;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_BIT_LOW(30, v0);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualBitsHigh(void)
+{
+    _UU32 v0 = 0xFF55AA00;
+    _UU32 v1 = 0x55550000;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_BITS_HIGH(v0, v1);
+    VERIFY_FAILS_END
+
+}
+
+void testNotEqualBitsLow(void)
+{
+    _UU32 v0 = 0xFF55AA00;
+    _UU32 v1 = 0x55550000;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_BITS_LOW(v0, v1);
+    VERIFY_FAILS_END
+
+}
+void testEqualShorts(void)
+{
+    short v0, v1;
+    short *p0, *p1;
+
+    v0 = 19467;
+    v1 = 19467;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_INT(1837, 1837);
+    TEST_ASSERT_EQUAL_INT(-2987, -2987);
+    TEST_ASSERT_EQUAL_INT(v0, v1);
+    TEST_ASSERT_EQUAL_INT(19467, v1);
+    TEST_ASSERT_EQUAL_INT(v0, 19467);
+    TEST_ASSERT_EQUAL_INT(*p0, v1);
+    TEST_ASSERT_EQUAL_INT(*p0, *p1);
+    TEST_ASSERT_EQUAL_INT(*p0, 19467);
+}
+
+void testEqualUShorts(void)
+{
+    unsigned short v0, v1;
+    unsigned short *p0, *p1;
+
+    v0 = 19467;
+    v1 = 19467;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_UINT(1837, 1837);
+    TEST_ASSERT_EQUAL_UINT(2987, 2987);
+    TEST_ASSERT_EQUAL_UINT(v0, v1);
+    TEST_ASSERT_EQUAL_UINT(19467, v1);
+    TEST_ASSERT_EQUAL_UINT(v0, 19467);
+    TEST_ASSERT_EQUAL_UINT(*p0, v1);
+    TEST_ASSERT_EQUAL_UINT(*p0, *p1);
+    TEST_ASSERT_EQUAL_UINT(*p0, 19467);
+}
+
+void testEqualChars(void)
+{
+    signed char v0, v1;
+    signed char *p0, *p1;
+
+    v0 = 109;
+    v1 = 109;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_INT(42, 42);
+    TEST_ASSERT_EQUAL_INT(-116, -116);
+    TEST_ASSERT_EQUAL_INT(v0, v1);
+    TEST_ASSERT_EQUAL_INT(109, v1);
+    TEST_ASSERT_EQUAL_INT(v0, 109);
+    TEST_ASSERT_EQUAL_INT(*p0, v1);
+    TEST_ASSERT_EQUAL_INT(*p0, *p1);
+    TEST_ASSERT_EQUAL_INT(*p0, 109);
+}
+
+void testEqualUChars(void)
+{
+    unsigned char v0, v1;
+    unsigned char *p0, *p1;
+
+    v0 = 251;
+    v1 = 251;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_INT(42, 42);
+    TEST_ASSERT_EQUAL_INT(v0, v1);
+    TEST_ASSERT_EQUAL_INT(251, v1);
+    TEST_ASSERT_EQUAL_INT(v0, 251);
+    TEST_ASSERT_EQUAL_INT(*p0, v1);
+    TEST_ASSERT_EQUAL_INT(*p0, *p1);
+    TEST_ASSERT_EQUAL_INT(*p0, 251);
+}
+
+void testEqualPointers(void)
+{
+    int v0, v1;
+    int *p0, *p1, *p2;
+
+    v0 = 19467;
+    v1 = 18271;
+    p0 = &v0;
+    p1 = &v1;
+    p2 = &v1;
+
+    TEST_ASSERT_EQUAL_PTR(p0, &v0);
+    TEST_ASSERT_EQUAL_PTR(&v1, p1);
+    TEST_ASSERT_EQUAL_PTR(p2, p1);
+    TEST_ASSERT_EQUAL_PTR(&v0, &v0);
+}
+
+void testNotEqualPointers(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_PTR(0x12345678, 0x12345677);
+    VERIFY_FAILS_END
+}
+
+void testIntsWithinDelta(void)
+{
+    TEST_ASSERT_INT_WITHIN(1, 5000, 5001);
+    TEST_ASSERT_INT_WITHIN(5, 5000, 4996);
+    TEST_ASSERT_INT_WITHIN(5, 5000, 5005);
+    TEST_ASSERT_INT_WITHIN(500, 50, -440);
+
+    TEST_ASSERT_INT_WITHIN(2, -1, -1);
+    TEST_ASSERT_INT_WITHIN(5, 1, -1);
+    TEST_ASSERT_INT_WITHIN(5, -1, 1);
+}
+
+void testIntsWithinDeltaAndCustomMessage(void)
+{
+    TEST_ASSERT_INT_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+    TEST_ASSERT_INT_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message.");
+    TEST_ASSERT_INT_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message.");
+    TEST_ASSERT_INT_WITHIN_MESSAGE(500, 50, -440, "Custom Message.");
+
+    TEST_ASSERT_INT_WITHIN_MESSAGE(2, -1, -1, "Custom Message.");
+    TEST_ASSERT_INT_WITHIN_MESSAGE(5, 1, -1, "Custom Message.");
+    TEST_ASSERT_INT_WITHIN_MESSAGE(5, -1, 1, "Custom Message.");
+}
+
+void testIntsNotWithinDelta(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_INT_WITHIN(5, 5000, 5006);
+    VERIFY_FAILS_END
+}
+
+void testIntsNotWithinDeltaAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_INT_WITHIN_MESSAGE(5, 5000, 5006, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testUIntsWithinDelta(void)
+{
+    TEST_ASSERT_UINT_WITHIN(1, 5000, 5001);
+    TEST_ASSERT_UINT_WITHIN(5, 5000, 4996);
+    TEST_ASSERT_UINT_WITHIN(5, 5000, 5005);
+}
+
+void testUIntsWithinDeltaAndCustomMessage(void)
+{
+    TEST_ASSERT_UINT_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+    TEST_ASSERT_UINT_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message.");
+    TEST_ASSERT_UINT_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message.");
+}
+
+void testUIntsNotWithinDelta(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT_WITHIN(1, 2147483647u, 2147483649u);
+    VERIFY_FAILS_END
+}
+
+void testUIntsNotWithinDeltaAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT_WITHIN_MESSAGE(1, 2147483647u, 2147483649u, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassSmallFirst(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT_WITHIN(5, 1, -1);
+    VERIFY_FAILS_END
+}
+
+void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassSmallFirstAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT_WITHIN_MESSAGE(5, 1, -1, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassBigFirst(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT_WITHIN(5, -1, 1);
+    VERIFY_FAILS_END
+}
+
+void testUIntsNotWithinDeltaEvenThoughASignedIntWouldPassBigFirstAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT_WITHIN_MESSAGE(5, -1, 1, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testHEX32sWithinDelta(void)
+{
+    TEST_ASSERT_HEX32_WITHIN(1, 5000, 5001);
+    TEST_ASSERT_HEX32_WITHIN(5, 5000, 4996);
+    TEST_ASSERT_HEX32_WITHIN(5, 5000, 5005);
+}
+
+void testHEX32sWithinDeltaAndCustomMessage(void)
+{
+    TEST_ASSERT_HEX32_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+    TEST_ASSERT_HEX32_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message.");
+    TEST_ASSERT_HEX32_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message.");
+}
+
+void testHEX32sNotWithinDelta(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_HEX32_WITHIN(1, 2147483647u, 2147483649u);
+    VERIFY_FAILS_END
+}
+
+void testHEX32sNotWithinDeltaAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_HEX32_WITHIN_MESSAGE(1, 2147483647u, 2147483649u, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testHEX32sNotWithinDeltaEvenThoughASignedIntWouldPass(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_HEX32_WITHIN(5, 1, -1);
+    VERIFY_FAILS_END
+}
+
+void testHEX32sNotWithinDeltaEvenThoughASignedIntWouldPassAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_HEX32_WITHIN_MESSAGE(5, 1, -1, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testHEX16sWithinDelta(void)
+{
+    TEST_ASSERT_HEX16_WITHIN(1, 5000, 5001);
+    TEST_ASSERT_HEX16_WITHIN(5, 5000, 4996);
+    TEST_ASSERT_HEX16_WITHIN(5, 5000, 5005);
+}
+
+void testHEX16sWithinDeltaAndCustomMessage(void)
+{
+    TEST_ASSERT_HEX16_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+    TEST_ASSERT_HEX16_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message.");
+    TEST_ASSERT_HEX16_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message.");
+}
+
+void testHEX16sWithinDeltaWhenThereAreDifferenceOutsideOf16Bits(void)
+{
+    TEST_ASSERT_HEX16_WITHIN(5, 0x54321, 0x44321);
+}
+
+void testHEX16sWithinDeltaWhenThereAreDifferenceOutsideOf16BitsAndCustomMessage(void)
+{
+    TEST_ASSERT_HEX16_WITHIN_MESSAGE(5, 0x54321, 0x44321, "Custom Message.");
+}
+
+void testHEX16sNotWithinDelta(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_HEX16_WITHIN(2, 65535, 0);
+    VERIFY_FAILS_END
+}
+
+void testHEX16sNotWithinDeltaAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_HEX16_WITHIN_MESSAGE(2, 65535, 0, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testHEX8sWithinDelta(void)
+{
+    TEST_ASSERT_HEX8_WITHIN(1, 254, 255);
+    TEST_ASSERT_HEX8_WITHIN(5, 251, 255);
+    TEST_ASSERT_HEX8_WITHIN(5, 1, 4);
+}
+
+void testHEX8sWithinDeltaAndCustomMessage(void)
+{
+    TEST_ASSERT_HEX8_WITHIN_MESSAGE(1, 254, 255, "Custom Message.");
+    TEST_ASSERT_HEX8_WITHIN_MESSAGE(5, 251, 255, "Custom Message.");
+    TEST_ASSERT_HEX8_WITHIN_MESSAGE(5, 1, 4, "Custom Message.");
+}
+
+void testHEX8sWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void)
+{
+    TEST_ASSERT_HEX8_WITHIN(5, 0x123, 0xF23);
+}
+
+void testHEX8sWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void)
+{
+    TEST_ASSERT_HEX8_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message.");
+}
+
+void testHEX8sNotWithinDelta(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_HEX8_WITHIN(2, 255, 0);
+    VERIFY_FAILS_END
+}
+
+void testHEX8sNotWithinDeltaAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_HEX8_WITHIN_MESSAGE(2, 255, 0, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+//-----------------
+
+void testUINT32sWithinDelta(void)
+{
+    TEST_ASSERT_UINT32_WITHIN(1, 5000, 5001);
+    TEST_ASSERT_UINT32_WITHIN(5, 5000, 4996);
+    TEST_ASSERT_UINT32_WITHIN(5, 5000, 5005);
+}
+
+void testUINT32sWithinDeltaAndCustomMessage(void)
+{
+    TEST_ASSERT_UINT32_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+    TEST_ASSERT_UINT32_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message.");
+    TEST_ASSERT_UINT32_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message.");
+}
+
+void testUINT32sNotWithinDelta(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT32_WITHIN(1, 2147483647u, 2147483649u);
+    VERIFY_FAILS_END
+}
+
+void testUINT32sNotWithinDeltaAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT32_WITHIN_MESSAGE(1, 2147483647u, 2147483649u, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testUINT32sNotWithinDeltaEvenThoughASignedIntWouldPass(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT32_WITHIN(5, 1, -1);
+    VERIFY_FAILS_END
+}
+
+void testUINT32sNotWithinDeltaEvenThoughASignedIntWouldPassAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT32_WITHIN_MESSAGE(5, 1, -1, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testUINT16sWithinDelta(void)
+{
+    TEST_ASSERT_UINT16_WITHIN(1, 5000, 5001);
+    TEST_ASSERT_UINT16_WITHIN(5, 5000, 4996);
+    TEST_ASSERT_UINT16_WITHIN(5, 5000, 5005);
+}
+
+void testUINT16sWithinDeltaAndCustomMessage(void)
+{
+    TEST_ASSERT_UINT16_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+    TEST_ASSERT_UINT16_WITHIN_MESSAGE(5, 5000, 4996, "Custom Message.");
+    TEST_ASSERT_UINT16_WITHIN_MESSAGE(5, 5000, 5005, "Custom Message.");
+}
+
+void testUINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16Bits(void)
+{
+    TEST_ASSERT_UINT16_WITHIN(5, 0x54321, 0x44321);
+}
+
+void testUINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16BitsAndCustomMessage(void)
+{
+    TEST_ASSERT_UINT16_WITHIN_MESSAGE(5, 0x54321, 0x44321, "Custom Message.");
+}
+
+void testUINT16sNotWithinDelta(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT16_WITHIN(2, 65535, 0);
+    VERIFY_FAILS_END
+}
+
+void testUINT16sNotWithinDeltaAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT16_WITHIN_MESSAGE(2, 65535, 0, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testUINT8sWithinDelta(void)
+{
+    TEST_ASSERT_UINT8_WITHIN(1, 254, 255);
+    TEST_ASSERT_UINT8_WITHIN(5, 251, 255);
+    TEST_ASSERT_UINT8_WITHIN(5, 1, 4);
+}
+
+void testUINT8sWithinDeltaAndCustomMessage(void)
+{
+    TEST_ASSERT_UINT8_WITHIN_MESSAGE(1, 254, 255, "Custom Message.");
+    TEST_ASSERT_UINT8_WITHIN_MESSAGE(5, 251, 255, "Custom Message.");
+    TEST_ASSERT_UINT8_WITHIN_MESSAGE(5, 1, 4, "Custom Message.");
+}
+
+void testUINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void)
+{
+    TEST_ASSERT_UINT8_WITHIN(5, 0x123, 0xF23);
+}
+
+void testUINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void)
+{
+    TEST_ASSERT_UINT8_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message.");
+}
+
+void testUINT8sNotWithinDelta(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT8_WITHIN(2, 255, 0);
+    VERIFY_FAILS_END
+}
+
+void testUINT8sNotWithinDeltaAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT8_WITHIN_MESSAGE(2, 255, 0, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testINT32sWithinDelta(void)
+{
+    TEST_ASSERT_INT32_WITHIN(1, 5000, 5001);
+    TEST_ASSERT_INT32_WITHIN(5, 1, -2);
+    TEST_ASSERT_INT32_WITHIN(5, -2, 1);
+}
+
+void testINT32sWithinDeltaAndCustomMessage(void)
+{
+    TEST_ASSERT_INT32_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+}
+
+void testINT32sNotWithinDelta(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_INT32_WITHIN(1, -3, 1);
+    VERIFY_FAILS_END
+}
+
+void testINT32sNotWithinDeltaAndDifferenceOverflows(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_INT32_WITHIN(1, -1, 0x7FFFFFFF);
+    VERIFY_FAILS_END
+}
+void testINT32sNotWithinDeltaAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_INT32_WITHIN_MESSAGE(1, -2, 1, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testINT16sWithinDelta(void)
+{
+    TEST_ASSERT_INT16_WITHIN(1, 5000, 5001);
+    TEST_ASSERT_INT16_WITHIN(5, 2, -2);
+    TEST_ASSERT_INT16_WITHIN(5, -2, 2);
+}
+
+void testINT16sWithinDeltaAndCustomMessage(void)
+{
+    TEST_ASSERT_INT16_WITHIN_MESSAGE(1, 5000, 5001, "Custom Message.");
+}
+
+void testINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16Bits(void)
+{
+    TEST_ASSERT_INT16_WITHIN(5, 0x54321, 0x44321);
+}
+
+void testINT16sWithinDeltaWhenThereAreDifferenceOutsideOf16BitsAndCustomMessage(void)
+{
+    TEST_ASSERT_INT16_WITHIN_MESSAGE(5, 0x54321, 0x44321, "Custom Message.");
+}
+
+void testINT16sNotWithinDelta(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_INT16_WITHIN(2, 4, -2);
+    VERIFY_FAILS_END
+}
+
+void testINT16sNotWithinDeltaAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_INT16_WITHIN_MESSAGE(2, 3, 0, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testINT8sWithinDelta(void)
+{
+    TEST_ASSERT_INT8_WITHIN(1, 127, 126);
+    TEST_ASSERT_INT8_WITHIN(5, -2, 2);
+    TEST_ASSERT_INT8_WITHIN(5, 2, -2);
+}
+
+void testINT8sWithinDeltaAndCustomMessage(void)
+{
+    TEST_ASSERT_INT8_WITHIN_MESSAGE(5, 1, 4, "Custom Message.");
+}
+
+void testINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8Bits(void)
+{
+    TEST_ASSERT_INT8_WITHIN(5, 0x123, 0xF23);
+}
+
+void testINT8sWithinDeltaWhenThereAreDifferenceOutsideOf8BitsAndCustomMessage(void)
+{
+    TEST_ASSERT_INT8_WITHIN_MESSAGE(5, 0x123, 0xF23, "Custom Message.");
+}
+
+void testINT8sNotWithinDelta(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_INT8_WITHIN(2, -3, 0);
+    VERIFY_FAILS_END
+}
+
+void testINT8sNotWithinDeltaAndCustomMessage(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_INT8_WITHIN_MESSAGE(2, -4, 0, "Custom Message.");
+    VERIFY_FAILS_END
+}
+
+void testEqualStrings(void)
+{
+    const char *testString = "foo";
+
+    TEST_ASSERT_EQUAL_STRING(testString, testString);
+    TEST_ASSERT_EQUAL_STRING_MESSAGE("foo", "foo", "foo isn't foo");
+    TEST_ASSERT_EQUAL_STRING("foo", testString);
+    TEST_ASSERT_EQUAL_STRING(testString, "foo");
+    TEST_ASSERT_EQUAL_STRING("", "");
+}
+
+void testEqualStringsLen(void)
+{
+    const char *testString = "foobar";
+    TEST_ASSERT_EQUAL_STRING_LEN(testString, testString, strlen(testString));
+    TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE("foobar", "foobaz", 5, "fooba isn't fooba");
+    TEST_ASSERT_EQUAL_STRING_LEN("foo", testString, 3);
+    TEST_ASSERT_EQUAL_STRING_LEN(testString, "foo", 3);
+    TEST_ASSERT_EQUAL_STRING_LEN("", "", 3);
+}
+
+void testEqualStringsWithCarriageReturnsAndLineFeeds(void)
+{
+    const char *testString = "foo\r\nbar";
+
+    TEST_ASSERT_EQUAL_STRING(testString, testString);
+    TEST_ASSERT_EQUAL_STRING("foo\r\nbar", "foo\r\nbar");
+    TEST_ASSERT_EQUAL_STRING("foo\r\nbar", testString);
+    TEST_ASSERT_EQUAL_STRING(testString, "foo\r\nbar");
+    TEST_ASSERT_EQUAL_STRING("", "");
+}
+
+void testNotEqualString1(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING("foo", "bar");
+    VERIFY_FAILS_END
+}
+
+void testNotEqualStringLen1(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_LEN("foobar", "foobaz", 6);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualString2(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING("foo", "");
+    VERIFY_FAILS_END
+}
+
+void testNotEqualStringLen2(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_LEN("foo", "", 3);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualString3(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING("", "bar");
+    VERIFY_FAILS_END
+}
+
+void testNotEqualStringLen3(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_LEN("", "bar", 3);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualString4(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING("bar\r", "bar\n");
+    VERIFY_FAILS_END
+}
+
+void testNotEqualStringLen4(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_LEN("\r\x16", "bar\n", 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualString5(void)
+{
+    const char str1[] = { 0x41, 0x42, 0x03, 0x00 };
+    const char str2[] = { 0x41, 0x42, 0x04, 0x00 };
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING(str1, str2);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualString_ExpectedStringIsNull(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING(NULL, "bar");
+    VERIFY_FAILS_END
+}
+
+void testNotEqualStringLen_ExpectedStringIsNull(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_LEN(NULL, "bar", 1);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualString_ActualStringIsNull(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING("foo", NULL);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualStringLen_ActualStringIsNull(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_LEN("foo", NULL, 1);
+    VERIFY_FAILS_END
+}
+
+void testEqualStringArrays(void)
+{
+    const char *testStrings[] = { "foo", "boo", "woo", "moo" };
+    const char *expStrings[] = { "foo", "boo", "woo", "zoo" };
+
+    TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, expStrings, 3);
+    TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 3);
+    TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 2);
+    TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 1);
+}
+
+void testNotEqualStringArray1(void)
+{
+    const char *testStrings[] = { "foo", "boo", "woo", "moo" };
+    const char *expStrings[] = { "foo", "boo", "woo", "zoo" };
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualStringArray2(void)
+{
+    const char *testStrings[] = { "zoo", "boo", "woo", "moo" };
+    const char *expStrings[] = { "foo", "boo", "woo", "moo" };
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualStringArray3(void)
+{
+    const char *testStrings[] = { "foo", "boo", "woo", NULL };
+    const char *expStrings[] = { "foo", "boo", "woo", "zoo" };
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualStringArray4(void)
+{
+    const char *testStrings[] = { "foo", "boo", "woo", "moo" };
+    const char *expStrings[] = { "foo", NULL, "woo", "moo" };
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualStringArray5(void)
+{
+    const char **testStrings = NULL;
+    const char *expStrings[] = { "foo", "boo", "woo", "zoo" };
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualStringArray6(void)
+{
+    const char *testStrings[] = { "foo", "boo", "woo", "zoo" };
+    const char **expStrings = NULL;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+    VERIFY_FAILS_END
+}
+
+void testEqualStringArrayIfBothNulls(void)
+{
+    const char **testStrings = NULL;
+    const char **expStrings = NULL;
+
+    TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 4);
+}
+
+void testNotEqualStringArrayLengthZero(void)
+{
+    const char *testStrings[] = {NULL};
+    const char **expStrings = NULL;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_ARRAY(expStrings, testStrings, 0);
+    VERIFY_FAILS_END
+}
+
+void testEqualMemory(void)
+{
+    const char *testString = "whatever";
+
+    TEST_ASSERT_EQUAL_MEMORY(testString, testString, 8);
+    TEST_ASSERT_EQUAL_MEMORY("whatever", "whatever", 8);
+    TEST_ASSERT_EQUAL_MEMORY("whatever", testString, 8);
+    TEST_ASSERT_EQUAL_MEMORY(testString, "whatever", 8);
+    TEST_ASSERT_EQUAL_MEMORY(testString, "whatever", 2);
+    TEST_ASSERT_EQUAL_MEMORY(NULL, NULL, 1);
+}
+
+void testNotEqualMemory1(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_MEMORY("foo", "bar", 3);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualMemory2(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_MEMORY("fool", "food", 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualMemory3(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_MEMORY(NULL, "food", 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualMemory4(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_MEMORY("fool", NULL, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryLengthZero(void)
+{
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_MEMORY(NULL, NULL, 0);
+    VERIFY_FAILS_END
+}
+
+void testEqualIntArrays(void)
+{
+    int p0[] = {1, 8, 987, -2};
+    int p1[] = {1, 8, 987, -2};
+    int p2[] = {1, 8, 987, 2};
+    int p3[] = {1, 500, 600, 700};
+
+    TEST_ASSERT_EQUAL_INT_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_INT_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_INT_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_INT_ARRAY(p0, p3, 1);
+    TEST_ASSERT_EQUAL_INT_ARRAY(NULL, NULL, 1);
+}
+
+void testNotEqualIntArraysNullExpected(void)
+{
+    int* p0 = NULL;
+    int p1[] = {1, 8, 987, 2};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualIntArraysNullActual(void)
+{
+    int* p1 = NULL;
+    int p0[] = {1, 8, 987, 2};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualIntArrays1(void)
+{
+    int p0[] = {1, 8, 987, -2};
+    int p1[] = {1, 8, 987, 2};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualIntArrays2(void)
+{
+    int p0[] = {1, 8, 987, -2};
+    int p1[] = {2, 8, 987, -2};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualIntArrays3(void)
+{
+    int p0[] = {1, 8, 987, -2};
+    int p1[] = {1, 8, 986, -2};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualIntArraysLengthZero(void)
+{
+    _UU32 p0[1] = {1};
+    _UU32 p1[1] = {1};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT_ARRAY(p0, p1, 0);
+    VERIFY_FAILS_END
+}
+
+void testEqualPtrArrays(void)
+{
+    char A = 1;
+    char B = 2;
+    char C = 3;
+    char* p0[] = {&A, &B, &C};
+    char* p1[] = {&A, &B, &C, &A};
+    char* p2[] = {&A, &B};
+    char* p3[] = {&A};
+
+    TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p0, 3);
+    TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 3);
+    TEST_ASSERT_EQUAL_PTR_ARRAY(p1, p2, 2);
+    TEST_ASSERT_EQUAL_PTR_ARRAY(p3, p0, 1);
+}
+
+void testNotEqualPtrArraysNullExpected(void)
+{
+    char A = 1;
+    char B = 2;
+    char** p0 = NULL;
+    char* p1[] = {&A, &B};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 2);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualPtrArraysNullActual(void)
+{
+    char A = 1;
+    char B = 2;
+    char** p0 = NULL;
+    char* p1[] = {&A, &B};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_PTR_ARRAY(p1, p0, 2);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualPtrArrays1(void)
+{
+    char A = 1;
+    char B = 2;
+    char C = 3;
+    char* p0[] = {&A, &B, &C, &B};
+    char* p1[] = {&A, &B, &C, &A};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualPtrArrays2(void)
+{
+    char A = 1;
+    char B = 2;
+    char C = 3;
+    char* p0[] = {&B, &B, &C, &A};
+    char* p1[] = {&A, &B, &C, &A};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualPtrArrays3(void)
+{
+    char A = 1;
+    char B = 2;
+    char C = 3;
+    char* p0[] = {&A, &B, &B, &A};
+    char* p1[] = {&A, &B, &C, &A};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_PTR_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testEqualInt8Arrays(void)
+{
+    _US8 p0[] = {1, 8, 117, -2};
+    _US8 p1[] = {1, 8, 117, -2};
+    _US8 p2[] = {1, 8, 117, 2};
+    _US8 p3[] = {1, 50, 60, 70};
+
+    TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualInt8Arrays(void)
+{
+    _US8 p0[] = {1, 8, 36, -2};
+    _US8 p1[] = {1, 8, 36, 2};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT8_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testEqualUIntArrays(void)
+{
+    unsigned int p0[] = {1, 8, 987, 65132u};
+    unsigned int p1[] = {1, 8, 987, 65132u};
+    unsigned int p2[] = {1, 8, 987, 2};
+    unsigned int p3[] = {1, 500, 600, 700};
+
+    TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualUIntArrays1(void)
+{
+    unsigned int p0[] = {1, 8, 987, 65132u};
+    unsigned int p1[] = {1, 8, 987, 65131u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualUIntArrays2(void)
+{
+    unsigned int p0[] = {1, 8, 987, 65132u};
+    unsigned int p1[] = {2, 8, 987, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualUIntArrays3(void)
+{
+    unsigned int p0[] = {1, 8, 987, 65132u};
+    unsigned int p1[] = {1, 8, 986, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testEqualInt16Arrays(void)
+{
+    _US16 p0[] = {1, 8, 117, 3};
+    _US16 p1[] = {1, 8, 117, 3};
+    _US16 p2[] = {1, 8, 117, 2};
+    _US16 p3[] = {1, 50, 60, 70};
+
+    TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualInt16Arrays(void)
+{
+    _US16 p0[] = {1, 8, 127, 3};
+    _US16 p1[] = {1, 8, 127, 2};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT16_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testEqualInt32Arrays(void)
+{
+    _US32 p0[] = {1, 8, 117, 3};
+    _US32 p1[] = {1, 8, 117, 3};
+    _US32 p2[] = {1, 8, 117, 2};
+    _US32 p3[] = {1, 50, 60, 70};
+
+    TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualInt32Arrays(void)
+{
+    _US32 p0[] = {1, 8, 127, 3};
+    _US32 p1[] = {1, 8, 127, 2};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT32_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testEqualUINT8Arrays(void)
+{
+    _UU8 p0[] = {1, 8, 100, 127};
+    _UU8 p1[] = {1, 8, 100, 127};
+    _UU8 p2[] = {1, 8, 100, 2};
+    _UU8 p3[] = {1, 50, 60, 70};
+
+    TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualUINT8Arrays1(void)
+{
+    unsigned char p0[] = {1, 8, 100, 127u};
+    unsigned char p1[] = {1, 8, 100, 255u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualUINT8Arrays2(void)
+{
+    unsigned char p0[] = {1, 8, 100, 127u};
+    unsigned char p1[] = {1, 8, 100, 255u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualUINT8Arrays3(void)
+{
+    unsigned char p0[] = {1, 8, 100, 127u};
+    unsigned char p1[] = {1, 8, 100, 255u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT8_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+
+void testEqualUINT16Arrays(void)
+{
+    unsigned short p0[] = {1, 8, 987, 65132u};
+    unsigned short p1[] = {1, 8, 987, 65132u};
+    unsigned short p2[] = {1, 8, 987, 2};
+    unsigned short p3[] = {1, 500, 600, 700};
+
+    TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualUINT16Arrays1(void)
+{
+    unsigned short p0[] = {1, 8, 987, 65132u};
+    unsigned short p1[] = {1, 8, 987, 65131u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualUINT16Arrays2(void)
+{
+    unsigned short p0[] = {1, 8, 987, 65132u};
+    unsigned short p1[] = {2, 8, 987, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualUINT16Arrays3(void)
+{
+    unsigned short p0[] = {1, 8, 987, 65132u};
+    unsigned short p1[] = {1, 8, 986, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT16_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testEqualUINT32Arrays(void)
+{
+    _UU32 p0[] = {1, 8, 987, 65132u};
+    _UU32 p1[] = {1, 8, 987, 65132u};
+    _UU32 p2[] = {1, 8, 987, 2};
+    _UU32 p3[] = {1, 500, 600, 700};
+
+    TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualUINT32Arrays1(void)
+{
+    _UU32 p0[] = {1, 8, 987, 65132u};
+    _UU32 p1[] = {1, 8, 987, 65131u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualUINT32Arrays2(void)
+{
+    _UU32 p0[] = {1, 8, 987, 65132u};
+    _UU32 p1[] = {2, 8, 987, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualUINT32Arrays3(void)
+{
+    _UU32 p0[] = {1, 8, 987, 65132u};
+    _UU32 p1[] = {1, 8, 986, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT32_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testEqualHEXArrays(void)
+{
+    _UU32 p0[] = {1, 8, 987, 65132u};
+    _UU32 p1[] = {1, 8, 987, 65132u};
+    _UU32 p2[] = {1, 8, 987, 2};
+    _UU32 p3[] = {1, 500, 600, 700};
+
+    TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualHEXArrays1(void)
+{
+    _UU32 p0[] = {1, 8, 987, 65132u};
+    _UU32 p1[] = {1, 8, 987, 65131u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHEXArrays2(void)
+{
+    _UU32 p0[] = {1, 8, 987, 65132u};
+    _UU32 p1[] = {2, 8, 987, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHEXArrays3(void)
+{
+    _UU32 p0[] = {1, 8, 987, 65132u};
+    _UU32 p1[] = {1, 8, 986, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testEqualHEX32Arrays(void)
+{
+    _UU32 p0[] = {1, 8, 987, 65132u};
+    _UU32 p1[] = {1, 8, 987, 65132u};
+    _UU32 p2[] = {1, 8, 987, 2};
+    _UU32 p3[] = {1, 500, 600, 700};
+
+    TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualHEX32Arrays1(void)
+{
+    _UU32 p0[] = {1, 8, 987, 65132u};
+    _UU32 p1[] = {1, 8, 987, 65131u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHEX32Arrays2(void)
+{
+    _UU32 p0[] = {1, 8, 987, 65132u};
+    _UU32 p1[] = {2, 8, 987, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHEX32Arrays3(void)
+{
+    _UU32 p0[] = {1, 8, 987, 65132u};
+    _UU32 p1[] = {1, 8, 986, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX32_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testEqualHEX16Arrays(void)
+{
+    unsigned short p0[] = {1, 8, 987, 65132u};
+    unsigned short p1[] = {1, 8, 987, 65132u};
+    unsigned short p2[] = {1, 8, 987, 2};
+    unsigned short p3[] = {1, 500, 600, 700};
+
+    TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualHEX16Arrays1(void)
+{
+    unsigned short p0[] = {1, 8, 987, 65132u};
+    unsigned short p1[] = {1, 8, 987, 65131u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHEX16Arrays2(void)
+{
+    unsigned short p0[] = {1, 8, 987, 65132u};
+    unsigned short p1[] = {2, 8, 987, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHEX16Arrays3(void)
+{
+    unsigned short p0[] = {1, 8, 987, 65132u};
+    unsigned short p1[] = {1, 8, 986, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX16_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testEqualHEX8Arrays(void)
+{
+    unsigned short p0[] = {1, 8, 254u, 123};
+    unsigned short p1[] = {1, 8, 254u, 123};
+    unsigned short p2[] = {1, 8, 254u, 2};
+    unsigned short p3[] = {1, 23, 25, 26};
+
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p3, 1);
+}
+
+void testNotEqualHEX8Arrays1(void)
+{
+    unsigned char p0[] = {1, 8, 254u, 253u};
+    unsigned char p1[] = {1, 8, 254u, 252u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHEX8Arrays2(void)
+{
+    unsigned char p0[] = {1, 8, 254u, 253u};
+    unsigned char p1[] = {2, 8, 254u, 253u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualHEX8Arrays3(void)
+{
+    unsigned char p0[] = {1, 8, 254u, 253u};
+    unsigned char p1[] = {1, 8, 255u, 253u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX8_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+}
+
+void testEqualMemoryArrays(void)
+{
+    int p0[] = {1, 8, 987, -2};
+    int p1[] = {1, 8, 987, -2};
+    int p2[] = {1, 8, 987, 2};
+    int p3[] = {1, 500, 600, 700};
+
+    TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p0, sizeof(int), 1);
+    TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p0, sizeof(int), 4);
+    TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4);
+    TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p2, sizeof(int), 3);
+    TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p3, sizeof(int), 1);
+}
+
+void testNotEqualMemoryArraysExpectedNull(void)
+{
+    int* p0 = NULL;
+    int p1[] = {1, 8, 987, 2};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryArraysActualNull(void)
+{
+    int p0[] = {1, 8, 987, -2};
+    int* p1 = NULL;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryArrays1(void)
+{
+    int p0[] = {1, 8, 987, -2};
+    int p1[] = {1, 8, 987, 2};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryArrays2(void)
+{
+    int p0[] = {1, 8, 987, -2};
+    int p1[] = {2, 8, 987, -2};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4);
+    VERIFY_FAILS_END
+}
+
+void testNotEqualMemoryArrays3(void)
+{
+    int p0[] = {1, 8, 987, -2};
+    int p1[] = {1, 8, 986, -2};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_MEMORY_ARRAY(p0, p1, sizeof(int), 4);
+    VERIFY_FAILS_END
+}
+
+void testProtection(void)
+{
+    volatile int mask = 0;
+
+    if (TEST_PROTECT())
+    {
+        mask |= 1;
+        TEST_ABORT();
+    }
+    else
+    {
+        Unity.CurrentTestFailed = 0;
+        mask |= 2;
+    }
+
+    TEST_ASSERT_EQUAL(3, mask);
+}
+
+void testIgnoredAndThenFailInTearDown(void)
+{
+    SetToOneToFailInTearDown = 1;
+    TEST_IGNORE();
+}
+
+// Tricky series of macros to set USING_OUTPUT_SPY
+#define USING_SPY_AS(a)           EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0)
+#define ASSIGN_VALUE(a)           VAL_##a
+#define VAL_putcharSpy            0, 1
+#define EXPAND_AND_USE_2ND(a, b)  SECOND_PARAM(a, b, throwaway)
+#define SECOND_PARAM(a, b, ...)   b
+#if USING_SPY_AS(UNITY_OUTPUT_CHAR)
+  #define USING_OUTPUT_SPY // true only if UNITY_OUTPUT_CHAR = putcharSpy
+#endif
+
+#ifdef USING_OUTPUT_SPY
+#include <stdio.h>
+#define SPY_BUFFER_MAX 40
+static char putcharSpyBuffer[SPY_BUFFER_MAX];
+#endif
+static int indexSpyBuffer;
+static int putcharSpyEnabled;
+
+void startPutcharSpy(void) {indexSpyBuffer = 0; putcharSpyEnabled = 1;}
+
+void endPutcharSpy(void) {putcharSpyEnabled = 0;}
+
+char* getBufferPutcharSpy(void)
+{
+#ifdef USING_OUTPUT_SPY
+    putcharSpyBuffer[indexSpyBuffer] = '\0';
+    return putcharSpyBuffer;
+#else
+    return NULL;
+#endif
+}
+
+void putcharSpy(int c)
+{
+#ifdef USING_OUTPUT_SPY
+    if (putcharSpyEnabled)
+    {
+        if (indexSpyBuffer < SPY_BUFFER_MAX - 1)
+            putcharSpyBuffer[indexSpyBuffer++] = (char)c;
+    } else
+        c = putchar(c);
+#endif
+}
+
+void testFailureCountIncrementsAndIsReturnedAtEnd(void)
+{
+    Unity.CurrentTestFailed = 1;
+    startPutcharSpy(); // Suppress output
+    UnityConcludeTest();
+    TEST_ASSERT_EQUAL(1, Unity.TestFailures);
+
+    int failures = UnityEnd();
+    Unity.TestFailures--;
+    endPutcharSpy();
+    TEST_ASSERT_EQUAL(1, failures);
+}
+
+#define TEST_ASSERT_EQUAL_PRINT_NUMBERS(expected, actual) {             \
+        startPutcharSpy(); UnityPrintNumber((actual)); endPutcharSpy(); \
+        TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy());    \
+        }
+
+#define TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS(expected, actual) {            \
+        startPutcharSpy(); UnityPrintNumberUnsigned((actual)); endPutcharSpy(); \
+        TEST_ASSERT_EQUAL_STRING((expected), getBufferPutcharSpy());            \
+        }
+
+void testPrintNumbers32(void)
+{
+#ifndef USING_OUTPUT_SPY
+    TEST_IGNORE_MESSAGE("Compile with '-D UNITY_OUTPUT_CHAR=putcharSpy' to enable print testing");
+#else
+    TEST_ASSERT_EQUAL_PRINT_NUMBERS("0", 0);
+    TEST_ASSERT_EQUAL_PRINT_NUMBERS("1", 1);
+    TEST_ASSERT_EQUAL_PRINT_NUMBERS("-1", -1);
+    TEST_ASSERT_EQUAL_PRINT_NUMBERS("2000000000", 2000000000);
+    TEST_ASSERT_EQUAL_PRINT_NUMBERS("-2147483648", (_US32)0x80000000);
+    TEST_ASSERT_EQUAL_PRINT_NUMBERS("-1",          (_US32)0xFFFFFFFF);
+#endif
+}
+
+void testPrintNumbersUnsigned32(void)
+{
+#ifndef USING_OUTPUT_SPY
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("0", 0);
+    TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("1", 1);
+    TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("1500000000", 1500000000);
+    TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("2147483648", (_UU32)0x80000000);
+    TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("4294967295", (_UU32)0xFFFFFFFF);
+#endif
+}
+
+// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES 64 BIT SUPPORT ==================
+
+void testPrintNumbersInt64(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+  #ifndef USING_OUTPUT_SPY
+    TEST_IGNORE();
+  #else
+    TEST_ASSERT_EQUAL_PRINT_NUMBERS("0", 0);
+    TEST_ASSERT_EQUAL_PRINT_NUMBERS("10000000000", 10000000000);
+    TEST_ASSERT_EQUAL_PRINT_NUMBERS("-9223372036854775808", (_U_SINT)0x8000000000000000);
+    TEST_ASSERT_EQUAL_PRINT_NUMBERS("-1", (_U_SINT)0xFFFFFFFFFFFFFFFF);
+  #endif
+#endif
+}
+
+void testPrintNumbersUInt64(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+  #ifndef USING_OUTPUT_SPY
+    TEST_IGNORE();
+  #else
+    TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("0", 0);
+    TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("70000000000", 70000000000);
+    TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("9223372036854775808",  (_U_UINT)0x8000000000000000);
+    TEST_ASSERT_EQUAL_PRINT_UNSIGNED_NUMBERS("18446744073709551615", (_U_UINT)0xFFFFFFFFFFFFFFFF);
+  #endif
+#endif
+}
+
+void testEqualHex64s(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _UU64 v0, v1;
+    _UU64 *p0, *p1;
+
+    v0 = 0x9876543201234567;
+    v1 = 0x9876543201234567;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_HEX64(0x9876543201234567, 0x9876543201234567);
+    TEST_ASSERT_EQUAL_HEX64(v0, v1);
+    TEST_ASSERT_EQUAL_HEX64(0x9876543201234567, v1);
+    TEST_ASSERT_EQUAL_HEX64(v0, 0x9876543201234567);
+    TEST_ASSERT_EQUAL_HEX64(*p0, v1);
+    TEST_ASSERT_EQUAL_HEX64(*p0, *p1);
+    TEST_ASSERT_EQUAL_HEX64(*p0, 0x9876543201234567);
+#endif
+}
+
+void testEqualUint64s(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _UU64 v0, v1;
+    _UU64 *p0, *p1;
+
+    v0 = 0x9876543201234567;
+    v1 = 0x9876543201234567;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_UINT64(0x9876543201234567, 0x9876543201234567);
+    TEST_ASSERT_EQUAL_UINT64(v0, v1);
+    TEST_ASSERT_EQUAL_UINT64(0x9876543201234567, v1);
+    TEST_ASSERT_EQUAL_UINT64(v0, 0x9876543201234567);
+    TEST_ASSERT_EQUAL_UINT64(*p0, v1);
+    TEST_ASSERT_EQUAL_UINT64(*p0, *p1);
+    TEST_ASSERT_EQUAL_UINT64(*p0, 0x9876543201234567);
+#endif
+}
+
+void testEqualInt64s(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _US64 v0, v1;
+    _US64 *p0, *p1;
+
+    v0 = (_US64)0x9876543201234567;
+    v1 = (_US64)0x9876543201234567;
+    p0 = &v0;
+    p1 = &v1;
+
+    TEST_ASSERT_EQUAL_INT64(0x9876543201234567, 0x9876543201234567);
+    TEST_ASSERT_EQUAL_INT64(v0, v1);
+    TEST_ASSERT_EQUAL_INT64(0x9876543201234567, v1);
+    TEST_ASSERT_EQUAL_INT64(v0, 0x9876543201234567);
+    TEST_ASSERT_EQUAL_INT64(*p0, v1);
+    TEST_ASSERT_EQUAL_INT64(*p0, *p1);
+    TEST_ASSERT_EQUAL_INT64(*p0, 0x9876543201234567);
+#endif
+}
+
+
+void testNotEqualHex64s(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _UU64 v0, v1;
+
+    v0 = 9000000000;
+    v1 = 9100000000;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX64(v0, v1);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualUint64s(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _UU64 v0, v1;
+
+    v0 = 9000000000;
+    v1 = 9100000000;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT64(v0, v1);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualInt64s(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _US64 v0, v1;
+
+    v0 = -9000000000;
+    v1 = 9100000000;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT64(v0, v1);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualHex64sIfSigned(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _US64 v0, v1;
+
+    v0 = -9000000000;
+    v1 = 9000000000;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX64(v0, v1);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testHEX64sWithinDelta(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_HEX64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x7FFFFFFFFFFFFFFE);
+    TEST_ASSERT_HEX64_WITHIN(5, 5000, 4996);
+    TEST_ASSERT_HEX64_WITHIN(5, 5000, 5005);
+#endif
+}
+
+void testHEX64sNotWithinDelta(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_HEX64_WITHIN(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFC);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testHEX64sNotWithinDeltaEvenThoughASignedIntWouldPass(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_HEX64_WITHIN(5, 1, -1);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testUINT64sWithinDelta(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_UINT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x7FFFFFFFFFFFFFFE);
+    TEST_ASSERT_UINT64_WITHIN(5, 5000, 4996);
+    TEST_ASSERT_UINT64_WITHIN(5, 5000, 5005);
+#endif
+}
+
+void testUINT64sNotWithinDelta(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFC);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testUINT64sNotWithinDeltaEvenThoughASignedIntWouldPass(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_UINT64_WITHIN(5, 1, -1);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testINT64sWithinDelta(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_INT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF,0x7FFFFFFFFFFFFFFE);
+    TEST_ASSERT_INT64_WITHIN(5, 5000, 4996);
+    TEST_ASSERT_INT64_WITHIN(5, 5000, 5005);
+#endif
+}
+
+void testINT64sNotWithinDelta(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_INT64_WITHIN(1, 0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFC);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testINT64sNotWithinDeltaAndDifferenceOverflows(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_INT64_WITHIN(1, 0x8000000000000000, 0x7FFFFFFFFFFFFFFF);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testEqualHEX64Arrays(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _UU64 p0[] = {1, 8, 987, 65132u};
+    _UU64 p1[] = {1, 8, 987, 65132u};
+    _UU64 p2[] = {1, 8, 987, 2};
+    _UU64 p3[] = {1, 500, 600, 700};
+
+    TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p3, 1);
+#endif
+}
+
+void testEqualUint64Arrays(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _UU64 p0[] = {1, 8, 987, 65132u};
+    _UU64 p1[] = {1, 8, 987, 65132u};
+    _UU64 p2[] = {1, 8, 987, 2};
+    _UU64 p3[] = {1, 500, 600, 700};
+
+    TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p3, 1);
+#endif
+}
+
+void testEqualInt64Arrays(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _US64 p0[] = {1, 8, 987, -65132};
+    _US64 p1[] = {1, 8, 987, -65132};
+    _US64 p2[] = {1, 8, 987, -2};
+    _US64 p3[] = {1, 500, 600, 700};
+
+    TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p3, 1);
+#endif
+}
+
+
+void testNotEqualHEX64Arrays1(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _UU64 p0[] = {1, 8, 987, 65132u};
+    _UU64 p1[] = {1, 8, 987, 65131u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualHEX64Arrays2(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _UU64 p0[] = {1, 8, 987, 65132u};
+    _UU64 p1[] = {2, 8, 987, 65132u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX64_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualUint64Arrays(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _UU64 p0[] = {1, 8, 987, 65132u};
+    _UU64 p1[] = {1, 8, 987, 65131u};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_UINT64_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualInt64Arrays(void)
+{
+#ifndef UNITY_SUPPORT_64
+    TEST_IGNORE();
+#else
+    _US64 p0[] = {1, 8, 987, -65132};
+    _US64 p1[] = {1, 8, 987, -65131};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT64_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES FLOAT SUPPORT ==================
+
+void testFloatsWithinDelta(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_FLOAT_WITHIN(0.00003f, 187245.03485f, 187245.03488f);
+    TEST_ASSERT_FLOAT_WITHIN(1.0f, 187245.0f, 187246.0f);
+    TEST_ASSERT_FLOAT_WITHIN(0.05f, 9273.2549f, 9273.2049f);
+    TEST_ASSERT_FLOAT_WITHIN(0.007f, -726.93724f, -726.94424f);
+#endif
+}
+
+void testFloatsNotWithinDelta(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_FLOAT_WITHIN(0.05f, 9273.2649f, 9273.2049f);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsEqual(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_EQUAL_FLOAT(187245.0f, 187246.0f);
+    TEST_ASSERT_EQUAL_FLOAT(18724.5f, 18724.6f);
+    TEST_ASSERT_EQUAL_FLOAT(9273.2549f, 9273.2599f);
+    TEST_ASSERT_EQUAL_FLOAT(-726.93724f, -726.9374f);
+#endif
+}
+
+void testFloatsNotEqual(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT(9273.9649f, 9273.0049f);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualNegative1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT(-9273.9649f, -9273.0049f);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualNegative2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT(-9273.0049f, -9273.9649f);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualActualNaN(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT(85.963f, 0.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualExpectedNaN(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT(0.0f / f_zero, 85.963f);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualBothNaN(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT(0.0f / f_zero, 0.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualInfNaN(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 0.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualNaNInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT(0.0f / f_zero, 1.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualActualInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT(321.642f, 1.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualExpectedInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 321.642f);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualBothInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, 1.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatsNotEqualPlusMinusInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT(1.0f / f_zero, -1.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsPosInf1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_FLOAT_IS_INF(2.0f / f_zero);
+#endif
+}
+
+void testFloatIsPosInf2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_FLOAT_IS_NOT_INF(2.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNegInf1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_FLOAT_IS_NEG_INF(-3.0f / f_zero);
+#endif
+}
+
+void testFloatIsNegInf2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(-3.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNotPosInf1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_FLOAT_IS_INF(2.0f);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNotPosInf2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_FLOAT_IS_NOT_INF(2.0f);
+#endif
+}
+
+void testFloatIsNotNegInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_FLOAT_IS_NEG_INF(-999.876f);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNan1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_FLOAT_IS_NAN(0.0f / f_zero);
+#endif
+}
+
+void testFloatIsNan2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_FLOAT_IS_NOT_NAN(0.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNotNan1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_FLOAT_IS_NAN(234.9f);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNotNan2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_FLOAT_IS_NOT_NAN(234.9f);
+#endif
+}
+
+void testFloatInfIsNotNan(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_FLOAT_IS_NAN(1.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatNanIsNotInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_FLOAT_IS_INF(0.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsDeterminate1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_FLOAT_IS_DETERMINATE(0.0f);
+    TEST_ASSERT_FLOAT_IS_DETERMINATE(123.3f);
+    TEST_ASSERT_FLOAT_IS_DETERMINATE(-88.3f);
+#endif
+}
+
+void testFloatIsDeterminate2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(-88.3f);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatIsNotDeterminate1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(1.0f / f_zero);
+    TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(-1.0f / f_zero);
+    TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(0.0f / f_zero);
+#endif
+}
+
+void testFloatIsNotDeterminate2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_FLOAT_IS_DETERMINATE(-1.0f / f_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testFloatTraitFailsOnInvalidTrait(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    UnityAssertFloatSpecial(1.0f, NULL, __LINE__, UNITY_FLOAT_INVALID_TRAIT);
+    VERIFY_FAILS_END
+#endif
+}
+
+
+void testEqualFloatArrays(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    float p0[] = {1.0f, -8.0f,  25.4f, -0.123f};
+    float p1[] = {1.0f, -8.0f,  25.4f, -0.123f};
+    float p2[] = {1.0f, -8.0f,  25.4f, -0.2f};
+    float p3[] = {1.0f, -23.0f, 25.0f, -0.26f};
+
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p3, 1);
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(NULL, NULL, 1);
+#endif
+}
+
+void testNotEqualFloatArraysExpectedNull(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    float* p0 = NULL;
+    float p1[] = {1.0f, 8.0f, 25.4f, 0.252f};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArraysActualNull(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    float p0[] = {1.0f, 8.0f, 25.4f, 0.253f};
+    float* p1 = NULL;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArrays1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    float p0[] = {1.0f, 8.0f, 25.4f, 0.253f};
+    float p1[] = {1.0f, 8.0f, 25.4f, 0.252f};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArrays2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    float p0[] = {1.0f, 8.0f, 25.4f, 0.253f};
+    float p1[] = {2.0f, 8.0f, 25.4f, 0.253f};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArrays3(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    float p0[] = {1.0f, 8.0f, 25.4f, 0.253f};
+    float p1[] = {1.0f, 8.0f, 25.5f, 0.253f};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArraysNegative1(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    float p0[] = {-1.0f, -8.0f, -25.4f, -0.253f};
+    float p1[] = {-1.0f, -8.0f, -25.4f, -0.252f};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArraysNegative2(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    float p0[] = {-1.0f, -8.0f, -25.4f, -0.253f};
+    float p1[] = {-2.0f, -8.0f, -25.4f, -0.253f};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArraysNegative3(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    float p0[] = {-1.0f, -8.0f, -25.4f, -0.253f};
+    float p1[] = {-1.0f, -8.0f, -25.5f, -0.253f};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArraysNaN(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    float p0[] = {1.0f, 0.0f / f_zero, 25.4f, 0.253f};
+    float p1[] = {1.0f, 0.0f / f_zero, 25.4f, 0.253f};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArraysInf(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    float p0[] = {1.0f, 1.0f / f_zero, 25.4f, 0.253f};
+    float p1[] = {1.0f, 1.0f / f_zero, 25.4f, 0.253f};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualFloatArraysLengthZero(void)
+{
+#ifdef UNITY_EXCLUDE_FLOAT
+    TEST_IGNORE();
+#else
+    float p0[1] = {0.0f};
+    float p1[1] = {0.0f};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_FLOAT_ARRAY(p0, p1, 0);
+    VERIFY_FAILS_END
+#endif
+}
+
+// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DOUBLE SUPPORT ==================
+
+void testDoublesWithinDelta(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_DOUBLE_WITHIN(0.00003, 187245.03485, 187245.03488);
+    TEST_ASSERT_DOUBLE_WITHIN(1.0, 187245.0, 187246.0);
+    TEST_ASSERT_DOUBLE_WITHIN(0.05, 9273.2549, 9273.2049);
+    TEST_ASSERT_DOUBLE_WITHIN(0.007, -726.93725, -726.94424);
+#endif
+}
+
+void testDoublesNotWithinDelta(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_DOUBLE_WITHIN(0.05, 9273.2649, 9273.2049);
+    VERIFY_FAILS_END
+#endif
+}
+
+
+void testDoublesEqual(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_EQUAL_DOUBLE(187245123456.0, 187245123456.0);
+    TEST_ASSERT_EQUAL_DOUBLE(187241234567.5, 187241234567.6);
+    TEST_ASSERT_EQUAL_DOUBLE(9273.2512345649, 9273.25123455699);
+    TEST_ASSERT_EQUAL_DOUBLE(-726.12345693724, -726.1234569374);
+#endif
+}
+
+void testDoublesNotEqual(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE(9273.9649, 9273.0049);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualNegative1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE(-9273.9649, -9273.0049);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualNegative2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE(-9273.0049, -9273.9649);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualActualNaN(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE(85.963, 0.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualExpectedNaN(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE(0.0 / d_zero, 85.963);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualBothNaN(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE(0.0 / d_zero, 0.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualInfNaN(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 0.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualNaNInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE(0.0 / d_zero, 1.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualActualInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE(321.642, 1.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualExpectedInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 321.642);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualBothInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, 1.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoublesNotEqualPlusMinusInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE(1.0 / d_zero, -1.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsPosInf1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_DOUBLE_IS_INF(2.0 / d_zero);
+#endif
+}
+
+void testDoubleIsPosInf2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_DOUBLE_IS_NOT_INF(2.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNegInf1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_DOUBLE_IS_NEG_INF(-3.0 / d_zero);
+#endif
+}
+
+void testDoubleIsNegInf2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(-3.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNotPosInf1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_DOUBLE_IS_INF(2.0);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNotPosInf2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_DOUBLE_IS_NOT_INF(2.0);
+#endif
+}
+
+void testDoubleIsNotNegInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_DOUBLE_IS_NEG_INF(-999.876);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNan1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_DOUBLE_IS_NAN(0.0 / d_zero);
+#endif
+}
+
+void testDoubleIsNan2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_DOUBLE_IS_NOT_NAN(0.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNotNan1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_DOUBLE_IS_NAN(234.9);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNotNan2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_DOUBLE_IS_NOT_NAN(234.9);
+#endif
+}
+
+void testDoubleInfIsNotNan(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_DOUBLE_IS_NAN(1.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleNanIsNotInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_DOUBLE_IS_INF(0.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsDeterminate1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_DOUBLE_IS_DETERMINATE(0.0);
+    TEST_ASSERT_DOUBLE_IS_DETERMINATE(123.3);
+    TEST_ASSERT_DOUBLE_IS_DETERMINATE(-88.3);
+#endif
+}
+
+void testDoubleIsDeterminate2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(-88.3);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleIsNotDeterminate1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(1.0 / d_zero);
+    TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(-1.0 / d_zero);
+    TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(0.0 / d_zero);
+#endif
+}
+
+void testDoubleIsNotDeterminate2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_DOUBLE_IS_DETERMINATE(-1.0 / d_zero);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testDoubleTraitFailsOnInvalidTrait(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    EXPECT_ABORT_BEGIN
+    UnityAssertDoubleSpecial(1.0, NULL, __LINE__, UNITY_FLOAT_INVALID_TRAIT);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testEqualDoubleArrays(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    double p0[] = {1.0, -8.0,  25.4, -0.123};
+    double p1[] = {1.0, -8.0,  25.4, -0.123};
+    double p2[] = {1.0, -8.0,  25.4, -0.2};
+    double p3[] = {1.0, -23.0, 25.0, -0.26};
+
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p0, 1);
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p0, 4);
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p2, 3);
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p3, 1);
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(NULL, NULL, 1);
+#endif
+}
+
+void testNotEqualDoubleArraysExpectedNull(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    double* p0 = NULL;
+    double p1[] = {1.0, 8.0, 25.4, 0.252};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArraysActualNull(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    double p0[] = {1.0, 8.0, 25.4, 0.253};
+    double* p1 = NULL;
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArrays1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    double p0[] = {1.0, 8.0, 25.4, 0.25666666667};
+    double p1[] = {1.0, 8.0, 25.4, 0.25666666666};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArrays2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    double p0[] = {1.0, 8.0, 25.4, 0.253};
+    double p1[] = {2.0, 8.0, 25.4, 0.253};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArrays3(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    double p0[] = {1.0, 8.0, 25.4, 0.253};
+    double p1[] = {1.0, 8.0, 25.5, 0.253};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArraysNegative1(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    double p0[] = {-1.0, -8.0, -25.4, -0.2566666667};
+    double p1[] = {-1.0, -8.0, -25.4, -0.2566666666};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArraysNegative2(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    double p0[] = {-1.0, -8.0, -25.4, -0.253};
+    double p1[] = {-2.0, -8.0, -25.4, -0.253};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArraysNegative3(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    double p0[] = {-1.0, -8.0, -25.4, -0.253};
+    double p1[] = {-1.0, -8.0, -25.5, -0.253};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArraysNaN(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    double p0[] = {1.0, 0.0 / d_zero, 25.4, 0.253};
+    double p1[] = {1.0, 0.0 / d_zero, 25.4, 0.253};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArraysInf(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    double p0[] = {1.0, 1.0 / d_zero, 25.4, 0.253};
+    double p1[] = {1.0, 1.0 / d_zero, 25.4, 0.253};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 4);
+    VERIFY_FAILS_END
+#endif
+}
+
+void testNotEqualDoubleArraysLengthZero(void)
+{
+#ifdef UNITY_EXCLUDE_DOUBLE
+    TEST_IGNORE();
+#else
+    double p0[1] = {0.0};
+    double p1[1] = {0.0};
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_DOUBLE_ARRAY(p0, p1, 0);
+    VERIFY_FAILS_END
+#endif
+}
+
+// ===================== THESE TEST WILL RUN IF YOUR CONFIG INCLUDES DETAIL SUPPORT ==================
+
+void testThatDetailsCanBeHandleOneDetail(void)
+{
+#ifdef UNITY_EXCLUDE_DETAILS
+    TEST_IGNORE();
+#else
+    UNITY_SET_DETAIL("Detail1");
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_INT_MESSAGE(5, 6, "Should Fail And Say Detail1");
+    VERIFY_FAILS_END
+#endif
+}
+
+void testThatDetailsCanHandleTestFail(void)
+{
+#ifdef UNITY_EXCLUDE_DETAILS
+    TEST_IGNORE();
+#else
+    UNITY_SET_DETAILS("Detail1","Detail2");
+
+    EXPECT_ABORT_BEGIN
+    TEST_FAIL_MESSAGE("Should Fail And Say Detail1 and Detail2");
+    VERIFY_FAILS_END
+#endif
+}
+
+void testThatDetailsCanBeHandleTwoDetails(void)
+{
+#ifdef UNITY_EXCLUDE_DETAILS
+    TEST_IGNORE();
+#else
+    UNITY_SET_DETAILS("Detail1","Detail2");
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_HEX8_MESSAGE(7, 8, "Should Fail And Say Detail1 and Detail2");
+    VERIFY_FAILS_END
+#endif
+}
+
+void testThatDetailsCanBeHandleSingleDetailClearingTwoDetails(void)
+{
+#ifdef UNITY_EXCLUDE_DETAILS
+    TEST_IGNORE();
+#else
+    UNITY_SET_DETAILS("Detail1","Detail2");
+    UNITY_SET_DETAIL("DetailNew");
+
+    EXPECT_ABORT_BEGIN
+    TEST_ASSERT_EQUAL_STRING_MESSAGE("MEH", "GUH", "Should Fail And Say DetailNew");
+    VERIFY_FAILS_END
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/Scripts/junit_cmd_wrapper.py	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,161 @@
+#!/usr/bin/env python
+import argparse
+import logging
+import string
+import subprocess
+import sys
+import time
+import xml.etree.cElementTree as ElementTree
+from io import BytesIO
+from threading import Thread
+
+logger = logging.getLogger('ta-junit-wrapper')
+
+
+class TeeBytesIO(BytesIO):
+    """duplicate each write command to an additional file object"""
+    def __init__(self, tee_fh):
+        self.tee_fh = tee_fh
+        super(TeeBytesIO, self).__init__()
+
+    def write(self, s):
+        self.tee_fh.write(s)
+        BytesIO.write(self, s)
+
+
+def get_parser():
+    parser = argparse.ArgumentParser(description='JUNIT wrapper')
+
+    parser.add_argument(
+        '-o',
+        '--output-file',
+        metavar='FILE',
+        type=argparse.FileType('w'),
+        help='output JUNIT XML file name',
+        required=True
+    )
+
+    parser.add_argument(
+        '-s',
+        '--test-suite',
+        metavar='NAME',
+        help='test suite name',
+        required=True
+    )
+
+    parser.add_argument(
+        '-t',
+        '--test-case',
+        metavar='NAME',
+        help='test case name',
+        required=True
+    )
+
+    parser.add_argument(
+        '-v',
+        '--verbose',
+        action='store_true',
+        help='verbose - duplicate command output to STDOUT'
+    )
+
+    parser.add_argument(
+        '--validate',
+        action='store_true',
+        help='validate generated XML against Jenkins XSD. Requires "requests" and "lxml" libraries'
+    )
+
+    parser.add_argument(
+        '--command',
+        nargs=argparse.REMAINDER,
+        help='command to be executed'
+    )
+    return parser
+
+
+def get_file_copy_worker(infile, outfile):
+    def do_work(_infile, _outfile):
+        for line in iter(_infile.readline, ''):
+            _outfile.write(line)
+        _infile.close()
+    thread = Thread(target=do_work, args=(infile, outfile))
+    thread.daemon = True
+    thread.start()
+    return thread
+
+
+def generate_junit_xml(test_suite, test_case, out_fh, stdout, stderr, return_code, duration_in_sec, command):
+    test_suite_root_element = ElementTree.Element(
+        'testsuite',
+        tests='1',
+        name=test_suite.replace(' ', '_'),
+        failures=str(1 if return_code != 0 else 0),
+        time=str(duration_in_sec)
+    )
+    test_case_element = ElementTree.SubElement(
+        test_suite_root_element,
+        'testcase',
+        time=str(duration_in_sec),
+        name=test_case.replace(' ', '_')
+    )
+    ElementTree.SubElement(test_case_element, 'system-out').text = filter(
+        lambda x: x in string.printable, stdout.getvalue()
+    )
+    ElementTree.SubElement(test_case_element, 'system-err').text = filter(
+        lambda x: x in string.printable, stderr.getvalue()
+    )
+
+    if return_code != 0:
+        failure_msg = 'Command "{cmd}" returned {ret}'.format(cmd=command, ret=return_code)
+        ElementTree.SubElement(
+            test_case_element,
+            'failure',
+            type='Non-Zero return code',
+            message=failure_msg)
+
+    ElementTree.ElementTree(test_suite_root_element).write(out_fh)
+
+
+def main():
+    parser = get_parser()
+    args = parser.parse_args()
+    logging.basicConfig(
+        level=logging.DEBUG if args.verbose else logging.INFO,
+        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
+        stream=sys.stdout
+    )
+
+    stdout = TeeBytesIO(sys.stdout) if args.verbose else BytesIO()
+    stderr = TeeBytesIO(stdout)
+    logger.debug('Executing + ' + ' '.join(args.command))
+    start_time = time.time()
+    process = subprocess.Popen(args.command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    threads = [
+        get_file_copy_worker(process.stdout, stdout),
+        get_file_copy_worker(process.stderr, stderr)
+    ]
+    for t in threads:  # wait for IO completion
+        t.join()
+    return_code = process.wait()
+    logger.debug('Wrapped process return code ' + str(return_code))
+    duration_in_sec = time.time() - start_time
+
+    with args.output_file as fh:  # insure file object is closed - since it will be read in do_validate()
+        generate_junit_xml(
+            args.test_suite,
+            args.test_case,
+            fh,
+            stdout,
+            stderr,
+            return_code,
+            duration_in_sec,
+            args.command
+        )
+    logger.debug('Generated JUNIT report file ' + args.output_file.name)
+
+    if args.validate:
+        do_validate(args.output_file.name)
+
+    raise SystemExit(return_code)
+
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/memoryProfiler/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+Other/*
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/memoryProfiler/Other/pal_memory.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,197 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+/*
+ * pal_memory.c
+ *
+ *  Created on: Jun 26, 2017
+ *      Author: pal
+ */
+
+#ifndef PAL_MEMORY_PRINT_DATA
+    #define PAL_MEMORY_PRINT_DATA	0
+#endif
+
+#ifndef PAL_MEMORY_BUCKET
+    #define PAL_MEMORY_BUCKET		0
+#endif
+
+#ifdef PAL_MEMORY_STATISTICS
+#include "stdio.h"
+#include "mbed-trace/mbed_trace.h"
+
+#define TRACE_GROUP "PAL_MEMORY"
+
+#ifdef PAL_MEMORY_BUCKET
+
+#define SMALL_BUCKET	32
+#define LARGE_BUCKET	4096
+
+typedef enum _memoryBucketSizes
+{
+	PAL_BUCKET_SIZE_32 = 0,
+	PAL_BUCKET_SIZE_64,
+	PAL_BUCKET_SIZE_128,
+	PAL_BUCKET_SIZE_256,
+	PAL_BUCKET_SIZE_512,
+	PAL_BUCKET_SIZE_1024,
+	PAL_BUCKET_SIZE_2048,
+	PAL_BUCKET_SIZE_4096,
+	PAL_BUCKET_SIZE_LARGE,
+	PAL_BUCKET_NUMBER
+}memoryBucketSizes;
+
+typedef struct _memoryAllocationData
+{
+	int32_t totalsize;
+	int32_t waterMark;
+	int32_t buckets[PAL_BUCKET_NUMBER];
+	int32_t waterMarkBuckets[PAL_BUCKET_NUMBER];
+}memoryAllocationData;
+
+static memoryAllocationData memoryStats = {0};
+
+
+static inline memoryBucketSizes getBucketNumber(size_t size)
+{
+	if (size <= SMALL_BUCKET)
+	{
+		return PAL_BUCKET_SIZE_32;
+	}
+	if (size >= LARGE_BUCKET)
+	{
+		return PAL_BUCKET_SIZE_LARGE;
+	}
+
+	uint8_t bucket = 1;
+	uint32_t power = 64; // Starting with 32
+	while (power < size)
+	{
+		bucket++;
+		power*=2;
+	}
+	return bucket;
+}
+#endif //PAL_MEMORY_BUCKET
+
+
+void* __wrap_malloc(size_t c)
+{
+	void *ptr  = NULL;
+#ifdef PAL_MEMORY_BUCKET
+	ptr = __real_malloc(c + sizeof(size_t) + sizeof(size_t));
+	if (ptr == NULL)
+	{
+		return NULL;
+	}
+	 int32_t currentTotal = pal_osAtomicIncrement((&memoryStats.totalsize),c);
+	if (currentTotal > memoryStats.waterMark)
+	{
+		memoryStats.waterMark = currentTotal; // need to make this thread safe
+	}
+
+	*(size_t*)ptr = c;
+	ptr = ((size_t*)ptr+1);
+	*(size_t*)ptr = (size_t)getBucketNumber(c);
+	 int32_t currentBucketTotal = pal_osAtomicIncrement(&(memoryStats.buckets[*(size_t*)ptr]),1);
+	if (memoryStats.waterMarkBuckets[*(size_t*)ptr] < currentBucketTotal)
+	{
+		memoryStats.waterMarkBuckets[*(size_t*)ptr] = currentBucketTotal;
+	}
+	ptr = ((size_t*)ptr + 1);
+#else
+	ptr = __real_malloc(c);
+#endif
+
+#if PAL_MEMORY_PRINT_DATA
+#ifdef __LINUX__
+	printf("malloc: ptr - %p, size - %d\n\r",ptr,c);
+#else
+	tr_info("malloc: ptr - %p, size - %d\n\r",ptr,c);
+#endif//LINUX
+
+#endif
+	return ptr;
+}
+
+
+void __wrap_free(void* ptr)
+{
+	if (NULL == ptr)
+	{
+		return;
+	}
+#if PAL_MEMORY_PRINT_DATA
+#ifdef __LINUX__
+	printf("free: ptr - %p\n\r",ptr);
+#endif
+#endif
+
+#ifdef PAL_MEMORY_BUCKET
+	ptr = ((size_t*)ptr-1);
+	pal_osAtomicIncrement(&(memoryStats.buckets[*(size_t*)ptr]),-1);
+	ptr = ((size_t*)ptr-1);
+	pal_osAtomicIncrement((&memoryStats.totalsize),-1*(*(size_t*)ptr));
+#endif
+
+
+
+	__real_free(ptr);
+
+}
+
+
+void* __wrap_calloc(size_t num, size_t size)
+{
+	void* ptr = __wrap_malloc(num*size);
+	if (NULL != ptr)
+	{
+		memset(ptr,0,(num*size));
+	}
+	return (ptr);
+}
+
+
+
+void printMemoryStats(void)
+{
+#ifdef PAL_MEMORY_BUCKET
+	tr_info("\n*******************************************************\r\n");
+	tr_info("water mark size = %ld\r\n",memoryStats.waterMark);
+	tr_info("total size = %ld\r\n",memoryStats.totalsize);
+	tr_info("bucket 32    allocation number %ld\r\n",memoryStats.buckets[PAL_BUCKET_SIZE_32]);
+	tr_info("bucket 64    allocation number %ld\r\n",memoryStats.buckets[PAL_BUCKET_SIZE_64]);
+	tr_info("bucket 128   allocation number %ld\r\n",memoryStats.buckets[PAL_BUCKET_SIZE_128]);
+	tr_info("bucket 258   allocation number %ld\r\n",memoryStats.buckets[PAL_BUCKET_SIZE_256]);
+	tr_info("bucket 512   allocation number %ld\r\n",memoryStats.buckets[PAL_BUCKET_SIZE_512]);
+	tr_info("bucket 1024  allocation number %ld\r\n",memoryStats.buckets[PAL_BUCKET_SIZE_1024]);
+	tr_info("bucket 2048  allocation number %ld\r\n",memoryStats.buckets[PAL_BUCKET_SIZE_2048]);
+	tr_info("bucket 4096  allocation number %ld\r\n",memoryStats.buckets[PAL_BUCKET_SIZE_4096]);
+	tr_info("bucket large allocation number %ld\r\n",memoryStats.buckets[PAL_BUCKET_SIZE_LARGE]);
+
+	tr_info("water mark bucket 32    allocation number %ld\r\n",memoryStats.waterMarkBuckets[PAL_BUCKET_SIZE_32]);
+	tr_info("water mark bucket 64    allocation number %ld\r\n",memoryStats.waterMarkBuckets[PAL_BUCKET_SIZE_64]);
+	tr_info("water mark bucket 128   allocation number %ld\r\n",memoryStats.waterMarkBuckets[PAL_BUCKET_SIZE_128]);
+	tr_info("water mark bucket 256   allocation number %ld\r\n",memoryStats.waterMarkBuckets[PAL_BUCKET_SIZE_256]);
+	tr_info("water mark bucket 512   allocation number %ld\r\n",memoryStats.waterMarkBuckets[PAL_BUCKET_SIZE_512]);
+	tr_info("water mark bucket 1024  allocation number %ld\r\n",memoryStats.waterMarkBuckets[PAL_BUCKET_SIZE_1024]);
+	tr_info("water mark bucket 2048  allocation number %ld\r\n",memoryStats.waterMarkBuckets[PAL_BUCKET_SIZE_2048]);
+	tr_info("water mark bucket 4096  allocation number %ld\r\n",memoryStats.waterMarkBuckets[PAL_BUCKET_SIZE_4096]);
+	tr_info("water mark bucket large allocation number %ld\r\n",memoryStats.waterMarkBuckets[PAL_BUCKET_SIZE_LARGE]);
+	tr_info("*******************************************************\r\n");
+#endif
+
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/memoryProfiler/mbed-os/pal_memory.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+/*
+ * pal_memory.c
+ *
+ *  Created on: Jun 26, 2017
+ *      Author: pal
+ */
+#ifdef PAL_MEMORY_STATISTICS
+
+#include "stdio.h"
+#include "mbed-trace/mbed_trace.h"
+#include "mbed_stats.h"
+
+#define TRACE_GROUP "PALM"
+void printMemoryStats(void)
+{
+	mbed_stats_heap_t heap_stats;
+	mbed_stats_heap_get(&heap_stats);
+
+	mbed_stats_stack_t stack_stats;
+	mbed_stats_stack_get(&stack_stats);
+	tr_info("--- heap stats ---\n");
+
+	tr_info("heap max size: %ld\n", heap_stats.max_size);
+	tr_info("heap reserved size: %ld\n", heap_stats.reserved_size);
+	tr_info("heap alloc cnt: %ld\n", heap_stats.alloc_cnt);
+	tr_info("heap alloc fail cnt: %ld\n", heap_stats.alloc_fail_cnt);
+
+	tr_info("--- stack stats ---\n");
+	tr_info("stack max size: %ld\n", stack_stats.max_size);
+	tr_info("stack reserved size: %ld\n", stack_stats.reserved_size);
+	tr_info("stack stack cnt: %ld\n", stack_stats.stack_cnt);
+
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/stackUsage/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+*
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/stackUsage/TestSuite/TargetFunctions.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,18 @@
+# TargetFunctions.txt contains the list of the functions' calls
+# User want to test their Stack Usage.
+#
+# User MUST supply include files, variables declarations, test function name and the target function call
+# for example:
+#          foo.h $ StackUsage_foo $ int a = 5; int b = 6; int c = 0 $ c = foo(a, a+b);
+# between each inputs (includes and variables for example) the syntax requires $ separation.
+# "stdio.h" and "stdlib.h" are already included in the generated files.
+
+#foo.h $ StackUsage_foo $ int a = 5; int b = 6; int c = 0; $ c = foo(a, a+b);
+$ StackUsage_memcmp $ char *mem1 = "blablabla"; int res = 0; $ res = memcmp(mem1, mem1, 8);
+#moo.h $ StackUsage_moo $ int a = 2; char b[2] = {'a','b'}; $ moo(a, b);
+#sum.h $ StackUsage_sum $ int res = 0; $ res = sum(88, 90);
+$ StackUsage_printf $ $ printf("I'm a test call\n");
+$ StackUsage_memcpy $ char* a = "PALTest"; char b[20] = {0}; $ memcpy(b, a, 8);
+
+
+List Finished!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/stackUsage/TestSuite/Template/template.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,31 @@
+int stackUsage_Template()
+{
+	char* stackArr = NULL;
+	int i = 0;
+	int stackUsageCounter = 0;
+	bool detectChange = false;
+	char borderArr[BORDER_ARRAY_SIZE]; //Used to mark the border of a stack frame.
+	for(i=0; i < BORDER_ARRAY_SIZE; ++i)
+	{
+		borderArr[i] = INIT_VALUE;
+	}
+	stackArr = paintStack();
+	Template_Func();
+	// The size of the second array is: 3*STACK_UNIT_SIZE.
+	// so we need to run over the array to detect the first changed byte.
+	// once we detect this byte, we can calculate the maximum stack usage.
+	for (i = 0 ; i < STACK_UNIT_NUM*STACK_UNIT_SIZE && !detectChange; ++i)
+	{
+		if(stackArr[i] != ((memPattern[i%PATTERN_SIZE]) ^ (i%MAX_CHAR_VALUE)))
+		{
+			detectChange = true;
+		}
+	}
+	stackUsageCounter = STACK_UNIT_NUM*STACK_UNIT_SIZE - i;
+	stackArr = stackArr + STACK_UNIT_NUM * STACK_UNIT_SIZE;
+	for (; stackArr != borderArr; ++stackArr)
+	{
+		++stackUsageCounter;
+	}
+	return stackUsageCounter;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/Utils/stackUsage/TestSuite/TestsGenarator.py	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,183 @@
+# This script responsible to generate C files.
+# The generated C files will create a TestSuite
+# for the Stack Usage analyzer.
+import os
+import shutil
+
+
+SCRIPTDIR = os.path.dirname(os.path.realpath(__file__))
+TEMPLATEFILE = os.path.join(SCRIPTDIR, 'Template', 'template.c')
+TESTSDIR = os.path.join(SCRIPTDIR, 'Tests')
+function_pointer_list = []
+STACK_UNIT_SIZE = 1024
+STACK_UNIT_NUM = 3
+
+
+def generate_functions(filename, includes, mainfunction, variables, targetcall):
+    generated = open(os.path.join(TESTSDIR, filename+'.c'), "a")
+    generated_header = open(os.path.join(TESTSDIR, filename+'.h'), "a")
+    template = open(TEMPLATEFILE, "r")
+    main_added = False
+    vars_added = False
+
+    # insert includes if exist
+    if len(includes) != 0:
+        for inc in includes.split(';'):
+            generated.write('#include \"' + inc + '\"\n')
+
+    # insert test main function
+    for line in template:
+        if main_added == True and vars_added == False:
+            if line.strip() == "{":
+                continue
+            # insert variables if exist
+            if len(variables) != 0:
+                for var in variables.split(';'):
+                    if len(var.strip(' ')) == 0:
+                        continue
+                    generated.write("\t"+var.strip(' ')+";\n")
+            generated.write(line)
+            vars_added = True
+            continue
+
+        if line.strip() == "int stackUsage_Template()":
+            generated_header.write("int "+mainfunction + "();\n")
+            generated.write("int "+mainfunction + "()\n{\n")
+            main_added = True
+            if mainfunction in function_pointer_list:
+                print "Error! This function already exist in the functions vector\n"
+                raise Exception('This function: "'+ mainfunction + '" is already exist in the functions vector')
+            function_pointer_list.append(mainfunction)
+        elif line.strip() == "Template_Func();":
+            generated.write("\t"+targetcall+"\n")
+
+        else:
+            generated.write(line)
+    generated.write('/***********************************************************************/\n')
+    generated.write("\n\n")
+    generated.write('/***********************************************************************/\n')
+    generated.close()
+    generated_header.close()
+    template.close()
+
+
+def generate_new_source_files(filename):
+    if os.path.exists(TESTSDIR):
+        shutil.rmtree(TESTSDIR)
+
+    os.mkdir(TESTSDIR)
+
+    generated_c = open(os.path.join(TESTSDIR, filename+'.c'), "w")
+    generated_h = open(os.path.join(TESTSDIR, filename+'.h'), "w")
+
+    generated_c.write('/* This file was generated automatically */\n')
+    generated_c.write("#include \""+filename+".h\"\n")
+    generated_c.write("\n\n")
+    generated_c.close()
+
+    generated_h.write('/**********************************************************************\n')
+    generated_h.write('* This file was generated automatically and it describes the generated\n')
+    generated_h.write('* Source file "'+filename+'.c" which contains stack usage test functions\n')
+    generated_h.write('* for the listed functions in the "TargetFunction.txt" file.\n')
+    generated_h.write('* Please do NOT edit these files (header and source) for requests please\n')
+    generated_h.write('* send an email to PAL team leader: Alex.Volinski@arm.com \n')
+    generated_h.write('**********************************************************************/\n\n')
+    generated_h.write("#ifndef _FUNCTIONS_VECTOR_H_\n")
+    generated_h.write("#define _FUNCTIONS_VECTOR_H_\n")
+    generated_h.write("#include <stdlib.h>\n")
+    generated_h.write("#include <stdio.h>\n")
+    generated_h.write("#include <stdbool.h>\n")
+    generated_h.write("#define STACK_UNIT_SIZE "+ str(STACK_UNIT_SIZE) +"\n")
+    generated_h.write("#define STACK_UNIT_NUM "+ str(STACK_UNIT_NUM) +"\n")
+    generated_h.write("char* paintStack();\n\n")
+    generated_h.close()
+
+
+def create_functions_struct(filename):
+
+    add_comma = False
+    generated_h = open(os.path.join(TESTSDIR, filename+'.h'), "a")
+    generated_h.write("\n\n#define BORDER_ARRAY_SIZE 32\n")
+    generated_h.write("#define FUNC_NUM "+ str(len(function_pointer_list)) +"\n")
+    generated_h.write("#define PATTERN_SIZE 4\n")
+    generated_h.write("#define INIT_VALUE 190\n")
+    generated_h.write("#define MAX_CHAR_VALUE 256\n")
+    generated_h.write("\ntypedef struct{\n\tint (*fp)();\n\tchar name[64];\n}functionNode;\n")
+    generated_h.write("\nstatic char memPattern[PATTERN_SIZE] = {0xDE, 0xAD, 0xFA, 0xCE};\n")
+    generated_h.write("\nstatic functionNode funcArray[FUNC_NUM] = {\n")
+
+    for func in function_pointer_list:
+        if add_comma:
+            generated_h.write(",\n")
+        generated_h.write('{'+func+",\""+func[len("StackUsage_"):]+"()\"}")
+        add_comma = True
+
+    generated_h.write("};\n\n")
+    generated_h.write("#endif //_FUNCTIONS_VECTOR_H_\n")
+    generated_h.close()
+
+
+def create_runner_source(vector_filename):
+    runner_c = open(os.path.join(TESTSDIR, 'TestSuiteRunner.c'), "w")
+
+    runner_c.write('/* This file was generated automatically */\n')
+    runner_c.write("#include \""+vector_filename+".h\"\n\n")
+    runner_c.write("void main()\n{\n")
+    runner_c.write("\tint i = 0;\n")
+    runner_c.write("\tfor (; i < FUNC_NUM ; ++i)\n\t{\n")
+    runner_c.write("\t\tprintf(\"%s function used: %d bytes in the stack\\n\", funcArray[i].name ,funcArray[i].fp());\n\t}\n")
+    runner_c.write("\tprintf(\"Test Finished!\\n\");\n")
+    runner_c.write("}\n")
+
+
+def create_runner_header():
+    generated_h = open(os.path.join(TESTSDIR, 'TestSuiteRunner.h'), "w")
+    generated_h.write('/**********************************************************************\n')
+    generated_h.write('* This file was generated automatically and it describes the generated\n')
+    generated_h.write('* Source file "TestSuiteRunner.c" which contains the test runner function\n')
+    generated_h.write('* for the listed functions in the "TargetFunction.txt" file.\n')
+    generated_h.write('* Please do NOT edit these files (header and source) for requests please\n')
+    generated_h.write('* send an email to PAL team \n')
+    generated_h.write('**********************************************************************/\n\n')
+    generated_h.write("#ifndef _TES_SUITE_RUNNER_H_\n")
+    generated_h.write("#define _TES_SUITE_RUNNER_H_\n")
+    generated_h.write("\nint TestSuiteRunner();\n\n")
+    generated_h.write("#endif //_TES_SUITE_RUNNER_H_\n")
+
+
+def generate_paint_stack():
+    runner_c = open(os.path.join(TESTSDIR, 'functionsVector.c'), "a")
+    runner_c.write("#pragma GCC diagnostic push\n")
+    runner_c.write("#pragma GCC diagnostic ignored \"-Wreturn-local-addr\"\n")
+    runner_c.write("/* We can not return the address of the (stackArr) directly, it will be NULL in run-time\n")
+    runner_c.write("*  Therefore new pointer (arrayPtr) required to hold the address of the (stackArr)*/\n")
+    runner_c.write("char* paintStack()\n{\n")
+    runner_c.write("\tchar* arrayPtr = NULL;\n")
+    runner_c.write("\tchar stackArr[STACK_UNIT_NUM*STACK_UNIT_SIZE] = {0};\n")
+    runner_c.write("\tint i = 0;\n")
+    runner_c.write("\tfor(i=0; i < STACK_UNIT_NUM*STACK_UNIT_SIZE; ++i)\n\t{\n")
+    runner_c.write("\t\t// Painting the stack with memory pattern (DEADFACE) XORed running index to make the stack more unique\n")
+    runner_c.write("\t\tstackArr[i] = memPattern[i%PATTERN_SIZE] ^ (i%MAX_CHAR_VALUE);\n\t}\n")
+    runner_c.write("\tarrayPtr = stackArr;\n")
+    runner_c.write("\treturn arrayPtr;\n}\n")
+    runner_c.write("#pragma GCC diagnostic pop\n\n")
+
+
+def main():
+    generate_new_source_files('functionsVector')
+    f = open('TargetFunctions.txt', 'r')
+    for line in f:
+        if line.strip() == 'List Finished!':
+            print "Code generation finished successfully"
+            break
+        if line[0] == "#" or line[0] == "\n":
+            continue
+        print "Reading new line: "+ line
+        list = line.strip().split('$')
+        generate_functions('functionsVector', list[0].strip(' '), list[1].strip(' '), list[2].strip(' '), list[3].strip(' '))
+    create_functions_struct('functionsVector')
+    create_runner_source('functionsVector')
+    generate_paint_stack()
+    create_runner_header()
+if __name__ == '__main__':
+    main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/mbed_lib.json	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,18 @@
+{
+    "name": "mbed-client-pal",
+    "config": {
+        "update-active-metadata-header-offset": null,
+        "rsa-required": false,
+        "pal-dns-api-version": {
+            "help": "Version of DNS API. This requires that PAL_NET_DNS_SUPPORT is defined to true",
+            "macro_name": "PAL_DNS_API_VERSION",
+            "value" : 1
+        }
+    },
+    "target_overrides": {
+        "MODULE_UBLOX_ODIN_W2": {
+            "rsa-required": true
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/pal_version.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright 2016, 2017 ARM Ltd.
+ *
+ * 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.
+ *******************************************************************************/
+#define PAL_VERSION_MAJOR 1
+#define PAL_VERSION_MINOR 2
+#define PAL_VERSION_PATCH 1
+#define PAL_VERSION PAL_VERSION_MAJOR##PAL_VERSION_MINOR##PAL_VERSION_PATCH
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/pal_version.h.in	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,6 @@
+#define PAL_VERSION_MAJOR @PAL_VERSION_MAJOR@
+#define PAL_VERSION_MINOR @PAL_VERSION_MINOR@
+#define PAL_VERSION_PATCH @PAL_VERSION_PATCH@
+#define PAL_VERSION       @PAL_VERSION@
+
+#cmakedefine PAL_USE_CMSIS
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-pal/valgrindSuppress.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,76 @@
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Cond
+   fun:internal_crc32
+   fun:pal_imagePrepare
+   fun:stateAdvance
+   fun:pal_imageInitAPI
+   fun:pal_update_xK
+   fun:TEST_pal_update_pal_update_writeSmallChunk_5b_
+   fun:UnityTestRunner
+   fun:TEST_pal_update_pal_update_writeSmallChunk_5b_run
+   fun:TEST_pal_update_GROUP_RUNNER
+   fun:TEST_pal_all_GROUPS_RUNNER
+   fun:UnityMain
+   fun:palTestMain
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Cond
+   fun:internal_crc32
+   fun:pal_imagePrepare
+   fun:multiWriteMultiRead
+   fun:pal_imageInitAPI
+   fun:TEST_pal_update_pal_update_4k_write_1k_4_times_
+   fun:UnityTestRunner
+   fun:TEST_pal_update_pal_update_4k_write_1k_4_times_run
+   fun:TEST_pal_update_GROUP_RUNNER
+   fun:TEST_pal_all_GROUPS_RUNNER
+   fun:UnityMain
+   fun:palTestMain
+   fun:palAllTestMain
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Param
+   write(buf)
+   obj:/lib/x86_64-linux-gnu/libc-2.23.so
+   fun:_IO_file_write@@GLIBC_2.2.5
+   fun:new_do_write
+   fun:_IO_do_write@@GLIBC_2.2.5
+   fun:_IO_file_close_it@@GLIBC_2.2.5
+   fun:fclose@@GLIBC_2.2.5
+   fun:pal_plat_fsFclose
+   fun:pal_fsFclose
+   fun:FilesTests
+   fun:TEST_pal_fileSystem_FilesTests_
+   fun:UnityTestRunner
+   fun:TEST_pal_fileSystem_FilesTests_run
+   fun:TEST_pal_fileSystem_GROUP_RUNNER
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   match-leak-kinds: possible
+   fun:calloc
+   fun:allocate_dtv
+   fun:_dl_allocate_tls
+   fun:allocate_stack
+   fun:pthread_create@@GLIBC_2.2.5
+   fun:pal_plat_osThreadCreate
+   fun:pal_osThreadCreateWithAlloc
+   ...
+}
+
+{
+   <insert_a_suppression_name_here>
+   Memcheck:Leak
+   match-leak-kinds: reachable
+   fun:malloc
+   fun:pal_plat_osThreadCreate
+   fun:pal_osThreadCreateWithAlloc
+   ...
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-randlib/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+linux/*
+test/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-randlib/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+Unless specifically indicated otherwise in a file, files are licensed
+under the Apache 2.0 license, as can be found in: apache-2.0.txt
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-randlib/apache-2.0.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,56 @@
+
+
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+    You must give any other recipients of the Work or Derivative Works a copy of this License; and
+    You must cause any modified files to carry prominent notices stating that You changed the files; and
+    You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+    If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+    You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-randlib/mbed-client-randlib/platform/arm_hal_random.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifndef ARM_HAL_RANDOM_H_
+#define ARM_HAL_RANDOM_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * \brief This function performs Random number driver init.
+ */
+extern void arm_random_module_init(void);
+/**
+ * \brief Get random library seed value.
+ *
+ * This function should return as random a value as possible, using
+ * hardware sources. Repeated calls should return different values if
+ * at all possible.
+ */
+extern uint32_t arm_random_seed_get(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* ARM_HAL_RANDOM_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-randlib/mbed-client-randlib/randLIB.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+ * \file randLIB.h
+ * \brief Pseudo Random Library API:
+ *
+ *
+ * \section net-boot Network Bootstrap Control API:
+ *  - randLIB_seed_random(), Set seed for pseudo random
+ *  - randLIB_get_8bit(), Generate 8-bit random number
+ *  - randLIB_get_16bit(),Generate 16-bit random number
+ *  - randLIB_get_32bit(),Generate 32-bit random number
+ *  - randLIB_get_n_bytes_random(), Generate n-bytes random numbers
+ *
+ */
+
+#ifndef RANDLIB_H_
+#define RANDLIB_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This library is made for getting random numbers for Timing needs in protocols.
+ *
+ * **not safe to use for security or cryptographic operations.**
+ *
+ */
+
+
+/**
+  * \brief Init seed for Pseudo Random.
+  *
+  * Makes call(s) to the platform's arm_random_seed_get() to seed the
+  * pseudo-random generator.
+  *
+  * \return None
+  *
+  */
+extern void randLIB_seed_random(void);
+
+/**
+ * \brief Update seed for pseudo-random generator
+ *
+ * Adds seed information to existing generator, to perturb the
+ * sequence.
+ * \param seed 64 bits of data to add to the seed.
+ */
+extern void randLIB_add_seed(uint64_t seed);
+
+/**
+  * \brief Generate 8-bit random number.
+  *
+  * \param None
+  * \return 8-bit random number
+  *
+  */
+extern uint8_t randLIB_get_8bit(void);
+
+/**
+  * \brief Generate 16-bit random number.
+  *
+  * \param None
+  * \return 16-bit random number
+  *
+  */
+extern uint16_t randLIB_get_16bit(void);
+
+/**
+  * \brief Generate 32-bit random number.
+  *
+  * \param None
+  * \return 32-bit random number
+  *
+  */
+extern uint32_t randLIB_get_32bit(void);
+
+/**
+  * \brief Generate 64-bit random number.
+  *
+  * \param None
+  * \return 64-bit random number
+  *
+  */
+extern uint64_t randLIB_get_64bit(void);
+
+/**
+  * \brief Generate n-bytes random numbers.
+  *
+  * \param data_ptr pointer where random will be stored
+  * \param count how many bytes need random
+  *
+  * \return data_ptr
+  */
+extern void *randLIB_get_n_bytes_random(void *data_ptr, uint8_t count);
+
+/**
+  * \brief Generate a random number within a range.
+  *
+  * The result is linearly distributed in the range [min..max], inclusive.
+  *
+  * \param min minimum value that can be generated
+  * \param max maximum value that can be generated
+  */
+uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max);
+
+/**
+  * \brief Randomise a base 32-bit number by a jitter factor
+  *
+  * The result is linearly distributed in the jitter range, which is expressed
+  * as fixed-point unsigned 1.15 values. For example, to produce a number in the
+  * range [0.75 * base, 1.25 * base], set min_factor to 0x6000 and max_factor to
+  * 0xA000.
+  *
+  * Result is clamped to 0xFFFFFFFF if it overflows.
+  *
+  * \param base The base 32-bit value
+  * \param min_factor The minimum value for the random factor
+  * \param max_factor The maximum value for the random factor
+  */
+uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor);
+
+#ifdef RANDLIB_PRNG
+/* \internal Reset the PRNG state to zero (invalid) */
+void randLIB_reset(void);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* RANDLIB_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client-randlib/source/randLIB.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include <stdint.h>
+#include <limits.h>
+#include "randLIB.h"
+#include "platform/arm_hal_random.h"
+
+/**
+ * This library is made for getting random numbers for timing needs in
+ * protocols, plus to generate dynamic ports, random IDs etc.
+ *
+ * **not safe to use for security or cryptographic operations.**
+ *
+ * Base implementation is a pseudo-RNG, but may also use a system RNG.
+ * Replay of sequence by reseeding is not possible.
+ *
+ * Base pseudo-RNG is the xoroshiro128+ generator by Marsaglia, Blackman and
+ * Vigna:
+ *
+ * http://xoroshiro.di.unimi.it/
+ *
+ * Certainly not the fastest for 32-bit or smaller platforms, but speed
+ * is not critical. None of the long operations in the core are actually hard,
+ * unlike the divisions and multiplies in the utility functions below, where we
+ * do try to keep the operations narrow.
+ */
+
+/* On some platforms, read from a system RNG, rather than use our own */
+/* RANDLIB_PRNG disables this and forces use of the PRNG (useful for test only?) */
+#ifndef RANDLIB_PRNG
+#ifdef __linux
+#define RANDOM_DEVICE "/dev/urandom"
+#endif
+#endif // RANDLIB_PRNG
+
+/* RAM usage - 16 bytes of state (or a FILE * pointer and underlying FILE, which
+ * will include a buffer) */
+#ifdef RANDOM_DEVICE
+#include <stdio.h>
+static FILE *random_file;
+#else
+static uint64_t state[2];
+#endif
+
+#ifdef RANDLIB_PRNG
+void randLIB_reset(void)
+{
+    state[0] = 0;
+    state[1] = 0;
+}
+#endif
+
+#ifndef RANDOM_DEVICE
+static inline uint64_t rol(uint64_t n, int bits)
+{
+    return (n << bits) | (n >> (64 - bits));
+}
+
+/* Lower-quality generator used only for initial seeding, if platform
+ * isn't returning multiple seeds itself. Multiplies are rather heavy
+ * for lower-end platforms, but this is initialisation only.
+ */
+static uint64_t splitmix64(uint64_t *seed)
+{
+    uint64_t z = (*seed += UINT64_C(0x9E3779B97F4A7C15));
+    z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9);
+    z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
+    return z ^ (z >> 31);
+}
+#endif // RANDOM_DEVICE
+
+void randLIB_seed_random(void)
+{
+#ifdef RANDOM_DEVICE
+    if (!random_file) {
+        random_file = fopen(RANDOM_DEVICE, "rb");
+    }
+#else
+    arm_random_module_init();
+
+    /* We exclusive-OR with the current state, in case they make this call
+     * multiple times,or in case someone has called randLIB_add_seed before
+     * this. We don't want to potentially lose entropy.
+     */
+
+    /* Spell out expressions so we get known ordering of 4 seed calls */
+    uint64_t s = (uint64_t) arm_random_seed_get() << 32;
+    state[0] ^= ( s | arm_random_seed_get());
+
+    s = (uint64_t) arm_random_seed_get() << 32;
+    state[1] ^= s | arm_random_seed_get();
+
+    /* This check serves to both to stir the state if the platform is returning
+     * constant seeding values, and to avoid the illegal all-zero state.
+     */
+    if (state[0] == state[1]) {
+        randLIB_add_seed(state[0]);
+    }
+#endif // RANDOM_DEVICE
+}
+
+void randLIB_add_seed(uint64_t seed)
+{
+#ifndef RANDOM_DEVICE
+    state[0] ^= splitmix64(&seed);
+    state[1] ^= splitmix64(&seed);
+    /* This is absolutely necessary, but I challenge you to add it to line coverage */
+    if (state[1] == 0 && state[0] == 0) {
+        state[0] = 1;
+    }
+#else
+    (void)seed;
+#endif
+}
+
+uint8_t randLIB_get_8bit(void)
+{
+    uint64_t r = randLIB_get_64bit();
+    return (uint8_t) (r >> 56);
+}
+
+uint16_t randLIB_get_16bit(void)
+{
+    uint64_t r = randLIB_get_64bit();
+    return (uint16_t) (r >> 48);
+}
+
+uint32_t randLIB_get_32bit(void)
+{
+    uint64_t r = randLIB_get_64bit();
+    return (uint32_t) (r >> 32);
+}
+
+
+uint64_t randLIB_get_64bit(void)
+{
+#ifdef RANDOM_DEVICE
+    if (!random_file) {
+        return 0;
+    }
+    uint64_t result;
+    if (fread(&result, sizeof result, 1, random_file) != 1) {
+        result = 0;
+    }
+    return result;
+#else
+    const uint64_t s0 = state[0];
+    uint64_t s1 = state[1];
+    const uint64_t result = s0 + s1;
+
+    s1 ^= s0;
+    state[0] = rol(s0, 55) ^ s1 ^ (s1 << 14);
+    state[1] = rol(s1, 36);
+
+    return result;
+#endif
+}
+
+void *randLIB_get_n_bytes_random(void *ptr, uint8_t count)
+{
+    uint8_t *data_ptr = ptr;
+    uint64_t r = 0;
+    for (uint_fast8_t i = 0; i < count; i++) {
+        /* Take 8 bytes at a time */
+        if (i % 8 == 0) {
+            r = randLIB_get_64bit();
+        } else {
+            r >>= 8;
+        }
+        data_ptr[i] = (uint8_t) r;
+    }
+    return data_ptr;
+}
+
+uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max)
+{
+    /* This special case is potentially common, particularly in this routine's
+     * first user (Trickle), so worth catching immediately */
+    if (min == max) {
+        return min;
+    }
+
+#if UINT_MAX >= 0xFFFFFFFF
+    const unsigned int rand_max = 0xFFFFFFFFu; // will use rand32
+#else
+    const unsigned int rand_max = 0xFFFFu; // will use rand16
+
+    /* 16-bit arithmetic below fails in this extreme case; we can optimise it */
+    if (max - min == 0xFFFF) {
+        return randLIB_get_16bit();
+    }
+#endif
+
+    /* We get rand_max values from rand16 or 32() in the range [0..rand_max-1], and
+     * need to divvy them up into the number of values we need. And reroll any
+     * odd values off the end as we insist every value having equal chance.
+     *
+     * Using the range [0..rand_max-1] saves long division on the band
+     * calculation - it means rand_max ends up always being rerolled.
+     *
+     * Eg, range(1,2), rand_max = 0xFFFF:
+     * We have 2 bands of size 0x7FFF (0xFFFF/2).
+     *
+     * We roll: 0x0000..0x7FFE -> 1
+     *          0x7FFF..0xFFFD -> 2
+     *          0xFFFE..0xFFFF -> reroll
+     * (calculating band size as 0x10000/2 would have avoided the reroll cases)
+     *
+     * Eg, range(1,3), rand_max = 0xFFFFFFFF:
+     * We have 3 bands of size 0x55555555 (0xFFFFFFFF/3).
+     *
+     * We roll: 0x00000000..0x555555554 -> 1
+     *          0x55555555..0xAAAAAAAA9 -> 2
+     *          0xAAAAAAAA..0xFFFFFFFFE -> 3
+     *          0xFFFFFFFF              -> reroll
+     *
+     * (Bias problem clearly pretty insignificant there, but gets worse as
+     * range increases).
+     */
+    const unsigned int values_needed = max + 1 - min;
+    /* Avoid the need for long division, at the expense of fractionally
+     * increasing reroll chance. */
+    const unsigned int band_size = rand_max / values_needed;
+    const unsigned int top_of_bands = band_size * values_needed;
+    unsigned int result;
+    do {
+#if UINT_MAX > 0xFFFF
+        result = randLIB_get_32bit();
+#else
+        result = randLIB_get_16bit();
+#endif
+    } while (result >= top_of_bands);
+
+    return min + (uint16_t)(result / band_size);
+}
+
+uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor)
+{
+    uint16_t random_factor = randLIB_get_random_in_range(min_factor, max_factor);
+
+    /* 32x16-bit long multiplication, to get 48-bit result */
+    uint32_t hi = (base >> 16) * random_factor;
+    uint32_t lo = (base & 0xFFFF) * random_factor;
+    /* Add halves, and take top 32 bits of 48-bit result */
+    uint32_t res = hi + (lo >> 16);
+
+    /* Randomisation factor is *2^15, so need to shift up 1 more bit, avoiding overflow */
+    if (res & 0x80000000) {
+        res = 0xFFFFFFFF;
+    } else {
+        res = (res << 1) | ((lo >> 15) & 1);
+    }
+
+    return res;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,9 @@
+config/*
+docs/*
+doxygen/*
+test/*
+yotta_modules/*
+yotta_targets/*
+build/*
+test_modules/*
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/DOXYGEN_FRONTPAGE.md	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,13 @@
+mbed Client API 
+================
+
+This is the Doxygen generated API documentation of mbed Client. See the [Files](files.html) section to find the documentation about specific API. It should be used together with the [mbed Client Guide](https://docs.mbed.com/docs/mbed-client-guide/en/latest/)
+hosted in http://docs.mbed.com.
+
+The mbed Client high-level APIs allow mbed OS developers to create applications with LwM2M features as described in the [Lightweight Machine to Machine Technical Specification](http://technical.openmobilealliance.org/Technical/technical-information/release-program/current-releases/oma-lightweightm2m-v1-0):
+
+- Manage devices on mbed Device Server.
+- Securely communicate with internet services over the industry standard TLS/DTLS.
+- Fully control the endpoint and application logic.
+
+The API is written in C++ to allow quick application development.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,202 @@
+Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   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.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/doxygen/mbedclient_doxy	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1850 @@
+# Doxyfile 1.8.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should 
+# identify the project. Note that if you do not use Doxywizard you need 
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME           = mbed-client
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description 
+# for a project that appears at the top of each page and should give viewer 
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = "mbed Client C++ library"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is 
+# included in the documentation. The maximum height of the logo should not 
+# exceed 55 pixels and the maximum width should not exceed 200 pixels. 
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO           = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = ../docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, 
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English 
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, 
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip. Note that you specify absolute paths here, but also 
+# relative paths, which will be relative from the directory where doxygen is 
+# started.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful if your file system 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 16
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only). 
+# A mapping has the form "name=value". For example adding 
+# "class=itcl::class" will allow you to use the command class in the 
+# itcl::class meaning.
+
+TCL_SUBST              = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it 
+# parses. With this tag you can assign which parser to use for a given 
+# extension. Doxygen has a built-in mapping, but you can override or extend it 
+# using this tag. The format is ext=language, where ext is a file extension, 
+# and language is one of the parsers supported by doxygen: IDL, Java, 
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, 
+# C++. For instance to make doxygen treat .inc files as Fortran files (default 
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note 
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the 
+# files are not read by doxygen.
+
+EXTENSION_MAPPING      = 
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all 
+# comments according to the Markdown format, which allows for more readable 
+# documentation. See http://daringfireball.net/projects/markdown/ for details. 
+# The output of markdown processing is further processed by doxygen, so you 
+# can mix doxygen, HTML, and XML commands with Markdown formatting. 
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes, 
+# or namespaces to their corresponding documentation. Such a link can be 
+# prevented in individual cases by by putting a % sign in front of the word or 
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also makes the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to 
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES (the
+# default) will make doxygen replace the get and set methods by a property in
+# the documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and 
+# unions are shown inside the group in which they are included (e.g. using 
+# @ingroup) instead of on a separate page (for HTML and Man pages) or 
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and 
+# unions with only public data fields will be shown inline in the documentation 
+# of the scope in which they are defined (i.e. file, namespace, or group 
+# documentation), provided this scope is documented. If set to NO (the default), 
+# structs, classes, and unions are shown on a separate page (for HTML and Man 
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to 
+# determine which symbols to keep in memory and which to flush to disk. 
+# When the cache is full, less often used symbols will be written to disk. 
+# For small to medium size projects (<1000 input files) the default value is 
+# probably good enough. For larger projects a too small cache size can cause 
+# doxygen to be busy swapping symbols to and from disk most of the time 
+# causing a significant performance penalty. 
+# If the system has enough physical memory increasing the cache will improve the 
+# performance by keeping more symbols in memory. Note that the value works on 
+# a logarithmic scale so increasing the size by one will roughly double the 
+# memory usage. The cache size is given by this formula: 
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE      = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be 
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given 
+# their name and scope. Since this can be an expensive process and often the 
+# same symbol appear multiple times in the code, doxygen keeps a cache of 
+# pre-resolved symbols. If the cache is too small doxygen will become slower. 
+# If the cache is too large, memory is wasted. The cache size is given by this 
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal 
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = NO
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = YES
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen 
+# will list include files with double quotes in the documentation 
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen 
+# will sort the (brief and detailed) documentation of class members so that 
+# constructors and destructors are listed first. If set to NO (the default) 
+# the constructors will appear in the respective orders defined by 
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. 
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO 
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. 
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to 
+# do proper type resolution of all parameters of a function it will reject a 
+# match between the prototype and the implementation of a member function even 
+# if there is only one candidate or it is obvious which candidate to choose 
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen 
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or macro consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and macros in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 18
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. 
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page.  This will remove the Namespaces entry from the Quick Index 
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed 
+# by doxygen. The layout file controls the global structure of the generated 
+# output files in an output format independent way. To create the layout file 
+# that represents doxygen's defaults, run doxygen with the -l option. 
+# You can optionally specify a file name after the option, if omitted 
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE            = 
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files 
+# containing the references data. This must be a list of .bib files. The 
+# .bib extension is automatically appended if omitted. Using this command 
+# requires the bibtex tool to be installed. See also 
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style 
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this 
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES         = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = ../mbed-client
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh 
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py 
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.d \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.idl \
+                         *.odl \
+                         *.cs \
+                         *.php \
+                         *.php3 \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.f90 \
+                         *.f \
+                         *.for \
+                         *.vhd \
+                         *.vhdl
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag. 
+# Note that relative paths are relative to the directory from which doxygen is 
+# run.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or 
+# directories that are symbolic links (a Unix file system feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = */config/*
+EXCLUDE_PATTERNS       += */docs/*
+EXCLUDE_PATTERNS       += */doxygen/*
+EXCLUDE_PATTERNS       += */source/*
+EXCLUDE_PATTERNS       += */test/*
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty or if 
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file 
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) 
+# and it is also possible to disable source filtering for a specific pattern 
+# using *.ext= (so without naming a filter). This option only has effect when 
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS = 
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 
+# link to the source code.  Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header. Note that when using a custom header you are responsible  
+# for the proper inclusion of any scripts and style sheets that doxygen 
+# needs, which is dependent on the configuration options used. 
+# It is advised to generate a default header using "doxygen -w html 
+# header.html footer.html stylesheet.css YourConfigFile" and then modify 
+# that header. Note that the header is subject to change so you typically 
+# have to redo this when upgrading to a newer version of doxygen or when 
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If left blank doxygen will 
+# generate a default style sheet. Note that it is recommended to use 
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this 
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET        = 
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional 
+# user-defined cascading style sheet that is included after the standard 
+# style sheets created by doxygen. Using this option one can overrule 
+# certain style aspects. This is preferred over using HTML_STYLESHEET 
+# since it does not replace the standard style sheet and is therefor more 
+# robust against future updates. Doxygen will copy the style sheet file to 
+# the output directory.
+
+HTML_EXTRA_STYLESHEET  = 
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or 
+# other source files which should be copied to the HTML output directory. Note 
+# that these files will be copied to the base HTML output directory. Use the 
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these 
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that 
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES       = 
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. 
+# Doxygen will adjust the colors in the style sheet and background images 
+# according to this color. Hue is specified as an angle on a colorwheel, 
+# see http://en.wikipedia.org/wiki/Hue for more information. 
+# For instance the value 0 represents red, 60 is yellow, 120 is green, 
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. 
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of 
+# the colors in the HTML output. For a value of 0 the output will use 
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to 
+# the luminance component of the colors in the HTML output. Values below 
+# 100 gradually make the output lighter, whereas values above 100 make 
+# the output darker. The value divided by 100 is the actual gamma applied, 
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, 
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML 
+# page will contain the date and time when the page was generated. Setting 
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of 
+# entries shown in the various tree structured indices initially; the user 
+# can expand and collapse entries dynamically later on. Doxygen will expand 
+# the tree to such a level that at most the specified number of entries are 
+# visible (unless a fully collapsed tree already exceeds this amount). 
+# So setting the number of entries 1 will produce a full collapsed tree by 
+# default. 0 is a special value representing an infinite number of entries 
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup. 
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html 
+# for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely 
+# identify the documentation publisher. This should be a reverse domain-name 
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING 
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file 
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and 
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated 
+# that can be used as input for Qt's qhelpgenerator to generate a 
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can 
+# be used to specify the file name of the resulting .qch file. 
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               = 
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to 
+# add. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   = 
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the 
+# custom filter to add. For more information please see 
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> 
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  = 
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this 
+# project's 
+# filter section matches. 
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> 
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  = 
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can 
+# be used to specify the location of Qt's qhelpgenerator. 
+# If non-empty doxygen will try to run qhelpgenerator on the generated 
+# .qhp file.
+
+QHG_LOCATION           = 
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files  
+# will be generated, which together with the HTML files, form an Eclipse help 
+# plugin. To install this plugin and make it available under the help contents 
+# menu in Eclipse, the contents of the directory containing the HTML and XML 
+# files needs to be copied into the plugins directory of eclipse. The name of 
+# the directory within the plugins directory should be the same as 
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before 
+# the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin 
+# the directory name containing the HTML and XML files should also have 
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) 
+# at top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it. Since the tabs have the same information as the 
+# navigation tree you can set this option to NO if you already set 
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 
+# structure should be generated to display hierarchical information. 
+# If the tag value is set to YES, a side panel will be generated 
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). 
+# Windows users are probably better off using the HTML help feature. 
+# Since the tree basically has the same information as the tab index you 
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values 
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML 
+# documentation. Note that a value of 0 will completely suppress the enum 
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open 
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images 
+# generated for formulas are transparent PNGs. Transparent PNGs are 
+# not supported properly for IE 6.0, but are supported on all modern browsers. 
+# Note that when changing this option you need to delete any form_*.png files 
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax 
+# (see http://www.mathjax.org) which uses client side Javascript for the 
+# rendering instead of using prerendered bitmaps. Use this if you do not 
+# have LaTeX installed or if you want to formulas look prettier in the HTML 
+# output. When enabled you may also need to install MathJax separately and 
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you need to specify the location relative to the 
+# HTML output directory using the MATHJAX_RELPATH option. The destination 
+# directory should contain the MathJax.js script. For instance, if the mathjax 
+# directory is located at the same level as the HTML output directory, then 
+# MATHJAX_RELPATH should be ../mathjax. The default value points to 
+# the MathJax Content Delivery Network so you can quickly see the result without 
+# installing MathJax.  However, it is strongly recommended to install a local 
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension 
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS     = 
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box 
+# for the HTML output. The underlying search engine uses javascript 
+# and DHTML and should work on any modern browser. Note that when using 
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets 
+# (GENERATE_DOCSET) there is already a search function so this one should 
+# typically be disabled. For large projects the javascript based search engine 
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be 
+# implemented using a PHP enabled web server instead of at the web client 
+# using Javascript. Doxygen will generate the search PHP script and index 
+# file to put on the web server. The advantage of the server 
+# based approach is that it scales better to large projects and allows 
+# full text search. The disadvantages are that it is more difficult to setup 
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name. 
+# Note that when enabling USE_PDFLATEX this option is only used for 
+# generating bitmaps for formulas in the HTML output, but not in the 
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for 
+# the generated latex document. The footer should contain everything after 
+# the last chapter. If it is left blank doxygen will generate a 
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include 
+# source code with syntax highlighting in the LaTeX output. 
+# Note that which sources are shown also depends on other settings 
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the 
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See 
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition that 
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all references to function-like macros 
+# that are alone on a line, have an all uppercase name, and do not end with a 
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each 
+# tag file the location of the external documentation should be added. The 
+# format of a tag file without this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths 
+# or URLs. Note that each tag file must have a unique name (where the name does 
+# NOT include the path). If a tag file is not located in the directory in which 
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option also works with HAVE_DOT disabled, but it is recommended to 
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = NO
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is 
+# allowed to run in parallel. When set to 0 (the default) doxygen will 
+# base this on the number of processors available in the system. You can set it 
+# explicitly to a value larger than 0 to get control over the balance 
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS        = 0
+
+# By default doxygen will use the Helvetica font for all dot files that 
+# doxygen generates. When you want a differently looking font you can specify 
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find 
+# the font, which can be done by putting it in a standard location or by setting 
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the 
+# directory containing the font.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. 
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the Helvetica font. 
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to 
+# set the path where dot can find it.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside 
+# the class node. If there are many fields or methods and many nodes the 
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS 
+# threshold limits the number of items for each type to make the size more 
+# managable. Set this to 0 for no limit. Note that the threshold may be 
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = YES
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include 
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are svg, png, jpg, or gif. 
+# If left blank png will be used. If you choose svg you need to set 
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files 
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to 
+# enable generation of interactive SVG images that allow zooming and panning. 
+# Note that this requires a modern browser other than Internet Explorer. 
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you 
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files 
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG        = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that 
+# contain msc files that are included in the documentation (see the 
+# \mscfile command).
+
+MSCFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 44
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, because dot on Windows does not 
+# seem to support this out of the box. Warning: Depending on the platform used, 
+# enabling this option may lead to badly anti-aliased labels on the edges of 
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+test/*
+unittest/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+Unless specifically indicated otherwise in a file, files are licensed
+under the Apache 2.0 license, as can be found in: apache-2.0.txt
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/README.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,5 @@
+The mbed Device C Client Library provides a simple and efficient way to create mbed Device Client in 
+C.
+
+Applications not using mbed-coap via mbedOS should add mbed-coap library either via mbed-coap.lib or via other
+applicable means.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/apache-2.0.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,56 @@
+
+
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+    You must give any other recipients of the Work or Derivative Works a copy of this License; and
+    You must cause any modified files to carry prominent notices stating that You changed the files; and
+    You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+    If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+    You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/doxygen/client-c_doxy	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1846 @@
+# Doxyfile 1.8.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should 
+# identify the project. Note that if you do not use Doxywizard you need 
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME           = client-c
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description 
+# for a project that appears at the top of each page and should give viewer 
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = "mbed Client C library"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is 
+# included in the documentation. The maximum height of the logo should not 
+# exceed 55 pixels and the maximum width should not exceed 200 pixels. 
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO           = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = ../docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, 
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English 
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, 
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip. Note that you specify absolute paths here, but also 
+# relative paths, which will be relative from the directory where doxygen is 
+# started.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful if your file system 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 16
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only). 
+# A mapping has the form "name=value". For example adding 
+# "class=itcl::class" will allow you to use the command class in the 
+# itcl::class meaning.
+
+TCL_SUBST              = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it 
+# parses. With this tag you can assign which parser to use for a given 
+# extension. Doxygen has a built-in mapping, but you can override or extend it 
+# using this tag. The format is ext=language, where ext is a file extension, 
+# and language is one of the parsers supported by doxygen: IDL, Java, 
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, 
+# C++. For instance to make doxygen treat .inc files as Fortran files (default 
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note 
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the 
+# files are not read by doxygen.
+
+EXTENSION_MAPPING      = 
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all 
+# comments according to the Markdown format, which allows for more readable 
+# documentation. See http://daringfireball.net/projects/markdown/ for details. 
+# The output of markdown processing is further processed by doxygen, so you 
+# can mix doxygen, HTML, and XML commands with Markdown formatting. 
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes, 
+# or namespaces to their corresponding documentation. Such a link can be 
+# prevented in individual cases by by putting a % sign in front of the word or 
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also makes the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to 
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES (the
+# default) will make doxygen replace the get and set methods by a property in
+# the documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and 
+# unions are shown inside the group in which they are included (e.g. using 
+# @ingroup) instead of on a separate page (for HTML and Man pages) or 
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and 
+# unions with only public data fields will be shown inline in the documentation 
+# of the scope in which they are defined (i.e. file, namespace, or group 
+# documentation), provided this scope is documented. If set to NO (the default), 
+# structs, classes, and unions are shown on a separate page (for HTML and Man 
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to 
+# determine which symbols to keep in memory and which to flush to disk. 
+# When the cache is full, less often used symbols will be written to disk. 
+# For small to medium size projects (<1000 input files) the default value is 
+# probably good enough. For larger projects a too small cache size can cause 
+# doxygen to be busy swapping symbols to and from disk most of the time 
+# causing a significant performance penalty. 
+# If the system has enough physical memory increasing the cache will improve the 
+# performance by keeping more symbols in memory. Note that the value works on 
+# a logarithmic scale so increasing the size by one will roughly double the 
+# memory usage. The cache size is given by this formula: 
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE      = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be 
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given 
+# their name and scope. Since this can be an expensive process and often the 
+# same symbol appear multiple times in the code, doxygen keeps a cache of 
+# pre-resolved symbols. If the cache is too small doxygen will become slower. 
+# If the cache is too large, memory is wasted. The cache size is given by this 
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal 
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = NO
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = YES
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen 
+# will list include files with double quotes in the documentation 
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen 
+# will sort the (brief and detailed) documentation of class members so that 
+# constructors and destructors are listed first. If set to NO (the default) 
+# the constructors will appear in the respective orders defined by 
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. 
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO 
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. 
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to 
+# do proper type resolution of all parameters of a function it will reject a 
+# match between the prototype and the implementation of a member function even 
+# if there is only one candidate or it is obvious which candidate to choose 
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen 
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or macro consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and macros in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 18
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. 
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page.  This will remove the Namespaces entry from the Quick Index 
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed 
+# by doxygen. The layout file controls the global structure of the generated 
+# output files in an output format independent way. To create the layout file 
+# that represents doxygen's defaults, run doxygen with the -l option. 
+# You can optionally specify a file name after the option, if omitted 
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE            = 
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files 
+# containing the references data. This must be a list of .bib files. The 
+# .bib extension is automatically appended if omitted. Using this command 
+# requires the bibtex tool to be installed. See also 
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style 
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this 
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES         = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = ../nsdl-c
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh 
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py 
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.d \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.idl \
+                         *.odl \
+                         *.cs \
+                         *.php \
+                         *.php3 \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.f90 \
+                         *.f \
+                         *.for \
+                         *.vhd \
+                         *.vhdl
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag. 
+# Note that relative paths are relative to the directory from which doxygen is 
+# run.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or 
+# directories that are symbolic links (a Unix file system feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty or if 
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file 
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) 
+# and it is also possible to disable source filtering for a specific pattern 
+# using *.ext= (so without naming a filter). This option only has effect when 
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS = 
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 
+# link to the source code.  Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header. Note that when using a custom header you are responsible  
+# for the proper inclusion of any scripts and style sheets that doxygen 
+# needs, which is dependent on the configuration options used. 
+# It is advised to generate a default header using "doxygen -w html 
+# header.html footer.html stylesheet.css YourConfigFile" and then modify 
+# that header. Note that the header is subject to change so you typically 
+# have to redo this when upgrading to a newer version of doxygen or when 
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If left blank doxygen will 
+# generate a default style sheet. Note that it is recommended to use 
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this 
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET        = 
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional 
+# user-defined cascading style sheet that is included after the standard 
+# style sheets created by doxygen. Using this option one can overrule 
+# certain style aspects. This is preferred over using HTML_STYLESHEET 
+# since it does not replace the standard style sheet and is therefor more 
+# robust against future updates. Doxygen will copy the style sheet file to 
+# the output directory.
+
+HTML_EXTRA_STYLESHEET  = 
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or 
+# other source files which should be copied to the HTML output directory. Note 
+# that these files will be copied to the base HTML output directory. Use the 
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these 
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that 
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES       = 
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. 
+# Doxygen will adjust the colors in the style sheet and background images 
+# according to this color. Hue is specified as an angle on a colorwheel, 
+# see http://en.wikipedia.org/wiki/Hue for more information. 
+# For instance the value 0 represents red, 60 is yellow, 120 is green, 
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. 
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of 
+# the colors in the HTML output. For a value of 0 the output will use 
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to 
+# the luminance component of the colors in the HTML output. Values below 
+# 100 gradually make the output lighter, whereas values above 100 make 
+# the output darker. The value divided by 100 is the actual gamma applied, 
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, 
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML 
+# page will contain the date and time when the page was generated. Setting 
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of 
+# entries shown in the various tree structured indices initially; the user 
+# can expand and collapse entries dynamically later on. Doxygen will expand 
+# the tree to such a level that at most the specified number of entries are 
+# visible (unless a fully collapsed tree already exceeds this amount). 
+# So setting the number of entries 1 will produce a full collapsed tree by 
+# default. 0 is a special value representing an infinite number of entries 
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup. 
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html 
+# for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely 
+# identify the documentation publisher. This should be a reverse domain-name 
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING 
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file 
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and 
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated 
+# that can be used as input for Qt's qhelpgenerator to generate a 
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can 
+# be used to specify the file name of the resulting .qch file. 
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               = 
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to 
+# add. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   = 
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the 
+# custom filter to add. For more information please see 
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> 
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  = 
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this 
+# project's 
+# filter section matches. 
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> 
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  = 
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can 
+# be used to specify the location of Qt's qhelpgenerator. 
+# If non-empty doxygen will try to run qhelpgenerator on the generated 
+# .qhp file.
+
+QHG_LOCATION           = 
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files  
+# will be generated, which together with the HTML files, form an Eclipse help 
+# plugin. To install this plugin and make it available under the help contents 
+# menu in Eclipse, the contents of the directory containing the HTML and XML 
+# files needs to be copied into the plugins directory of eclipse. The name of 
+# the directory within the plugins directory should be the same as 
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before 
+# the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin 
+# the directory name containing the HTML and XML files should also have 
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) 
+# at top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it. Since the tabs have the same information as the 
+# navigation tree you can set this option to NO if you already set 
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 
+# structure should be generated to display hierarchical information. 
+# If the tag value is set to YES, a side panel will be generated 
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). 
+# Windows users are probably better off using the HTML help feature. 
+# Since the tree basically has the same information as the tab index you 
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values 
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML 
+# documentation. Note that a value of 0 will completely suppress the enum 
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open 
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images 
+# generated for formulas are transparent PNGs. Transparent PNGs are 
+# not supported properly for IE 6.0, but are supported on all modern browsers. 
+# Note that when changing this option you need to delete any form_*.png files 
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax 
+# (see http://www.mathjax.org) which uses client side Javascript for the 
+# rendering instead of using prerendered bitmaps. Use this if you do not 
+# have LaTeX installed or if you want to formulas look prettier in the HTML 
+# output. When enabled you may also need to install MathJax separately and 
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you need to specify the location relative to the 
+# HTML output directory using the MATHJAX_RELPATH option. The destination 
+# directory should contain the MathJax.js script. For instance, if the mathjax 
+# directory is located at the same level as the HTML output directory, then 
+# MATHJAX_RELPATH should be ../mathjax. The default value points to 
+# the MathJax Content Delivery Network so you can quickly see the result without 
+# installing MathJax.  However, it is strongly recommended to install a local 
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension 
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS     = 
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box 
+# for the HTML output. The underlying search engine uses javascript 
+# and DHTML and should work on any modern browser. Note that when using 
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets 
+# (GENERATE_DOCSET) there is already a search function so this one should 
+# typically be disabled. For large projects the javascript based search engine 
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be 
+# implemented using a PHP enabled web server instead of at the web client 
+# using Javascript. Doxygen will generate the search PHP script and index 
+# file to put on the web server. The advantage of the server 
+# based approach is that it scales better to large projects and allows 
+# full text search. The disadvantages are that it is more difficult to setup 
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name. 
+# Note that when enabling USE_PDFLATEX this option is only used for 
+# generating bitmaps for formulas in the HTML output, but not in the 
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for 
+# the generated latex document. The footer should contain everything after 
+# the last chapter. If it is left blank doxygen will generate a 
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include 
+# source code with syntax highlighting in the LaTeX output. 
+# Note that which sources are shown also depends on other settings 
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the 
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See 
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition that 
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all references to function-like macros 
+# that are alone on a line, have an all uppercase name, and do not end with a 
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each 
+# tag file the location of the external documentation should be added. The 
+# format of a tag file without this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths 
+# or URLs. Note that each tag file must have a unique name (where the name does 
+# NOT include the path). If a tag file is not located in the directory in which 
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option also works with HAVE_DOT disabled, but it is recommended to 
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = NO
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is 
+# allowed to run in parallel. When set to 0 (the default) doxygen will 
+# base this on the number of processors available in the system. You can set it 
+# explicitly to a value larger than 0 to get control over the balance 
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS        = 0
+
+# By default doxygen will use the Helvetica font for all dot files that 
+# doxygen generates. When you want a differently looking font you can specify 
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find 
+# the font, which can be done by putting it in a standard location or by setting 
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the 
+# directory containing the font.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. 
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the Helvetica font. 
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to 
+# set the path where dot can find it.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside 
+# the class node. If there are many fields or methods and many nodes the 
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS 
+# threshold limits the number of items for each type to make the size more 
+# managable. Set this to 0 for no limit. Note that the threshold may be 
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = YES
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include 
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are svg, png, jpg, or gif. 
+# If left blank png will be used. If you choose svg you need to set 
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files 
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to 
+# enable generation of interactive SVG images that allow zooming and panning. 
+# Note that this requires a modern browser other than Internet Explorer. 
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you 
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files 
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG        = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that 
+# contain msc files that are included in the documentation (see the 
+# \mscfile command).
+
+MSCFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 44
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, because dot on Windows does not 
+# seem to support this out of the box. Warning: Depending on the platform used, 
+# enabling this option may lead to badly anti-aliased labels on the edges of 
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/nsdl-c/sn_client_config.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifndef SN_CLIENT_CONFIG_H
+#define SN_CLIENT_CONFIG_H
+
+#ifdef __DOXYGEN__
+
+/**
+* \brief Configuration options (set of defines and values)
+*
+*  This lists set of compile-time options that needs to be used to enable
+*  or disable features selectively, and set the values for the mandatory
+*  parameters.
+*/
+
+/**
+ * \def DISABLE_RESOURCE_TYPE
+ * \brief For Disabling Resource type
+ *
+ */
+#define DISABLE_RESOURCE_TYPE
+
+/**
+ * \def DISABLE_INTERFACE_DESCRIPTION
+ * \brief For Disabling Resource type
+ *
+ */
+#define DISABLE_INTERFACE_DESCRIPTION
+
+/**
+ * \def MBED_CLIENT_PRINT_COAP_PAYLOAD
+ * \brief If enabled this will print out the CoAP package payload.
+ */
+#define MBED_CLIENT_PRINT_COAP_PAYLOAD
+#endif
+
+#ifdef MBED_CLIENT_USER_CONFIG_FILE
+#include MBED_CLIENT_USER_CONFIG_FILE
+#endif
+
+#endif // SN_CONFIG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/nsdl-c/sn_nsdl.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+* \file sn_nsdl.h
+*
+* \brief libNsdl generic header file
+*
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SN_NSDL_H_
+#define SN_NSDL_H_
+
+#define SN_NSDL_SUCCESS  0
+#define SN_NSDL_FAILURE (-1)
+#define SN_NSDL_RESEND_QUEUE_FULL (-2)
+
+#include "sn_coap_header.h"
+
+#endif /* SN_NSDL_H_ */
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/nsdl-c/sn_nsdl_lib.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,763 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+* \file sn_nsdl_lib.h
+*
+* \brief NanoService Devices Library header file
+*
+*
+*/
+
+#ifndef SN_NSDL_LIB_H_
+#define SN_NSDL_LIB_H_
+
+#include "ns_list.h"
+#include "sn_client_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SN_NSDL_ENDPOINT_NOT_REGISTERED  0
+#define SN_NSDL_ENDPOINT_IS_REGISTERED   1
+
+#define MAX_TOKEN_SIZE 8
+#define MAX_URI_QUERY_LEN 255
+
+#ifdef YOTTA_CFG_DISABLE_INTERFACE_DESCRIPTION
+#define DISABLE_INTERFACE_DESCRIPTION YOTTA_CFG_DISABLE_INTERFACE_DESCRIPTION
+#elif defined MBED_CONF_MBED_CLIENT_DISABLE_INTERFACE_DESCRIPTION
+#define DISABLE_INTERFACE_DESCRIPTION MBED_CONF_MBED_CLIENT_DISABLE_INTERFACE_DESCRIPTION
+#endif
+
+#ifdef YOTTA_CFG_DISABLE_RESOURCE_TYPE
+#define DISABLE_RESOURCE_TYPE YOTTA_CFG_DISABLE_RESOURCE_TYPE
+#elif defined MBED_CONF_MBED_CLIENT_DISABLE_RESOURCE_TYPE
+#define DISABLE_RESOURCE_TYPE MBED_CONF_MBED_CLIENT_DISABLE_RESOURCE_TYPE
+#endif
+
+/* Handle structure */
+struct nsdl_s;
+
+/**
+ * \brief Received device server security
+ */
+typedef enum omalw_server_security_ {
+    SEC_NOT_SET = -1,
+    PSK = 0,
+    RPK = 1,
+    CERTIFICATE = 2,
+    NO_SEC = 3
+} omalw_server_security_t;
+
+/**
+ * \brief Endpoint binding and mode
+ */
+typedef enum sn_nsdl_oma_binding_and_mode_ {
+    BINDING_MODE_NOT_SET = 0,
+    BINDING_MODE_U = 0x01,
+    BINDING_MODE_Q = 0x02,
+    BINDING_MODE_S = 0x04
+} sn_nsdl_oma_binding_and_mode_t;
+
+//#define RESOURCE_ATTRIBUTES_LIST
+#ifdef RESOURCE_ATTRIBUTES_LIST
+/*
+ * \brief Resource attributes types
+ */
+typedef enum sn_nsdl_resource_attribute_ {
+    ATTR_RESOURCE_TYPE,
+    ATTR_INTERFACE_DESCRIPTION,
+    ATTR_ENDPOINT_NAME,
+    ATTR_QUEUE_MODE,
+    ATTR_LIFETIME,
+    ATTR_NOP,
+    ATTR_END
+} sn_nsdl_resource_attribute_t;
+
+typedef struct sn_nsdl_attribute_item_ {
+    sn_nsdl_resource_attribute_t attribute_name;
+    char *value;
+} sn_nsdl_attribute_item_s;
+
+#endif
+
+/**
+ * \brief Endpoint registration mode.
+ *      If REGISTER_WITH_RESOURCES, endpoint sends list of all resources during registration.
+ *      If REGISTER_WITH_TEMPLATE, endpoint sends registration without resource list. Device server must have
+ *      correctly configured template.
+ */
+typedef enum sn_nsdl_registration_mode_ {
+    REGISTER_WITH_RESOURCES = 0,
+    REGISTER_WITH_TEMPLATE
+} sn_nsdl_registration_mode_t;
+
+/**
+ * \brief Endpoint registration parameters
+ */
+typedef struct sn_nsdl_ep_parameters_ {
+    uint8_t     endpoint_name_len;
+    uint8_t     domain_name_len;
+    uint8_t     type_len;
+    uint8_t     lifetime_len;
+    uint8_t     location_len;
+
+    sn_nsdl_registration_mode_t ds_register_mode;       /**< Defines registration mode */
+    sn_nsdl_oma_binding_and_mode_t binding_and_mode;    /**< Defines endpoints binding and mode */
+
+    uint8_t     *endpoint_name_ptr;                     /**< Endpoint name */
+    uint8_t     *domain_name_ptr;                       /**< Domain to register. If null, NSP uses default domain */
+    uint8_t     *type_ptr;                              /**< Endpoint type */
+    uint8_t     *lifetime_ptr;                          /**< Endpoint lifetime in seconds. eg. "1200" = 1200 seconds */
+    uint8_t     *location_ptr;                          /**< Endpoint location in server, optional parameter,default is NULL */
+} sn_nsdl_ep_parameters_s;
+
+/**
+ * \brief Resource access rights
+ */
+typedef enum sn_grs_resource_acl_ {
+    SN_GRS_GET_ALLOWED  = 0x01 ,
+    SN_GRS_PUT_ALLOWED  = 0x02,
+    SN_GRS_POST_ALLOWED = 0x04,
+    SN_GRS_DELETE_ALLOWED   = 0x08
+} sn_grs_resource_acl_e;
+
+/**
+ * \brief Defines the resource mode
+ */
+typedef enum sn_nsdl_resource_mode_ {
+    SN_GRS_STATIC = 0,                  /**< Static resources have some value that doesn't change */
+    SN_GRS_DYNAMIC,                     /**< Dynamic resources are handled in application. Therefore one must give function callback pointer to them */
+    SN_GRS_DIRECTORY                    /**< Directory resources are unused and unsupported */
+} sn_nsdl_resource_mode_e;
+
+/**
+ * Enum defining an status codes that can happen when
+ * sending notification
+*/
+typedef enum {
+    NOTIFICATION_STATUS_INIT = 0,           // Initial state.
+    NOTIFICATION_STATUS_BUILD_ERROR,        // CoAP message building fails.
+    NOTIFICATION_STATUS_RESEND_QUEUE_FULL,  // CoAP resend queue full.
+    NOTIFICATION_STATUS_SENT,               // Notification sent to the server but ACK not yet received.
+    NOTIFICATION_STATUS_DELIVERED,          // Received ACK from server.
+    NOTIFICATION_STATUS_SEND_FAILED,        // Message sending failed (retransmission completed).
+    NOTIFICATION_STATUS_SUBSCRIBED,         // Server has started the observation
+    NOTIFICATION_STATUS_UNSUBSCRIBED        // Server has stopped the observation (RESET message or GET with observe 1)
+} NotificationDeliveryStatus;
+
+/** Dummy alias to maintain compatibility with older version which had a typo in the enum name. */
+typedef NotificationDeliveryStatus NoticationDeliveryStatus;
+
+
+/**
+ * \brief Defines static parameters for the resource.
+ */
+typedef struct sn_nsdl_static_resource_parameters_ {
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_RESOURCE_TYPE
+    char        *resource_type_ptr;         /**< Type of the resource */
+#endif
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+    char        *interface_description_ptr; /**< Interface description */
+#endif
+#else
+    sn_nsdl_attribute_item_s *attributes_ptr;
+#endif
+    char        *path;                      /**< Resource path */
+    bool        external_memory_block:1;    /**< 0 means block messages are handled inside this library,
+                                                 otherwise block messages are passed to application */
+    unsigned    mode:2;                     /**< STATIC etc.. */
+    bool        free_on_delete:1;           /**< 1 if struct is dynamic allocted --> to be freed */
+} sn_nsdl_static_resource_parameters_s;
+
+/**
+ * \brief Defines dynamic parameters for the resource.
+ */
+typedef struct sn_nsdl_resource_parameters_ {
+    uint8_t                                     (*sn_grs_dyn_res_callback)(struct nsdl_s *,
+                                                                       sn_coap_hdr_s *,
+                                                                       sn_nsdl_addr_s *,
+                                                                       sn_nsdl_capab_e);
+#ifdef MEMORY_OPTIMIZED_API
+    const sn_nsdl_static_resource_parameters_s  *static_resource_parameters;
+#else
+    sn_nsdl_static_resource_parameters_s        *static_resource_parameters;
+#endif
+    uint8_t                                     *resource;          /**< NULL if dynamic resource */
+    ns_list_link_t                              link;
+    uint16_t                                    resource_len;        /**< 0 if dynamic resource, resource information in static resource */
+    uint16_t                                    coap_content_type;  /**< CoAP content type */
+    uint16_t                                    msg_id;             /**< Notification message id. */
+    unsigned                                    access:4;           /**< Allowed operation mode, GET, PUT, etc,
+                                                                         TODO! This should be in static struct but current
+                                                                         mbed-client implementation requires this to be changed at runtime */
+    unsigned                                    registered:2;       /**< Is resource registered or not */
+    bool                                        publish_uri:1;      /**< 1 if resource to be published to server */
+    bool                                        free_on_delete:1;   /**< 1 if struct is dynamic allocted --> to be freed */
+    bool                                        observable:1;       /**< Is resource observable or not */
+    bool                                        auto_observable:1;  /**< Is resource auto observable or not */
+    bool                                        always_publish:1;  /**< 1 if resource should always be published in registration or registration update **/
+    unsigned                                    publish_value:2;    /**< 0 for non-publishing,1 if resource value to be published in registration message,
+                                                                         2 if resource value to be published in Base64 encoded format */
+} sn_nsdl_dynamic_resource_parameters_s;
+
+
+/**
+ * \fn struct nsdl_s *sn_nsdl_init  (uint8_t (*sn_nsdl_tx_cb)(sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *),
+ *                          uint8_t (*sn_nsdl_rx_cb)(sn_coap_hdr_s *, sn_nsdl_addr_s *),
+ *                          sn_nsdl_mem_s *sn_memory)
+ *
+ * \brief Initialization function for NSDL library. Initializes NSDL, GRS, HTTP and CoAP.
+ *
+ * \param *sn_nsdl_tx_callback  A callback function for sending messages.
+ *
+ * \param *sn_nsdl_rx_callback  A callback function for parsed messages. If received message is not CoAP protocol message (eg. ACK), message for GRS (GET, PUT, POST, DELETE) or
+ *                              reply for some DS messages (register message etc.), rx callback will be called.
+ *
+ * \param *sn_memory            Memory structure which includes function pointers to the allocation and free functions.
+ *
+ * \return  pointer to created handle structure. NULL if failed
+ */
+struct nsdl_s *sn_nsdl_init(uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *),
+                            uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *),
+                            void *(*sn_nsdl_alloc)(uint16_t), void (*sn_nsdl_free)(void *),
+                            uint8_t (*sn_nsdl_auto_obs_token_cb)(struct nsdl_s *, const char *, uint8_t *));
+
+/**
+ * \fn extern uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr, const char *uri_query_parameters);
+ *
+ * \brief Registers endpoint to mbed Device Server.
+ * \param *handle               Pointer to nsdl-library handle
+ * \param *endpoint_info_ptr    Contains endpoint information.
+ * \param *uri_query_parameters Uri query parameters.
+ *
+ * \return registration message ID, 0 if failed
+ */
+extern uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle,
+                                          sn_nsdl_ep_parameters_s *endpoint_info_ptr,
+                                          const char *uri_query_parameters);
+
+/**
+ * \fn extern int32_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle)
+ *
+ * \brief Sends unregister-message to mbed Device Server.
+ *
+ * \param *handle               Pointer to nsdl-library handle
+ *
+ * \return  unregistration message ID, 0 if failed
+ */
+extern int32_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle);
+
+/**
+ * \fn extern int32_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len);
+ *
+ * \brief Update the registration with mbed Device Server.
+ *
+ * \param *handle   Pointer to nsdl-library handle
+ * \param *lt_ptr   Pointer to lifetime value string in ascii form, eg. "1200"
+ * \param lt_len    Length of the lifetime string
+ *
+ * \return  registration update message ID, <0 if failed
+ */
+extern int32_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len);
+
+/**
+ * \fn extern int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len);
+ *
+ * \brief Sets the location receievd from Device Server.
+ *
+ * \param *handle   Pointer to nsdl-library handle
+ * \param *lt_ptr   Pointer to location value string , eg. "s322j4k"
+ * \param lt_len    Length of the location string
+ *
+ * \return  success, <0 if failed
+ */
+extern int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len);
+
+/**
+ * \fn extern int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle)
+ *
+ * \brief Checks if endpoint is registered.
+ *
+ * \param *handle   Pointer to nsdl-library handle
+ *
+ * \return 1 Endpoint registration is done successfully
+ * \return 0 Endpoint is not registered
+ */
+extern int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle);
+
+/**
+ * \fn extern void sn_nsdl_nsp_lost(struct nsdl_s *handle);
+ *
+ * \brief A function to inform mbed Device C client library if application detects a fault in mbed Device Server registration.
+ *
+ * \param *handle   Pointer to nsdl-library handle
+ *
+ * After calling this function sn_nsdl_is_ep_registered() will return "not registered".
+ */
+extern void sn_nsdl_nsp_lost(struct nsdl_s *handle);
+
+/**
+ * \fn extern uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len,
+ *                                                  uint8_t *payload_ptr, uint16_t payload_len,
+ *                                                  sn_coap_observe_e observe,
+ *                                                  sn_coap_msg_type_e message_type, sn_coap_content_format_e content_format)
+ *
+ *
+ * \brief Sends observation message to mbed Device Server
+ *
+ * \param   *handle         Pointer to nsdl-library handle
+ * \param   *token_ptr      Pointer to token to be used
+ * \param   token_len       Token length
+ * \param   *payload_ptr    Pointer to payload to be sent
+ * \param   payload_len     Payload length
+ * \param   observe         Observe option value to be sent
+ * \param   message_type    Observation message type (confirmable or non-confirmable)
+ * \param   content_format  Observation message payload content format
+ * \param   message_id      -1 means stored value to be used otherwise new one is generated
+ *
+ * \return  >0  Success, observation messages message ID
+ * \return  <=0   Failure
+ */
+extern int32_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len,
+        uint8_t *payload_ptr, uint16_t payload_len,
+        sn_coap_observe_e observe,
+        sn_coap_msg_type_e message_type,
+        sn_coap_content_format_e content_format,
+        const int32_t message_id);
+
+/**
+ * \fn extern uint32_t sn_nsdl_get_version(void)
+ *
+ * \brief Version query function.
+ *
+ * Used to retrieve the version information from the mbed Device C Client library.
+ *
+ * \return Pointer to library version string
+*/
+extern char *sn_nsdl_get_version(void);
+
+/**
+ * \fn extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src)
+ *
+ * \brief To push CoAP packet to mbed Device C Client library
+ *
+ * Used to push an CoAP packet to mbed Device C Client library for processing.
+ *
+ * \param   *handle     Pointer to nsdl-library handle
+ *
+ * \param   *packet     Pointer to a uint8_t array containing the packet (including the CoAP headers).
+ *      After successful execution this array may contain the response packet.
+ *
+ * \param   *packet_len Pointer to length of the packet. After successful execution this array may contain the length
+ *      of the response packet.
+ *
+ * \param   *src        Pointer to packet source address information. After successful execution this array may contain
+ *      the destination address of the response packet.
+ *
+ * \return  0   Success
+ * \return  -1  Failure
+ */
+extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src);
+
+/**
+ * \fn extern int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time);
+ *
+ * \brief CoAP retransmission function.
+ *
+ * Used to give execution time for the mbed Device C Client library for retransmissions.
+ *
+ * \param   *handle Pointer to nsdl-library handle
+ *
+ * \param  time Time in seconds.
+ *
+ * \return  0   Success
+ * \return  -1  Failure
+ */
+extern int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time);
+
+/**
+ * \fn  extern int8_t sn_nsdl_put_resource(struct nsdl_s *handle, const sn_nsdl_dynamic_resource_parameters_s *res);
+ *
+ * \brief Resource putting function.
+ *
+ * Used to put a static or dynamic CoAP resource without creating copy of it.
+ * NOTE: Remember that only resource will be owned, not data that it contains
+ * NOTE: The resource may be removed from list by sn_nsdl_pop_resource().
+ *
+ * \param   *res    Pointer to a structure of type sn_nsdl_dynamic_resource_parameters_s that contains the information
+ *     about the resource.
+ *
+ * \return  0   Success
+ * \return  -1  Failure
+ * \return  -2  Resource already exists
+ * \return  -3  Invalid path
+ * \return  -4  List adding failure
+ */
+extern int8_t sn_nsdl_put_resource(struct nsdl_s *handle, sn_nsdl_dynamic_resource_parameters_s *res);
+
+/**
+ * \fn  extern int8_t sn_nsdl_pop_resource(struct nsdl_s *handle, const sn_nsdl_dynamic_resource_parameters_s *res);
+ *
+ * \brief Resource popping function.
+ *
+ * Used to remove a static or dynamic CoAP resource from lists without deleting it.
+ * NOTE: This function is a counterpart of sn_nsdl_put_resource().
+ *
+ * \param   *res    Pointer to a structure of type sn_nsdl_dynamic_resource_parameters_s that contains the information
+ *     about the resource.
+ *
+ * \return  0   Success
+ * \return  -1  Failure
+ * \return  -3  Invalid path
+ */
+extern int8_t sn_nsdl_pop_resource(struct nsdl_s *handle, sn_nsdl_dynamic_resource_parameters_s *res);
+
+/**
+ * \fn extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, char *path)
+ *
+ * \brief Resource delete function.
+ *
+ * Used to delete a resource. If resource has a subresources, these all must also be removed.
+ *
+ * \param   *handle     Pointer to nsdl-library handle
+ * \param   *path_ptr   A pointer to an array containing the path.
+ *
+ * \return  0   Success
+ * \return  -1  Failure (No such resource)
+ */
+extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, const char *path);
+
+/**
+ * \fn extern sn_nsdl_dynamic_resource_parameters_s *sn_nsdl_get_resource(struct nsdl_s *handle, char *path)
+ *
+ * \brief Resource get function.
+ *
+ * Used to get a resource.
+ *
+ * \param   *handle     Pointer to nsdl-library handle
+  * \param   *path   A pointer to an array containing the path.
+ *
+ * \return  !NULL   Success, pointer to a sn_nsdl_dynamic_resource_parameters_s that contains the resource information\n
+ * \return  NULL    Failure
+ */
+extern sn_nsdl_dynamic_resource_parameters_s *sn_nsdl_get_resource(struct nsdl_s *handle, const char *path);
+
+/**
+ * \fn extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr);
+ *
+ * \brief Send an outgoing CoAP request.
+ *
+ * \param   *handle Pointer to nsdl-library handle
+ * \param   *address_ptr    Pointer to source address struct
+ * \param   *coap_hdr_ptr   Pointer to CoAP message to be sent
+ *
+ * \return  0   Success
+ * \return  -1  Failure
+ */
+extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr);
+
+/**
+ * \fn extern int32_t sn_nsdl_send_request(struct nsdl_s *handle, sn_coap_msg_code_e msg_code, const char *uri_path, const uint32_t token, const size_t offset, const uint16_t payload_len, const uint8_t* payload_ptr);
+ *
+ * \brief Send an outgoing CoAP request.
+ *
+ * \param   *handle       Pointer to nsdl-library handle
+ * \param   msg-code      CoAP message code to use for request
+ * \param   *uri_path     Path to the data
+ * \param   *token        Message token
+ * \param   offset        Offset within response body to request
+ * \param   payload_len   Message payload length, can be 0 for no payload
+ * \param   *payload_ptr  Message payload pointer, can be NULL for no payload
+ *
+ * \Return  > 0 Success else Failure
+ */
+extern int32_t sn_nsdl_send_request(struct nsdl_s *handle,
+                                    sn_coap_msg_code_e msg_code,
+                                    const char *uri_path,
+                                    const uint32_t token,
+                                    const size_t offset,
+                                    const uint16_t payload_len,
+                                    uint8_t* payload_ptr);
+
+/**
+ * \fn extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint8_t address_length, uint16_t port, sn_nsdl_addr_type_e address_type);
+ *
+ * \brief This function is used to set the mbed Device Server address given by an application.
+ *
+ * \param   *handle Pointer to nsdl-library handle
+ * \return  0   Success
+ * \return  -1  Failed to indicate that internal address pointer is not allocated (call nsdl_init() first).
+ */
+extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint8_t address_length, uint16_t port, sn_nsdl_addr_type_e address_type);
+
+/**
+ * \fn extern int8_t sn_nsdl_destroy(struct nsdl_s *handle);
+ *
+ * \param   *handle Pointer to nsdl-library handle
+ * \brief This function releases all allocated memory in mbed Device C Client library.
+ */
+extern int8_t sn_nsdl_destroy(struct nsdl_s *handle);
+
+/**
+ * \fn extern uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, sn_nsdl_ep_parameters_s *endpoint_info_ptr, sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr);
+ *
+ * \brief Starts OMA bootstrap process
+ *
+ * \param   *handle Pointer to nsdl-library handle
+ *
+ * \return bootstrap message ID, 0 if failed
+ */
+extern uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle,
+                                      sn_nsdl_addr_s *bootstrap_address_ptr,
+                                      sn_nsdl_ep_parameters_s *endpoint_info_ptr,
+                                      const char *uri_query_parameters);
+
+/**
+ * \fn sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)
+ *
+ * \brief Prepares generic response packet from a request packet. This function allocates memory for the resulting sn_coap_hdr_s
+ *
+ * \param *handle Pointer to library handle
+ * \param *coap_packet_ptr The request packet pointer
+ * \param msg_code response messages code
+ *
+ * \return *coap_packet_ptr The allocated and pre-filled response packet pointer
+ *          NULL    Error in parsing the request
+ *
+ */
+extern sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code);
+
+/**
+ * \brief Allocates and initializes options list structure
+ *
+ * \param *handle Pointer to library handle
+ * \param *coap_msg_ptr is pointer to CoAP message that will contain the options
+ *
+ * If the message already has a pointer to an option structure, that pointer
+ * is returned, rather than a new structure being allocated.
+ *
+ * \return Return value is pointer to the CoAP options structure.\n
+ *         In following failure cases NULL is returned:\n
+ *          -Failure in given pointer (= NULL)\n
+ *          -Failure in memory allocation (malloc() returns NULL)
+ */
+extern sn_coap_options_list_s *sn_nsdl_alloc_options_list(struct nsdl_s *handle, sn_coap_hdr_s *coap_msg_ptr);
+
+/**
+ * \fn void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr)
+ *
+ * \brief Releases memory of given CoAP message
+ *
+ *        Note!!! Does not release Payload part
+ *
+ * \param *handle Pointer to library handle
+ *
+ * \param *freed_coap_msg_ptr is pointer to released CoAP message
+ */
+extern void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr);
+
+/**
+ * \fn int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *handle, uint8_t resending_count, uint8_t resending_intervall)
+ *
+ * \brief  If re-transmissions are enabled, this function changes resending count and interval.
+ *
+ * \param *handle Pointer to library handle
+ * \param uint8_t resending_count max number of resendings for message
+ * \param uint8_t resending_intervall message resending intervall in seconds
+ * \return  0 = success, -1 = failure
+ */
+extern int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *handle, uint8_t resending_count, uint8_t resending_interval);
+
+/**
+ * \fn int8_t sn_nsdl_set_retransmission_buffer(struct nsdl_s *handle, uint8_t buffer_size_messages, uint16_t buffer_size_bytes)
+ *
+ * \brief If re-transmissions are enabled, this function changes message retransmission queue size.
+ *  Set size to '0' to disable feature. If both are set to '0', then re-sendings are disabled.
+ *
+ * \param *handle Pointer to library handle
+ * \param uint8_t buffer_size_messages queue size - maximum number of messages to be saved to queue
+ * \param uint8_t buffer_size_bytes queue size - maximum size of messages saved to queue
+ * \return  0 = success, -1 = failure
+ */
+extern int8_t sn_nsdl_set_retransmission_buffer(struct nsdl_s *handle,
+        uint8_t buffer_size_messages, uint16_t buffer_size_bytes);
+
+/**
+ * \fn int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size)
+ *
+ * \brief If block transfer is enabled, this function changes the block size.
+ *
+ * \param *handle Pointer to library handle
+ * \param uint16_t block_size maximum size of CoAP payload. Valid sizes are 16, 32, 64, 128, 256, 512 and 1024 bytes
+ * \return  0 = success, -1 = failure
+ */
+extern int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size);
+
+/**
+ * \fn int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle,uint8_t message_count)
+ *
+ * \brief If dublicate message detection is enabled, this function changes buffer size.
+ *
+ * \param *handle Pointer to library handle
+ * \param uint8_t message_count max number of messages saved for duplicate control
+ * \return  0 = success, -1 = failure
+ */
+extern int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle, uint8_t message_count);
+
+/**
+ * \fn void *sn_nsdl_set_context(const struct nsdl_s *handle, void *context)
+ *
+ * \brief Set the application defined context parameter for given handle.
+ *        This is useful for example when interfacing with c++ objects where a
+ *        pointer to object is set as the context, and in the callback functions
+ *        the context pointer can be used to call methods for the correct instance
+ *        of the c++ object.
+ *
+ * \param *handle Pointer to library handle
+ * \param *context Pointer to the application defined context
+ * \return 0 = success, -1 = failure
+ */
+extern int8_t sn_nsdl_set_context(struct nsdl_s * const handle, void * const context);
+
+/**
+ * \fn void *sn_nsdl_get_context(const struct nsdl_s *handle)
+ *
+ * \brief Get the application defined context parameter for given handle.
+ *        This is useful for example when interfacing with c++ objects where a
+ *        pointer to object is set as the context, and in the callback functions
+ *        the context pointer can be used to call methods for the correct instance
+ *        of the c++ object.
+ *
+ * \param *handle Pointer to library handle
+ * \return Pointer to the application defined context
+ */
+extern void *sn_nsdl_get_context(const struct nsdl_s * const handle);
+
+/**
+ * \fn int8_t sn_nsdl_clear_coap_resending_queue(struct nsdl_s *handle)
+ *
+ * \brief Clean confirmable message list.
+ *
+ * \param *handle Pointer to library handle
+ * \return  0 = success, -1 = failure
+ */
+extern int8_t sn_nsdl_clear_coap_resending_queue(struct nsdl_s *handle);
+
+/**
+ * \fn int8_t sn_nsdl_clear_coap_sent_blockwise_messages(struct nsdl_s *handle)
+ *
+ * \brief Clears the sent blockwise messages from the linked list.
+ *
+ * \param *handle Pointer to library handle
+ * \return  0 = success, -1 = failure
+ */
+extern int8_t sn_nsdl_clear_coap_sent_blockwise_messages(struct nsdl_s *handle);
+
+/**
+ * \fn int8_t sn_nsdl_handle_block2_response_internally(struct nsdl_s *handle, uint8_t handle_response)
+ *
+ * \brief This function change the state whether CoAP library sends the block 2 response automatically or not.
+ *
+ * \param *handle Pointer to NSDL library handle
+ * \param handle_response 1 if CoAP library handles the response sending otherwise 0.
+ *
+ * \return  0 = success, -1 = failure
+ */
+extern int8_t sn_nsdl_handle_block2_response_internally(struct nsdl_s *handle, uint8_t handle_response);
+
+#ifdef RESOURCE_ATTRIBUTES_LIST
+/**
+ * \fn int8_t sn_nsdl_free_resource_attributes_list(struct nsdl_s *handle, sn_nsdl_static_resource_parameters_s *params)
+ *
+ * \brief Free resource attributes list if free_on_delete is true for params. This will also free all attributes values
+ * if they are pointer types.
+ *
+ * \param *params Pointer to resource static parameters
+ */
+extern void sn_nsdl_free_resource_attributes_list(sn_nsdl_static_resource_parameters_s *params);
+
+/*
+ * \fn bool sn_nsdl_set_resource_attribute(sn_nsdl_static_resource_parameters_s *params, sn_nsdl_attribute_item_s attribute)
+ *
+ * \brief Set resource link-format attribute value, create if it doesn't exist yet.
+ *
+ * \param *params Pointer to resource static parameters
+ * \param attribute sn_nsdl_attribute_item_s structure containing attribute to set
+ * \return True if successful, false on error
+ */
+extern bool sn_nsdl_set_resource_attribute(sn_nsdl_static_resource_parameters_s *params, const sn_nsdl_attribute_item_s *attribute);
+
+/*
+ * \fn bool sn_nsdl_get_resource_attribute(sn_nsdl_static_resource_parameters_s *params, sn_nsdl_resource_attribute_t attribute)
+ *
+ * \brief Get resource link-format attribute value
+ *
+ * \param *params Pointer to resource static parameters
+ * \param attribute sn_nsdl_resource_attribute_t enum value for attribute to get
+ * \return Pointer to value or null if attribute did not exist or had no value
+ */
+extern const char* sn_nsdl_get_resource_attribute(const sn_nsdl_static_resource_parameters_s *params, sn_nsdl_resource_attribute_t attribute);
+
+/*
+ * \fn bool sn_nsdl_remove_resource_attribute(sn_nsdl_static_resource_parameters_s *params, sn_nsdl_resource_attribute_t attribute)
+ *
+ * \brief Remove resource link-format attribute value
+ *
+ * \param *params Pointer to resource static parameters
+ * \param attribute sn_nsdl_resource_attribute_t enum value for attribute to remove
+ */
+extern bool sn_nsdl_remove_resource_attribute(sn_nsdl_static_resource_parameters_s *params, sn_nsdl_resource_attribute_t attribute);
+#endif
+
+/**
+ * \fn bool sn_nsdl_print_coap_data(sn_coap_hdr_s *coap_header_ptr, bool outgoing)
+ *
+ * \brief Utility function to print all the CoAP header parameters
+ *
+ * \param *coap_header_ptr CoAP header
+ * \param outgoing If True, package is going to be sent to server otherwise receiving
+ */
+extern void sn_nsdl_print_coap_data(sn_coap_hdr_s *coap_header_ptr, bool outgoing);
+
+/**
+ * \fn uint16_t sn_nsdl_get_block_size(struct nsdl_s *handle)
+ *
+ * \brief Get CoAP block size
+ *
+ * \param *handle Pointer to library handle
+ * \return  block size
+ */
+extern uint16_t sn_nsdl_get_block_size(const struct nsdl_s *handle);
+
+/**
+ * \fn uint8_t sn_nsdl_get_retransmission_count(struct nsdl_s *handle)
+ *
+ * \brief  Returns retransmission coint
+ *
+ * \param *handle Pointer to library handle
+ * \return  Retransmission count
+ */
+extern uint8_t sn_nsdl_get_retransmission_count(struct nsdl_s *handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SN_NSDL_LIB_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/source/include/sn_grs.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef GRS_H_
+#define GRS_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define SN_GRS_RESOURCE_ALREADY_EXISTS  -2
+#define SN_GRS_INVALID_PATH             -3
+#define SN_GRS_LIST_ADDING_FAILURE      -4
+#define SN_GRS_RESOURCE_UPDATED     -5
+
+#define ACCESS_DENIED           -6
+
+#define SN_GRS_DELETE_METHOD    0
+#define SN_GRS_SEARCH_METHOD    1
+
+#define SN_GRS_DEFAULT_ACCESS   0x0F
+
+#define SN_NDSL_RESOURCE_NOT_REGISTERED 0
+#define SN_NDSL_RESOURCE_REGISTERING    1
+#define SN_NDSL_RESOURCE_REGISTERED     2
+
+/***** Structs *****/
+
+typedef struct sn_grs_version_ {
+    uint8_t major_version;
+    uint8_t minor_version;
+    uint8_t build;
+} sn_grs_version_s;
+
+typedef NS_LIST_HEAD(sn_nsdl_dynamic_resource_parameters_s, link) resource_list_t;
+
+struct grs_s {
+    struct coap_s *coap;
+
+    void *(*sn_grs_alloc)(uint16_t);
+    void (*sn_grs_free)(void *);
+    uint8_t (*sn_grs_tx_callback)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *);
+    int8_t (*sn_grs_rx_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *);
+
+    uint16_t resource_root_count;
+    resource_list_t resource_root_list;
+};
+
+
+struct nsdl_s {
+    uint32_t update_register_token;
+    uint32_t register_token;
+    uint32_t unregister_token;
+    uint32_t bootstrap_token;
+    uint32_t token_seed;
+    unsigned int sn_nsdl_endpoint_registered:1;
+    unsigned int is_bs_server:1;
+
+    struct grs_s *grs;
+    sn_nsdl_ep_parameters_s *ep_information_ptr;     // Endpoint parameters, Name, Domain etc..
+    sn_nsdl_addr_s server_address;                   // server address information
+    /* Application definable context. This is useful for example when interfacing with c++ objects where a pointer to object is set as the
+     * context, and in the callback functions the context pointer can be used to call methods for the correct instance of the c++ object. */
+    void *context;
+
+    void *(*sn_nsdl_alloc)(uint16_t);
+    void (*sn_nsdl_free)(void *);
+    uint8_t (*sn_nsdl_tx_callback)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *);
+    uint8_t (*sn_nsdl_rx_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *);
+    uint8_t (*sn_nsdl_auto_obs_token_callback)(struct nsdl_s *, const char*, uint8_t*);
+};
+
+/***** Function prototypes *****/
+/**
+ *  \fn extern grs_s *sn_grs_init   (uint8_t (*sn_grs_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t,
+ *                                  sn_nsdl_addr_s *), uint8_t (*sn_grs_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *),
+ *                                  sn_grs_mem_s *sn_memory)
+ *
+ *  \brief GRS library initialize function.
+ *
+ *  This function initializes GRS and CoAP.
+ *
+ *  \param  sn_grs_tx_callback      A function pointer to a transmit callback function. Should return 1 when succeed, 0 when failed
+ *  \param  *sn_grs_rx_callback_ptr A function pointer to a receiving callback function. If received packet is not for GRS, it will be passed to
+ *                                  upper level (NSDL) to be proceed.
+ *  \param  sn_memory               A pointer to a structure containing the platform specific functions for memory allocation and free.
+ *
+ *  \return success pointer to handle, failure = NULL
+ *
+*/
+extern struct grs_s *sn_grs_init(uint8_t (*sn_grs_tx_callback_ptr)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t,
+                                 sn_nsdl_addr_s *),
+                                 int8_t (*sn_grs_rx_callback_ptr)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *),
+                                 void *(*sn_grs_alloc)(uint16_t),
+                                 void (*sn_grs_free)(void *));
+
+extern sn_nsdl_dynamic_resource_parameters_s    *sn_grs_get_first_resource(struct grs_s *handle);
+extern sn_nsdl_dynamic_resource_parameters_s    *sn_grs_get_next_resource(struct grs_s *handle,
+                                                                          const sn_nsdl_dynamic_resource_parameters_s *sn_grs_current_resource);
+extern int8_t                                   sn_grs_process_coap(struct nsdl_s *handle,
+                                                                    sn_coap_hdr_s *coap_packet_ptr,
+                                                                    sn_nsdl_addr_s *src);
+extern sn_nsdl_dynamic_resource_parameters_s    *sn_grs_search_resource(struct grs_s *handle,
+                                                                        const char *path,
+                                                                        uint8_t search_method);
+extern int8_t                                   sn_grs_destroy(struct grs_s *handle);
+extern int8_t                                   sn_grs_send_coap_message(struct nsdl_s *handle,
+                                                                         sn_nsdl_addr_s *address_ptr,
+                                                                         sn_coap_hdr_s *coap_hdr_ptr);
+extern int8_t                                   sn_grs_put_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res);
+extern int8_t                                   sn_grs_pop_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res);
+extern int8_t                                   sn_grs_delete_resource(struct grs_s *handle, const char *path);
+extern void                                     sn_grs_mark_resources_as_registered(struct nsdl_s *handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
+#endif /* GRS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/source/sn_grs.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,735 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+ *
+ * \file sn_grs.c
+ *
+ * \brief General resource server.
+ *
+ */
+#include <string.h>
+#include <stdlib.h>
+#include "ns_list.h"
+#include "ns_types.h"
+#include "sn_nsdl.h"
+#include "sn_coap_header.h"
+#include "sn_coap_protocol.h"
+#include "source/include/sn_coap_protocol_internal.h"
+#include "sn_nsdl_lib.h"
+#include "sn_grs.h"
+
+/* Defines */
+#define WELLKNOWN_PATH_LEN              16
+#define WELLKNOWN_PATH                  (".well-known/core")
+
+/* Local static function prototypes */
+static int8_t                       sn_grs_resource_info_free(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *resource_ptr);
+static char *sn_grs_convert_uri(uint16_t *uri_len, const char *uri_ptr);
+static int8_t                       sn_grs_core_request(struct nsdl_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *coap_packet_ptr);
+static uint8_t                      coap_tx_callback(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *);
+static int8_t                       coap_rx_callback(sn_coap_hdr_s *coap_ptr, sn_nsdl_addr_s *address_ptr, void *param);
+
+/* Extern function prototypes */
+extern int8_t                       sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration);
+
+/**
+ * \fn int8_t sn_grs_destroy(void)
+ * \brief This function may be used to flush GRS related stuff when a program exits.
+ * @return always 0.
+ */
+extern int8_t sn_grs_destroy(struct grs_s *handle)
+{
+    if( handle == NULL ){
+        return 0;
+    }
+    ns_list_foreach_safe(sn_nsdl_dynamic_resource_parameters_s, tmp, &handle->resource_root_list) {
+        ns_list_remove(&handle->resource_root_list, tmp);
+        --handle->resource_root_count;
+        sn_grs_resource_info_free(handle, tmp);
+    }
+    handle->sn_grs_free(handle);
+
+    return 0;
+}
+
+static uint8_t coap_tx_callback(uint8_t *data_ptr, uint16_t data_len, sn_nsdl_addr_s *address_ptr, void *param)
+{
+    struct nsdl_s *handle = (struct nsdl_s *)param;
+
+    if (handle == NULL) {
+        return 0;
+    }
+
+    return handle->grs->sn_grs_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, data_ptr, data_len, address_ptr);
+}
+
+static int8_t coap_rx_callback(sn_coap_hdr_s *coap_ptr, sn_nsdl_addr_s *address_ptr, void *param)
+{
+    struct nsdl_s *handle = (struct nsdl_s *)param;
+
+    if (handle == NULL) {
+        return 0;
+    }
+
+    return handle->sn_nsdl_rx_callback(handle, coap_ptr, address_ptr);
+}
+
+/**
+ * \fn int8_t sn_grs_init   (uint8_t (*sn_grs_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t,
+ *      sn_nsdl_addr_s *), int8_t (*sn_grs_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *), sn_nsdl_mem_s *sn_memory)
+ *
+ * \brief GRS library initialize function.
+ *
+ * This function initializes GRS and CoAP libraries.
+ *
+ * \param   sn_grs_tx_callback      A function pointer to a transmit callback function.
+ * \param  *sn_grs_rx_callback_ptr A function pointer to a receiving callback function. If received packet is not for GRS, it will be passed to
+ *                                  upper level (NSDL) to be proceed.
+ * \param   sn_memory               A pointer to a structure containing the platform specific functions for memory allocation and free.
+ *
+ * \return success = 0, failure = -1
+ *
+*/
+extern struct grs_s *sn_grs_init(uint8_t (*sn_grs_tx_callback_ptr)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t,
+                                 sn_nsdl_addr_s *), int8_t (*sn_grs_rx_callback_ptr)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *),
+                                 void *(*sn_grs_alloc)(uint16_t), void (*sn_grs_free)(void *))
+{
+
+    struct grs_s *handle_ptr = NULL;
+
+    /* Check parameters */
+    if (sn_grs_alloc == NULL || sn_grs_free == NULL ||
+        sn_grs_tx_callback_ptr == NULL || sn_grs_rx_callback_ptr == NULL) {
+        return NULL;
+    }
+
+    handle_ptr = sn_grs_alloc(sizeof(struct grs_s));
+
+    if (handle_ptr == NULL) {
+        return NULL;
+    }
+
+    memset(handle_ptr, 0, sizeof(struct grs_s));
+
+    /* Allocation and free - function pointers  */
+    handle_ptr->sn_grs_alloc = sn_grs_alloc;
+    handle_ptr->sn_grs_free = sn_grs_free;
+
+    /* TX callback function pointer */
+    handle_ptr->sn_grs_tx_callback = sn_grs_tx_callback_ptr;
+    handle_ptr->sn_grs_rx_callback = sn_grs_rx_callback_ptr;
+
+    /* Initialize CoAP protocol library */
+    handle_ptr->coap = sn_coap_protocol_init(sn_grs_alloc, sn_grs_free, coap_tx_callback, coap_rx_callback);
+
+    return handle_ptr;
+}
+
+extern sn_nsdl_dynamic_resource_parameters_s *sn_grs_get_first_resource(struct grs_s *handle)
+{
+    if( !handle ){
+        return NULL;
+    }
+    return ns_list_get_first(&handle->resource_root_list);
+}
+
+extern sn_nsdl_dynamic_resource_parameters_s *sn_grs_get_next_resource(struct grs_s *handle,
+                                                                             const sn_nsdl_dynamic_resource_parameters_s *sn_grs_current_resource)
+{
+    if( !handle || !sn_grs_current_resource ){
+        return NULL;
+    }
+    return ns_list_get_next(&handle->resource_root_list, sn_grs_current_resource);
+}
+
+extern int8_t sn_grs_delete_resource(struct grs_s *handle, const char *path)
+{
+    /* Local variables */
+    sn_nsdl_dynamic_resource_parameters_s     *resource_temp  = NULL;
+
+    /* Search if resource found */
+    resource_temp = sn_grs_search_resource(handle, path, SN_GRS_SEARCH_METHOD);
+
+    /* If not found */
+    if (resource_temp == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+
+    /* If found, delete it and delete also subresources, if there is any */
+    do {
+        /* Remove from list */
+        ns_list_remove(&handle->resource_root_list, resource_temp);
+        --handle->resource_root_count;
+
+        /* Free */
+        sn_grs_resource_info_free(handle, resource_temp);
+
+        /* Search for subresources */
+        resource_temp = sn_grs_search_resource(handle, path, SN_GRS_DELETE_METHOD);
+    } while (resource_temp != NULL);
+
+    return SN_NSDL_SUCCESS;
+}
+
+int8_t sn_grs_put_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res)
+{
+    if (!res || !handle) {
+        return SN_NSDL_FAILURE;
+    }
+
+    /* Check path validity */
+    if (!res->static_resource_parameters->path || res->static_resource_parameters->path[0] == '\0') {
+        return SN_GRS_INVALID_PATH;
+    }
+
+    /* Check if resource already exists */
+    if (sn_grs_search_resource(handle,
+                               res->static_resource_parameters->path, SN_GRS_SEARCH_METHOD) != (sn_nsdl_dynamic_resource_parameters_s *)NULL) {
+        return SN_GRS_RESOURCE_ALREADY_EXISTS;
+    }
+
+    res->registered = SN_NDSL_RESOURCE_NOT_REGISTERED;
+
+    ns_list_add_to_start(&handle->resource_root_list, res);
+    ++handle->resource_root_count;
+
+    return SN_NSDL_SUCCESS;
+}
+
+int8_t sn_grs_pop_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res)
+{
+    if (!res || !handle) {
+        return SN_NSDL_FAILURE;
+    }
+
+    /* Check path validity */
+    if (!res->static_resource_parameters->path || res->static_resource_parameters->path[0] == '\0') {
+        return SN_GRS_INVALID_PATH;
+    }
+
+    /* Check if resource exists on list. */
+    if (sn_grs_search_resource(handle,
+                               res->static_resource_parameters->path, SN_GRS_SEARCH_METHOD) == (sn_nsdl_dynamic_resource_parameters_s *)NULL) {
+        return SN_NSDL_FAILURE;
+    }
+
+    ns_list_remove(&handle->resource_root_list, res);
+    --handle->resource_root_count;
+
+    return SN_NSDL_SUCCESS;
+}
+
+/**
+ * \fn  extern int8_t sn_grs_process_coap(uint8_t *packet, uint16_t *packet_len, sn_nsdl_addr_s *src)
+ *
+ * \brief To push CoAP packet to GRS library
+ *
+ *  Used to push an CoAP packet to GRS library for processing.
+ *
+ *  \param  *packet     Pointer to a uint8_t array containing the packet (including the CoAP headers).
+ *                      After successful execution this array may contain the response packet.
+ *
+ *  \param  *packet_len Pointer to length of the packet. After successful execution this array may contain the length
+ *                      of the response packet.
+ *
+ *  \param  *src        Pointer to packet source address information. After successful execution this array may contain
+ *                      the destination address of the response packet.
+ *
+ *  \return             0 = success, -1 = failure
+*/
+extern int8_t sn_grs_process_coap(struct nsdl_s *nsdl_handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *src_addr_ptr)
+{
+    if( !coap_packet_ptr || !nsdl_handle){
+        return SN_NSDL_FAILURE;
+    }
+
+    sn_nsdl_dynamic_resource_parameters_s *resource_temp_ptr  = NULL;
+    sn_coap_msg_code_e      status              = COAP_MSG_CODE_EMPTY;
+    sn_coap_hdr_s           *response_message_hdr_ptr = NULL;
+    struct grs_s            *handle = nsdl_handle->grs;
+    bool                    static_get_request = false;
+
+    if (coap_packet_ptr->msg_code <= COAP_MSG_CODE_REQUEST_DELETE) {
+        /* Check if .well-known/core */
+        if (coap_packet_ptr->uri_path_len == WELLKNOWN_PATH_LEN && memcmp(coap_packet_ptr->uri_path_ptr, WELLKNOWN_PATH, WELLKNOWN_PATH_LEN) == 0) {
+            return sn_grs_core_request(nsdl_handle, src_addr_ptr, coap_packet_ptr);
+        }
+
+        /* Get resource */
+        char* path = nsdl_handle->grs->sn_grs_alloc(coap_packet_ptr->uri_path_len + 1);
+        if (!path) {
+            return SN_NSDL_FAILURE;
+        }
+
+        memcpy(path,
+               coap_packet_ptr->uri_path_ptr,
+               coap_packet_ptr->uri_path_len);
+        path[coap_packet_ptr->uri_path_len] = '\0';
+
+        resource_temp_ptr = sn_grs_search_resource(handle, path, SN_GRS_SEARCH_METHOD);
+        nsdl_handle->grs->sn_grs_free(path);
+
+        /* * * * * * * * * * * */
+        /* If resource exists  */
+        /* * * * * * * * * * * */
+        if (resource_temp_ptr) {
+            /* If dynamic resource, go to callback */
+            if (resource_temp_ptr->static_resource_parameters->mode == SN_GRS_DYNAMIC) {
+                /* Check accesses */
+                if (((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) && !(resource_temp_ptr->access & SN_GRS_GET_ALLOWED))          ||
+                        ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) && !(resource_temp_ptr->access & SN_GRS_POST_ALLOWED))   ||
+                        ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT) && !(resource_temp_ptr->access & SN_GRS_PUT_ALLOWED))     ||
+                        ((coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_DELETE) && !(resource_temp_ptr->access & SN_GRS_DELETE_ALLOWED))) {
+                    status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+                } else {
+                    /* Do not call null pointer.. */
+                    if (resource_temp_ptr->sn_grs_dyn_res_callback != NULL) {
+                        resource_temp_ptr->sn_grs_dyn_res_callback(nsdl_handle, coap_packet_ptr, src_addr_ptr, SN_NSDL_PROTOCOL_COAP);
+                    } else {
+                        if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
+                            handle->sn_grs_free(coap_packet_ptr->payload_ptr);
+                            coap_packet_ptr->payload_ptr = 0;
+                        }
+                        sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
+                    }
+
+                    return SN_NSDL_SUCCESS;
+                }
+            } else {
+                /* Static resource handling */
+                switch (coap_packet_ptr->msg_code) {
+                    case COAP_MSG_CODE_REQUEST_GET:
+                        if (resource_temp_ptr->access & SN_GRS_GET_ALLOWED) {
+                            status = COAP_MSG_CODE_RESPONSE_CONTENT;
+                            static_get_request = true;
+                        } else {
+                            status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+                        }
+                        break;
+
+                    case COAP_MSG_CODE_REQUEST_POST:
+                    case COAP_MSG_CODE_REQUEST_PUT:
+                    case COAP_MSG_CODE_REQUEST_DELETE:
+                        status = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+                        break;
+
+                    default:
+                        status = COAP_MSG_CODE_RESPONSE_FORBIDDEN;
+                        break;
+                }
+            }
+        }
+
+        /* * * * * * * * * * * * * * */
+        /* If resource was not found */
+        /* * * * * * * * * * * * * * */
+
+        else {
+            if (coap_packet_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) {
+                handle->sn_grs_rx_callback(nsdl_handle, coap_packet_ptr, src_addr_ptr);
+
+                if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
+                    handle->sn_grs_free(coap_packet_ptr->payload_ptr);
+                    coap_packet_ptr->payload_ptr = 0;
+                }
+
+                sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
+                return SN_NSDL_SUCCESS;
+            } else {
+                status = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
+            }
+        }
+    }
+
+    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+    /* If received packed was other than reset, create response  */
+    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+    if (coap_packet_ptr->msg_type != COAP_MSG_TYPE_RESET && coap_packet_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT) {
+
+        /* Allocate resopnse message  */
+        response_message_hdr_ptr = sn_coap_parser_alloc_message(handle->coap);
+        if (!response_message_hdr_ptr) {
+            if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
+                handle->sn_grs_free(coap_packet_ptr->payload_ptr);
+                coap_packet_ptr->payload_ptr = 0;
+            }
+            sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
+            return SN_NSDL_FAILURE;
+        }
+
+        /* If status has not been defined, response internal server error */
+        if (status == COAP_MSG_CODE_EMPTY) {
+            status = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
+        }
+
+        /* Fill header */
+        response_message_hdr_ptr->msg_code = status;
+
+        if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
+            response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
+        } else {
+            response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE;
+        }
+
+        response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id;
+
+        if (coap_packet_ptr->token_ptr) {
+            response_message_hdr_ptr->token_len = coap_packet_ptr->token_len;
+            response_message_hdr_ptr->token_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->token_len);
+            if (!response_message_hdr_ptr->token_ptr) {
+                sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr);
+
+                if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
+                    handle->sn_grs_free(coap_packet_ptr->payload_ptr);
+                    coap_packet_ptr->payload_ptr = 0;
+                }
+
+                sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
+                return SN_NSDL_FAILURE;
+            }
+            memcpy(response_message_hdr_ptr->token_ptr, coap_packet_ptr->token_ptr, response_message_hdr_ptr->token_len);
+        }
+
+        if (status == COAP_MSG_CODE_RESPONSE_CONTENT) {
+            /* Add content type if other than default */
+            if (resource_temp_ptr->static_resource_parameters) {
+                response_message_hdr_ptr->content_format =
+                    (sn_coap_content_format_e) resource_temp_ptr->coap_content_type;
+             }
+
+            /* Add payload */
+            if (resource_temp_ptr->resource_len != 0) {
+                response_message_hdr_ptr->payload_len = resource_temp_ptr->resource_len;
+                response_message_hdr_ptr->payload_ptr = handle->sn_grs_alloc(response_message_hdr_ptr->payload_len);
+
+                if (!response_message_hdr_ptr->payload_ptr) {
+                    sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr);
+
+                    if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
+                        handle->sn_grs_free(coap_packet_ptr->payload_ptr);
+                        coap_packet_ptr->payload_ptr = 0;
+                    }
+
+                    sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
+                    return SN_NSDL_FAILURE;
+                }
+
+                memcpy(response_message_hdr_ptr->payload_ptr,
+                       resource_temp_ptr->resource,
+                       response_message_hdr_ptr->payload_len);
+            }
+            // Add max-age attribute for static resources.
+            // Not a mandatory parameter, no need to return in case of memory allocation fails.
+            if (static_get_request) {
+                if (sn_coap_parser_alloc_options(handle->coap, response_message_hdr_ptr)) {
+                    response_message_hdr_ptr->options_list_ptr->max_age = 0;
+                }
+            }
+        }
+        sn_grs_send_coap_message(nsdl_handle, src_addr_ptr, response_message_hdr_ptr);
+
+        if (response_message_hdr_ptr->payload_ptr) {
+            handle->sn_grs_free(response_message_hdr_ptr->payload_ptr);
+            response_message_hdr_ptr->payload_ptr = 0;
+        }
+        sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, response_message_hdr_ptr);
+    }
+
+    /* Free parsed CoAP message */
+    if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
+        handle->sn_grs_free(coap_packet_ptr->payload_ptr);
+        coap_packet_ptr->payload_ptr = 0;
+    }
+    sn_coap_parser_release_allocated_coap_msg_mem(handle->coap, coap_packet_ptr);
+
+    return SN_NSDL_SUCCESS;
+}
+
+extern int8_t sn_grs_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr)
+{
+    uint8_t *message_ptr = NULL;
+    uint16_t message_len = 0;
+    int16_t ret_val = 0;
+
+    if( !handle ){
+        return SN_NSDL_FAILURE;
+    }
+
+#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */
+    ret_val = prepare_blockwise_message(handle->grs->coap, coap_hdr_ptr);
+    if( 0 != ret_val ) {
+        return SN_NSDL_FAILURE;
+    }
+#endif
+
+    /* Calculate message length */
+    message_len = sn_coap_builder_calc_needed_packet_data_size_2(coap_hdr_ptr, handle->grs->coap->sn_coap_block_data_size);
+
+    /* Allocate memory for message and check was allocating successfully */
+    message_ptr = handle->grs->sn_grs_alloc(message_len);
+    if (message_ptr == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+
+    /* Build CoAP message */
+    ret_val = sn_coap_protocol_build(handle->grs->coap, address_ptr, message_ptr, coap_hdr_ptr, (void *)handle);
+    if (ret_val < 0) {
+        handle->grs->sn_grs_free(message_ptr);
+        message_ptr = 0;
+        if (ret_val == -4) {
+            return SN_NSDL_RESEND_QUEUE_FULL;
+        } else {
+            return SN_NSDL_FAILURE;
+        }
+    }
+
+    /* Call tx callback function to send message */
+    ret_val = handle->grs->sn_grs_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, message_ptr, message_len, address_ptr);
+
+    /* Free allocated memory */
+    handle->grs->sn_grs_free(message_ptr);
+    message_ptr = 0;
+
+    if (ret_val == 0) {
+        return SN_NSDL_FAILURE;
+    } else {
+        return SN_NSDL_SUCCESS;
+    }
+}
+
+static int8_t sn_grs_core_request(struct nsdl_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *coap_packet_ptr)
+{
+    sn_coap_hdr_s           *response_message_hdr_ptr = NULL;
+    sn_coap_content_format_e wellknown_content_format = COAP_CT_LINK_FORMAT;
+
+    /* Allocate response message  */
+    response_message_hdr_ptr = sn_coap_parser_alloc_message(handle->grs->coap);
+    if (response_message_hdr_ptr == NULL) {
+        if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
+            handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr);
+            coap_packet_ptr->payload_ptr = 0;
+        }
+        sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
+        return SN_NSDL_FAILURE;
+    }
+
+    /* Build response */
+    response_message_hdr_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
+    response_message_hdr_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
+    response_message_hdr_ptr->msg_id = coap_packet_ptr->msg_id;
+    response_message_hdr_ptr->content_format = wellknown_content_format;
+
+    sn_nsdl_build_registration_body(handle, response_message_hdr_ptr, 0);
+
+    /* Send and free */
+    sn_grs_send_coap_message(handle, src_addr_ptr, response_message_hdr_ptr);
+
+    if (response_message_hdr_ptr->payload_ptr) {
+        handle->grs->sn_grs_free(response_message_hdr_ptr->payload_ptr);
+        response_message_hdr_ptr->payload_ptr = 0;
+    }
+    sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, response_message_hdr_ptr);
+
+    /* Free parsed CoAP message */
+    if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED && coap_packet_ptr->payload_ptr) {
+        handle->grs->sn_grs_free(coap_packet_ptr->payload_ptr);
+        coap_packet_ptr->payload_ptr = 0;
+    }
+    sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
+
+    return SN_NSDL_SUCCESS;
+}
+
+/**
+ * \fn  static sn_grs_resource_info_s *sn_grs_search_resource(struct grs_s *handle, const char *path, uint8_t search_method)
+ *
+ * \brief Searches given resource from linked list
+ *
+ *  Search either precise path, or subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc...
+ *
+ *  \param  pathlen         Length of the path to be search
+ *
+ *  \param  *path           Pointer to the path string to be search
+ *
+ *  \param  search_method   Search method, SEARCH or DELETE
+ *
+ *  \return                 Pointer to the resource. If resource not found, return value is NULL
+ *
+*/
+
+sn_nsdl_dynamic_resource_parameters_s *sn_grs_search_resource(struct grs_s *handle, const char *path, uint8_t search_method)
+{
+    /* Local variables */
+    char                     *path_temp_ptr          = NULL;
+    /* Check parameters */
+    if (!handle || !path) {
+        return NULL;
+    }
+    uint16_t pathlen = strlen(path);
+    /* Remove '/' - marks from the end and beginning */
+    path_temp_ptr = sn_grs_convert_uri(&pathlen, path);
+
+    /* Searchs exact path */
+    if (search_method == SN_GRS_SEARCH_METHOD) {
+        /* Scan all nodes on list */
+        ns_list_foreach(sn_nsdl_dynamic_resource_parameters_s, resource_search_temp, &handle->resource_root_list) {
+            /* If length equals.. */
+            size_t len = 0;
+            if(resource_search_temp &&
+                    resource_search_temp->static_resource_parameters &&
+                    resource_search_temp->static_resource_parameters->path) {
+                len = strlen(resource_search_temp->static_resource_parameters->path);
+            }
+
+            if (len == pathlen) {
+                /* Compare paths, If same return node pointer*/
+                if (0 == memcmp(resource_search_temp->static_resource_parameters->path,
+                                path_temp_ptr,
+                                pathlen)) {
+                    return resource_search_temp;
+                }
+            }
+        }
+    }
+    /* Search also subresources, eg. dr/x -> returns dr/x/1, dr/x/2 etc... */
+    else if (search_method == SN_GRS_DELETE_METHOD) {
+        /* Scan all nodes on list */
+        ns_list_foreach(sn_nsdl_dynamic_resource_parameters_s, resource_search_temp, &handle->resource_root_list) {
+            char *temp_path = resource_search_temp->static_resource_parameters->path;
+            if (strlen(resource_search_temp->static_resource_parameters->path) > pathlen &&
+                    (*(temp_path + (uint8_t)pathlen) == '/') &&
+                    0 == memcmp(resource_search_temp->static_resource_parameters->path,
+                                path_temp_ptr,
+                                pathlen)) {
+                return resource_search_temp;
+            }
+        }
+    }
+
+    /* If there was not nodes we wanted, return NULL */
+    return NULL;
+}
+
+/**
+ * \fn  static uint8_t *sn_grs_convert_uri(uint16_t *uri_len, uint8_t *uri_ptr)
+ *
+ * \brief Removes '/' from the beginning and from the end of uri string
+ *
+ *  \param  *uri_len            Pointer to the length of the path string
+ *
+ *  \param  *uri_ptr            Pointer to the path string
+ *
+ *  \return start pointer of the uri
+ *
+*/
+
+static char *sn_grs_convert_uri(uint16_t *uri_len, const char *uri_ptr)
+{
+    /* Local variables */
+    char *uri_start_ptr = (char *) uri_ptr;
+
+    /* If '/' in the beginning, update uri start pointer and uri len */
+    if (*uri_ptr == '/') {
+        uri_start_ptr = (char *) uri_ptr + 1;
+        *uri_len = *uri_len - 1;
+    }
+
+    /* If '/' at the end, update uri len */
+    if (*(uri_start_ptr + *uri_len - 1) == '/') {
+        *uri_len = *uri_len - 1;
+    }
+
+    /* Return start pointer */
+    return uri_start_ptr;
+}
+
+/**
+ * \fn  static int8_t sn_grs_resource_info_free(sn_grs_resource_info_s *resource_ptr)
+ *
+ * \brief Frees resource info structure
+ *
+ *  \param *resource_ptr    Pointer to the resource
+ *
+ *  \return 0 if success, -1 if failed
+ *
+*/
+static int8_t sn_grs_resource_info_free(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *resource_ptr)
+{
+    if (resource_ptr) {
+#ifdef MEMORY_OPTIMIZED_API
+        if (resource_ptr->free_on_delete) {
+            handle->sn_grs_free(resource_ptr);
+        }
+        return SN_NSDL_FAILURE;
+#else
+        if (resource_ptr->static_resource_parameters &&
+                resource_ptr->static_resource_parameters->free_on_delete) {
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+            if (resource_ptr->static_resource_parameters->interface_description_ptr) {
+                handle->sn_grs_free(resource_ptr->static_resource_parameters->interface_description_ptr);
+                resource_ptr->static_resource_parameters->interface_description_ptr = 0;
+            }
+#endif
+#ifndef DISABLE_RESOURCE_TYPE
+            if (resource_ptr->static_resource_parameters->resource_type_ptr) {
+                handle->sn_grs_free(resource_ptr->static_resource_parameters->resource_type_ptr);
+                resource_ptr->static_resource_parameters->resource_type_ptr = 0;
+            }
+#endif
+#else
+            sn_nsdl_free_resource_attributes_list(resource_ptr->static_resource_parameters);
+#endif
+            if (resource_ptr->static_resource_parameters->path) {
+                handle->sn_grs_free(resource_ptr->static_resource_parameters->path);
+                resource_ptr->static_resource_parameters->path = 0;
+            }
+
+            if (resource_ptr->resource) {
+                handle->sn_grs_free(resource_ptr->resource);
+                resource_ptr->resource = 0;
+            }
+
+            handle->sn_grs_free(resource_ptr->static_resource_parameters);
+            resource_ptr->static_resource_parameters = 0;
+        }
+        if (resource_ptr->free_on_delete) {
+            handle->sn_grs_free(resource_ptr);
+        }
+        return SN_NSDL_SUCCESS;
+#endif
+    }
+    return SN_NSDL_FAILURE; //Dead code?
+}
+
+void sn_grs_mark_resources_as_registered(struct nsdl_s *handle)
+{
+    if( !handle ){
+        return;
+    }
+
+    sn_nsdl_dynamic_resource_parameters_s *temp_resource;
+
+    temp_resource = sn_grs_get_first_resource(handle->grs);
+
+    while (temp_resource) {
+        if (temp_resource->registered == SN_NDSL_RESOURCE_REGISTERING) {
+            temp_resource->registered = SN_NDSL_RESOURCE_REGISTERED;
+        }
+        temp_resource = sn_grs_get_next_resource(handle->grs, temp_resource);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-c/source/sn_nsdl.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2566 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+/**
+ * \file sn_nsdl.c
+ *
+ * \brief Nano service device library
+ *
+ */
+
+// Needed for PRIu64 on FreeRTOS
+#include <stdio.h>
+// Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+
+// Note: this macro is needed on armcc to get the the PRI*32 macros
+// from inttypes.h in a C++ code.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <string.h>
+
+#include "ns_types.h"
+#include "sn_nsdl.h"
+#include "sn_coap_header.h"
+#include "sn_coap_protocol.h"
+#include "source/include/sn_coap_protocol_internal.h"
+#include "sn_nsdl_lib.h"
+#include "sn_grs.h"
+#include "mbed-trace/mbed_trace.h"
+#include "mbedtls/base64.h"
+#include "common_functions.h"
+#include "randLIB.h"
+
+#include <stdlib.h>
+
+
+/* Defines */
+#define TRACE_GROUP "mClt"
+#define RESOURCE_DIR_LEN                2
+#define EP_NAME_PARAMETERS_LEN          3
+#define ET_PARAMETER_LEN                3
+#define LT_PARAMETER_LEN                3
+#define DOMAIN_PARAMETER_LEN            2
+#define RT_PARAMETER_LEN                3
+#define IF_PARAMETER_LEN                3
+#define NAME_PARAMETER_LEN              5
+#define OBS_PARAMETER_LEN               3
+#define AOBS_PARAMETER_LEN              5
+#define COAP_CON_PARAMETER_LEN          3
+#define BS_EP_PARAMETER_LEN             3
+#define BS_QUEUE_MODE_PARAMETER_LEN     2
+#define RESOURCE_VALUE_PARAMETER_LEN    2
+
+#define SN_NSDL_EP_REGISTER_MESSAGE     1
+#define SN_NSDL_EP_UPDATE_MESSAGE       2
+
+#ifdef YOTTA_CFG_DISABLE_OBS_FEATURE
+#define COAP_DISABLE_OBS_FEATURE YOTTA_CFG_DISABLE_OBS_FEATURE
+#elif defined MBED_CONF_MBED_CLIENT_COAP_DISABLE_OBS_FEATURE
+#define COAP_DISABLE_OBS_FEATURE MBED_CONF_MBED_CLIENT_COAP_DISABLE_OBS_FEATURE
+#endif
+
+#ifdef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE
+#define MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE
+#elif defined MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+#define MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+#endif
+
+/* Constants */
+static uint8_t      ep_name_parameter_string[]  = {'e', 'p', '='};      /* Endpoint name. A unique name for the registering node in a domain.  */
+static uint8_t      resource_path_ptr[]         = {'r', 'd'};           /* For resource directory */
+static uint8_t      resource_type_parameter[]   = {'r', 't', '='};      /* Resource type. Only once for registration */
+#ifndef COAP_DISABLE_OBS_FEATURE
+static uint8_t      obs_parameter[]             = {'o', 'b', 's'};      /* Observable */
+static uint8_t      aobs_parameter[]            = {'a', 'o', 'b', 's', '='}; /* Auto observable */
+#endif
+static uint8_t      if_description_parameter[]  = {'i', 'f', '='};      /* Interface description. Only once */
+static uint8_t      ep_lifetime_parameter[]     = {'l', 't', '='};      /* Lifetime. Number of seconds that this registration will be valid for. Must be updated within this time, or will be removed. */
+static uint8_t      ep_domain_parameter[]       = {'d', '='};           /* Domain name. If this parameter is missing, a default domain is assumed. */
+static uint8_t      coap_con_type_parameter[]   = {'c', 't', '='};      /* CoAP content type */
+static uint8_t      resource_value[]            = {'v', '='};           /* Resource value */
+#ifdef RESOURCE_ATTRIBUTES_LIST
+static uint8_t      name_parameter[]            = {'n', 'a', 'm', 'e', '='};
+#endif
+
+/* * OMA BS parameters * */
+static uint8_t bs_uri[]                         = {'b', 's'};
+static uint8_t bs_ep_name[]                     = {'e', 'p', '='};
+static uint8_t et_parameter[]                   = {'e', 't', '='};      /* Endpoint type */
+static uint8_t bs_queue_mode[]                  = {'b', '='};
+
+/* Function prototypes */
+static int32_t          sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr);
+static void             sn_nsdl_resolve_nsp_address(struct nsdl_s *handle);
+int8_t                  sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration);
+static uint16_t         sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration, int8_t *error);
+static uint8_t          sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type, const char *uri_query);
+static int8_t           sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type, const char *uri_query);
+static int8_t           sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr);
+static int8_t           sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr);
+static uint8_t          sn_nsdl_itoa_len(uint32_t value);
+static uint8_t          *sn_nsdl_itoa(uint8_t *ptr, uint32_t value);
+static int8_t           set_endpoint_info(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr);
+static bool             validateParameters(sn_nsdl_ep_parameters_s *parameter_ptr);
+static bool             validate(uint8_t* ptr, uint32_t len, char illegalChar);
+static bool             sn_nsdl_check_uint_overflow(uint16_t resource_size, uint16_t param_a, uint16_t param_b);
+static void             remove_previous_block_data(struct nsdl_s *handle, sn_nsdl_addr_s *src_ptr, const uint32_t block_number);
+static bool             update_last_block_data(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, bool block1);
+#if defined(FEA_TRACE_SUPPORT) || MBED_CONF_MBED_TRACE_ENABLE || YOTTA_CFG_MBED_TRACE || (defined(YOTTA_CFG) && !defined(NDEBUG))
+static const char*      sn_nsdl_coap_status_description(sn_coap_status_e status);
+static const char*      sn_nsdl_coap_message_code_desc(int msg_code);
+static const char*      sn_nsdl_coap_message_type_desc(int msg_type);
+#endif
+
+static void             sn_nsdl_add_token(struct nsdl_s *handle, uint32_t *token, sn_coap_hdr_s *message_ptr);
+
+int8_t sn_nsdl_destroy(struct nsdl_s *handle)
+{
+    if (handle == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+
+    if (handle->ep_information_ptr) {
+        handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr);
+        handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr);
+        handle->sn_nsdl_free(handle->ep_information_ptr->location_ptr);
+        handle->sn_nsdl_free(handle->ep_information_ptr->type_ptr);
+        handle->sn_nsdl_free(handle->ep_information_ptr->lifetime_ptr);
+        handle->sn_nsdl_free(handle->ep_information_ptr);
+    }
+
+    if (handle->server_address.addr_ptr) {
+        handle->sn_nsdl_free(handle->server_address.addr_ptr);
+        handle->server_address.addr_ptr = NULL;
+        handle->server_address.type = SN_NSDL_ADDRESS_TYPE_NONE;
+    }
+
+    /* Destroy also libCoap and grs part of libNsdl */
+    sn_coap_protocol_destroy(handle->grs->coap);
+    sn_grs_destroy(handle->grs);
+    handle->sn_nsdl_free(handle);
+
+    return SN_NSDL_SUCCESS;
+}
+
+struct nsdl_s *sn_nsdl_init(uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *),
+                            uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *),
+                            void *(*sn_nsdl_alloc)(uint16_t), void (*sn_nsdl_free)(void *),
+                            uint8_t (*sn_nsdl_auto_obs_token_cb)(struct nsdl_s *, const char *, uint8_t *))
+{
+    /* Check pointers and define function pointers */
+    if (!sn_nsdl_alloc || !sn_nsdl_free || !sn_nsdl_tx_cb || !sn_nsdl_rx_cb) {
+        return NULL;
+    }
+
+    struct nsdl_s *handle = NULL;
+
+    handle = sn_nsdl_alloc(sizeof(struct nsdl_s));
+
+    if (handle == NULL) {
+        return NULL;
+    }
+
+    memset(handle, 0, sizeof(struct nsdl_s));
+
+    /* Define function pointers */
+    handle->sn_nsdl_alloc = sn_nsdl_alloc;
+    handle->sn_nsdl_free = sn_nsdl_free;
+
+    handle->sn_nsdl_tx_callback = sn_nsdl_tx_cb;
+    handle->sn_nsdl_rx_callback = sn_nsdl_rx_cb;
+    handle->sn_nsdl_auto_obs_token_callback = sn_nsdl_auto_obs_token_cb;
+
+    /* Initialize ep parameters struct */
+    if (!handle->ep_information_ptr) {
+        handle->ep_information_ptr = handle->sn_nsdl_alloc(sizeof(sn_nsdl_ep_parameters_s));
+        if (!handle->ep_information_ptr) {
+            sn_nsdl_free(handle);
+            return NULL;
+        }
+        memset(handle->ep_information_ptr, 0, sizeof(sn_nsdl_ep_parameters_s));
+    }
+
+    handle->grs = sn_grs_init(sn_nsdl_tx_cb, &sn_nsdl_local_rx_function, sn_nsdl_alloc, sn_nsdl_free);
+
+    /* Initialize GRS */
+    if (handle->grs == NULL) {
+        handle->sn_nsdl_free(handle->ep_information_ptr);
+        handle->ep_information_ptr = 0;
+        sn_nsdl_free(handle);
+        return NULL;
+    }
+
+    sn_nsdl_resolve_nsp_address(handle);
+
+    handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED;
+    handle->context = NULL;
+
+    randLIB_get_n_bytes_random(&handle->token_seed, sizeof(handle->token_seed));
+    if (handle->token_seed == 0) {
+        handle->token_seed++;
+    }
+    return handle;
+}
+
+uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle,
+                                   sn_nsdl_ep_parameters_s *endpoint_info_ptr,
+                                   const char *uri_query_parameters)
+{
+    /* Local variables */
+    sn_coap_hdr_s   *register_message_ptr;
+    uint16_t        message_id  = 0;
+
+    if (endpoint_info_ptr == NULL || handle == NULL) {
+        return 0;
+    }
+
+    /*** Build endpoint register message ***/
+
+    handle->is_bs_server = false;
+
+    /* Allocate memory for header struct */
+    register_message_ptr = sn_coap_parser_alloc_message(handle->grs->coap);
+    if (register_message_ptr == NULL) {
+        return 0;
+    }
+
+    /* Fill message fields -> confirmable post to specified NSP path */
+    register_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
+    register_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST;
+
+    /* Allocate memory for the extended options list */
+    if (sn_coap_parser_alloc_options(handle->grs->coap, register_message_ptr) == NULL) {
+        sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
+        register_message_ptr = 0;
+        return 0;
+    }
+
+    register_message_ptr->uri_path_len = sizeof(resource_path_ptr);
+    register_message_ptr->uri_path_ptr = resource_path_ptr;
+
+    /* Fill Uri-query options */
+    if( SN_NSDL_FAILURE == sn_nsdl_fill_uri_query_options(handle, endpoint_info_ptr,
+                                                          register_message_ptr, SN_NSDL_EP_REGISTER_MESSAGE,
+                                                          uri_query_parameters) ){
+        register_message_ptr->uri_path_ptr = NULL;
+        sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
+        return 0;
+    }
+
+    if (endpoint_info_ptr->ds_register_mode == REGISTER_WITH_RESOURCES) {
+        /* Built body for message */
+        if (sn_nsdl_build_registration_body(handle, register_message_ptr, 0) == SN_NSDL_FAILURE) {
+            register_message_ptr->uri_path_ptr = NULL;
+            register_message_ptr->options_list_ptr->uri_host_ptr = NULL;
+            sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
+            return 0;
+        }
+    }
+
+    /* Clean (possible) existing and save new endpoint info to handle */
+    if (set_endpoint_info(handle, endpoint_info_ptr) == -1) {
+
+        handle->sn_nsdl_free(register_message_ptr->payload_ptr);
+        register_message_ptr->payload_ptr = NULL;
+
+        register_message_ptr->uri_path_ptr = NULL;
+        register_message_ptr->options_list_ptr->uri_host_ptr = NULL;
+
+        sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
+
+        return 0;
+    }
+
+    sn_nsdl_add_token(handle, &handle->register_token, register_message_ptr);
+
+    /* Build and send coap message to NSP */
+    message_id = sn_nsdl_internal_coap_send(handle, register_message_ptr, &handle->server_address);
+
+    handle->sn_nsdl_free(register_message_ptr->payload_ptr);
+    register_message_ptr->payload_ptr = NULL;
+
+    register_message_ptr->uri_path_ptr = NULL;
+    register_message_ptr->options_list_ptr->uri_host_ptr = NULL;
+
+    register_message_ptr->token_ptr = NULL;
+    register_message_ptr->token_len = 0;
+
+    sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
+
+    return message_id;
+}
+
+int32_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle)
+{
+    /* Local variables */
+    sn_coap_hdr_s   *unregister_message_ptr;
+    uint8_t         *temp_ptr = 0;
+    int32_t        message_id = 0;
+
+    /* Check parameters */
+    if (handle == NULL) {
+        return 0;
+    }
+
+    /* Check that EP have been registered */
+    if (sn_nsdl_is_ep_registered(handle)) {
+
+        /* Memory allocation for unregister message */
+        unregister_message_ptr = sn_coap_parser_alloc_message(handle->grs->coap);
+        if (!unregister_message_ptr) {
+            return 0;
+        }
+
+        /* Fill unregister message */
+        unregister_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
+        unregister_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_DELETE;
+
+        if(handle->ep_information_ptr->location_ptr) {
+            unregister_message_ptr->uri_path_len = handle->ep_information_ptr->location_len;
+            unregister_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(unregister_message_ptr->uri_path_len);
+            if (!unregister_message_ptr->uri_path_ptr) {
+                sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr);
+                return 0;
+            }
+
+            temp_ptr = unregister_message_ptr->uri_path_ptr;
+
+            memcpy(temp_ptr , handle->ep_information_ptr->location_ptr, handle->ep_information_ptr->location_len);
+        } else {
+            unregister_message_ptr->uri_path_len = (RESOURCE_DIR_LEN + 1 + handle->ep_information_ptr->domain_name_len + 1 + handle->ep_information_ptr->endpoint_name_len);
+            unregister_message_ptr->uri_path_ptr = handle->sn_nsdl_alloc(unregister_message_ptr->uri_path_len);
+            if (!unregister_message_ptr->uri_path_ptr) {
+                sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr);
+                return 0;
+            }
+
+            temp_ptr = unregister_message_ptr->uri_path_ptr;
+
+            memcpy(temp_ptr, resource_path_ptr, RESOURCE_DIR_LEN);
+            temp_ptr += RESOURCE_DIR_LEN;
+
+            *temp_ptr++ = '/';
+
+            memcpy(temp_ptr , handle->ep_information_ptr->domain_name_ptr, handle->ep_information_ptr->domain_name_len);
+            temp_ptr += handle->ep_information_ptr->domain_name_len;
+
+            *temp_ptr++ = '/';
+
+            memcpy(temp_ptr , handle->ep_information_ptr->endpoint_name_ptr, handle->ep_information_ptr->endpoint_name_len);
+        }
+
+        sn_nsdl_add_token(handle, &handle->unregister_token, unregister_message_ptr);
+
+        /* Send message */
+        message_id = sn_nsdl_internal_coap_send(handle, unregister_message_ptr, &handle->server_address);
+
+        unregister_message_ptr->token_ptr = NULL;
+        unregister_message_ptr->token_len = 0;
+
+        /* Free memory */
+        sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, unregister_message_ptr);
+
+    }
+
+    return message_id;
+}
+
+int32_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len)
+{
+    /* Local variables */
+    sn_coap_hdr_s   *register_message_ptr;
+    uint8_t         *temp_ptr;
+    sn_nsdl_ep_parameters_s temp_parameters;
+    int32_t        message_id = 0;
+
+    /* Check parameters */
+    if (handle == NULL) {
+        return 0;
+    }
+
+    if (!sn_nsdl_is_ep_registered(handle)){
+        return 0;
+    }
+
+    memset(&temp_parameters, 0, sizeof(sn_nsdl_ep_parameters_s));
+
+    temp_parameters.lifetime_len = lt_len;
+    temp_parameters.lifetime_ptr = lt_ptr;
+
+    if (handle->ep_information_ptr) {
+        temp_parameters.type_len = handle->ep_information_ptr->type_len;
+        temp_parameters.type_ptr = handle->ep_information_ptr->type_ptr;
+    }
+
+    /*** Build endpoint register update message ***/
+
+    /* Allocate memory for header struct */
+    register_message_ptr = sn_coap_parser_alloc_message(handle->grs->coap);
+    if (register_message_ptr == NULL) {
+        return 0;
+    }
+
+    /* Fill message fields -> confirmable post to specified NSP path */
+    register_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
+    register_message_ptr->msg_code = COAP_MSG_CODE_REQUEST_POST;
+
+    if(handle->ep_information_ptr->location_ptr) {
+        register_message_ptr->uri_path_len  =   handle->ep_information_ptr->location_len;    /* = Only location set by Device Server*/
+
+        register_message_ptr->uri_path_ptr  =   handle->sn_nsdl_alloc(register_message_ptr->uri_path_len);
+        if (!register_message_ptr->uri_path_ptr) {
+            sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
+            return 0;
+        }
+
+        temp_ptr = register_message_ptr->uri_path_ptr;
+
+        /* location */
+        memcpy(temp_ptr, handle->ep_information_ptr->location_ptr, handle->ep_information_ptr->location_len);
+    } else {
+        register_message_ptr->uri_path_len  =   sizeof(resource_path_ptr) + handle->ep_information_ptr->domain_name_len + handle->ep_information_ptr->endpoint_name_len + 2;    /* = rd/domain/endpoint */
+
+        register_message_ptr->uri_path_ptr  =   handle->sn_nsdl_alloc(register_message_ptr->uri_path_len);
+        if (!register_message_ptr->uri_path_ptr) {
+            sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
+            return 0;
+        }
+
+        temp_ptr = register_message_ptr->uri_path_ptr;
+
+        /* rd/ */
+        memcpy(temp_ptr, resource_path_ptr, sizeof(resource_path_ptr));
+        temp_ptr += sizeof(resource_path_ptr);
+        *temp_ptr++ = '/';
+
+        /* rd/DOMAIN/ */
+        memcpy(temp_ptr, handle->ep_information_ptr->domain_name_ptr, handle->ep_information_ptr->domain_name_len);
+        temp_ptr += handle->ep_information_ptr->domain_name_len;
+        *temp_ptr++ = '/';
+
+        /* rd/domain/ENDPOINT */
+        memcpy(temp_ptr, handle->ep_information_ptr->endpoint_name_ptr, handle->ep_information_ptr->endpoint_name_len);
+    }
+
+    /* Allocate memory for the extended options list */
+    if (sn_coap_parser_alloc_options(handle->grs->coap, register_message_ptr) == NULL) {
+        sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
+        return 0;
+    }
+
+    /* Fill Uri-query options */
+    sn_nsdl_fill_uri_query_options(handle, &temp_parameters, register_message_ptr, SN_NSDL_EP_UPDATE_MESSAGE, NULL);
+
+    /* Build payload */
+    if (handle->ep_information_ptr->ds_register_mode == REGISTER_WITH_RESOURCES) {
+        if (sn_nsdl_build_registration_body(handle, register_message_ptr, 1) == SN_NSDL_FAILURE) {
+            sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
+            return 0;
+        }
+    }
+
+    sn_nsdl_add_token(handle, &handle->update_register_token, register_message_ptr);
+
+    /* Build and send coap message to NSP */
+    message_id = sn_nsdl_internal_coap_send(handle, register_message_ptr, &handle->server_address);
+
+    register_message_ptr->token_ptr = NULL;
+    register_message_ptr->token_len = 0;
+
+    handle->sn_nsdl_free(register_message_ptr->payload_ptr);
+
+    sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, register_message_ptr);
+
+    return message_id;
+}
+
+int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len)
+{
+    if(!handle || !location_ptr || (location_len == 0)) {
+        return -1;
+    }
+
+    handle->sn_nsdl_free(handle->ep_information_ptr->location_ptr);
+    handle->ep_information_ptr->location_ptr = handle->sn_nsdl_alloc(location_len);
+    memcpy(handle->ep_information_ptr->location_ptr, location_ptr, location_len);
+    handle->ep_information_ptr->location_len = location_len;
+
+    return 0;
+}
+
+void sn_nsdl_nsp_lost(struct nsdl_s *handle)
+{
+    /* Check parameters */
+    if (handle == NULL) {
+        return;
+    }
+
+    handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED;
+}
+
+int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle)
+{
+    /* Check parameters */
+    if (handle == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+
+    return handle->sn_nsdl_endpoint_registered;
+}
+
+int32_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len,
+   uint8_t *payload_ptr, uint16_t payload_len, sn_coap_observe_e observe, sn_coap_msg_type_e message_type,
+   sn_coap_content_format_e content_format,
+   const int32_t message_id)
+{
+    sn_coap_hdr_s   *notification_message_ptr;
+    int32_t         return_msg_id = 0;
+
+    /* Check parameters */
+    if (handle == NULL || handle->grs == NULL || token_len == 0) {
+        return 0;
+    }
+
+    /* Allocate and initialize memory for header struct */
+    notification_message_ptr = sn_coap_parser_alloc_message(handle->grs->coap);
+    if (notification_message_ptr == NULL) {
+        return 0;
+    }
+
+    if (sn_coap_parser_alloc_options(handle->grs->coap, notification_message_ptr) == NULL) {
+        handle->sn_nsdl_free(notification_message_ptr);
+        return 0;
+    }
+
+    /* Fill header */
+    notification_message_ptr->msg_type = message_type;
+    notification_message_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
+
+    /* Fill token */
+    notification_message_ptr->token_len = token_len;
+    notification_message_ptr->token_ptr = token_ptr;
+
+    /* Fill payload */
+    notification_message_ptr->payload_len = payload_len;
+    notification_message_ptr->payload_ptr = payload_ptr;
+
+    /* Fill observe */
+    notification_message_ptr->options_list_ptr->observe = observe;
+
+    /* Fill content format */
+    notification_message_ptr->content_format = content_format;
+
+    if (message_id != -1) {
+        notification_message_ptr->msg_id = message_id;
+    }
+
+    /* Send message */
+    return_msg_id = sn_nsdl_send_coap_message(handle, &handle->server_address, notification_message_ptr);
+    if (return_msg_id >= SN_NSDL_SUCCESS) {
+        return_msg_id = notification_message_ptr->msg_id;
+    }
+
+    /* Free memory */
+    notification_message_ptr->payload_ptr = NULL;
+    notification_message_ptr->token_ptr = NULL;
+
+    sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, notification_message_ptr);
+
+    return return_msg_id;
+}
+
+/* * * * * * * * * * */
+/* ~ OMA functions ~ */
+/* * * * * * * * * * */
+
+uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle,
+                               sn_nsdl_addr_s *bootstrap_address_ptr,
+                               sn_nsdl_ep_parameters_s *endpoint_info_ptr,
+                               const char *uri_query_parameters)
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    /* Local variables */
+    sn_coap_hdr_s bootstrap_coap_header;
+    uint8_t *uri_query_tmp_ptr;
+    uint16_t message_id = 0;
+
+    /* Check parameters */
+    if (!bootstrap_address_ptr || !endpoint_info_ptr || !handle) {
+        return 0;
+    }
+
+    if (set_NSP_address(handle,
+                        bootstrap_address_ptr->addr_ptr,
+                        bootstrap_address_ptr->addr_len,
+                        bootstrap_address_ptr->port,
+                        bootstrap_address_ptr->type) == SN_NSDL_FAILURE) {
+        return 0;
+    }
+
+    handle->is_bs_server = true;
+
+    /* XXX FIX -- Init CoAP header struct */
+    sn_coap_parser_init_message(&bootstrap_coap_header);
+
+    if (!sn_coap_parser_alloc_options(handle->grs->coap, &bootstrap_coap_header)) {
+        return 0;
+    }
+
+    /* Build bootstrap start message */
+    bootstrap_coap_header.msg_code = COAP_MSG_CODE_REQUEST_POST;
+    bootstrap_coap_header.msg_type = COAP_MSG_TYPE_CONFIRMABLE;
+
+    bootstrap_coap_header.uri_path_ptr = bs_uri;
+    bootstrap_coap_header.uri_path_len = sizeof(bs_uri);
+
+    size_t query_len = endpoint_info_ptr->endpoint_name_len + BS_EP_PARAMETER_LEN;
+    size_t optional_params_len = 0;
+    if (uri_query_parameters) {
+        optional_params_len = strlen(uri_query_parameters);
+    }
+
+    query_len += optional_params_len;
+
+    if (query_len > MAX_URI_QUERY_LEN) {
+        handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr);
+        tr_error("sn_nsdl_oma_bootstrap - max param length reached (%lu)", (unsigned long)query_len);
+        return 0;
+    }
+
+    uri_query_tmp_ptr = handle->sn_nsdl_alloc(query_len);
+    if (!uri_query_tmp_ptr) {
+        handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr);
+        return 0;
+    }
+
+    memcpy(uri_query_tmp_ptr, bs_ep_name, BS_EP_PARAMETER_LEN);
+    memcpy((uri_query_tmp_ptr + BS_EP_PARAMETER_LEN),
+           endpoint_info_ptr->endpoint_name_ptr,
+           endpoint_info_ptr->endpoint_name_len);
+
+    if (optional_params_len > 0) {
+        memcpy(uri_query_tmp_ptr + endpoint_info_ptr->endpoint_name_len + BS_EP_PARAMETER_LEN,
+               uri_query_parameters,
+               optional_params_len);
+    }
+
+    bootstrap_coap_header.options_list_ptr->uri_query_len = query_len;
+    bootstrap_coap_header.options_list_ptr->uri_query_ptr = uri_query_tmp_ptr;
+
+    /* Save bootstrap server address */
+    sn_nsdl_add_token(handle, &handle->bootstrap_token, &bootstrap_coap_header);
+
+    /* Send message */
+    message_id = sn_nsdl_internal_coap_send(handle, &bootstrap_coap_header, bootstrap_address_ptr);
+
+    /* Free allocated memory */
+    handle->sn_nsdl_free(uri_query_tmp_ptr);
+    handle->sn_nsdl_free(bootstrap_coap_header.options_list_ptr);
+
+    return message_id;
+#else
+    return 0;
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+
+}
+
+char *sn_nsdl_get_version(void)
+{
+#if defined(YOTTA_MBED_CLIENT_C_VERSION_STRING)
+    return YOTTA_MBED_CLIENT_C_VERSION_STRING;
+#elif defined(VERSION)
+    return VERSION;
+#else
+    return "0.0.0";
+#endif
+}
+
+int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet_ptr, uint16_t packet_len, sn_nsdl_addr_s *src_ptr)
+{
+    sn_coap_hdr_s           *coap_packet_ptr    = NULL;
+    sn_coap_hdr_s           *coap_response_ptr  = NULL;
+    sn_nsdl_dynamic_resource_parameters_s *resource = NULL;
+    /* Check parameters */
+    if (handle == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+
+    /* Parse CoAP packet */
+    coap_packet_ptr = sn_coap_protocol_parse(handle->grs->coap, src_ptr, packet_len, packet_ptr, (void *)handle);
+
+    /* Check if parsing was successfull */
+    if (coap_packet_ptr == (sn_coap_hdr_s *)NULL) {
+        return SN_NSDL_FAILURE;
+    }
+    sn_nsdl_print_coap_data(coap_packet_ptr, false);
+
+#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+    // Pass block to application if external_memory_block is set
+    if((coap_packet_ptr->options_list_ptr &&
+        coap_packet_ptr->options_list_ptr->block1 != -1) &&
+        (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING ||
+        coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED)) {
+        // Block 1 handling
+        /* Get resource */
+        char* path = handle->sn_nsdl_alloc(coap_packet_ptr->uri_path_len + 1);
+        if (!path) {
+            return SN_NSDL_FAILURE;
+        }
+
+        memcpy(path,
+                coap_packet_ptr->uri_path_ptr,
+                coap_packet_ptr->uri_path_len);
+        path[coap_packet_ptr->uri_path_len] = '\0';
+
+
+        resource = sn_nsdl_get_resource(handle, path);
+        handle->sn_nsdl_free(path);
+
+        if (coap_packet_ptr->options_list_ptr) {
+            if(resource &&
+               resource->static_resource_parameters->external_memory_block &&
+               coap_packet_ptr->options_list_ptr->block1) {
+
+                uint32_t block_number = coap_packet_ptr->options_list_ptr->block1 >> 4;
+                if (block_number) {
+                    remove_previous_block_data(handle, src_ptr, block_number);
+                }
+
+                // Whole message received --> pass only the last block data to application
+                if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) {
+                    // Get the block size
+                    uint8_t temp = (coap_packet_ptr->options_list_ptr->block1 & 0x07);
+                    uint16_t block_size = 1u << (temp + 4);
+
+                    uint32_t new_payload_len = coap_packet_ptr->payload_len - block_size;
+                    uint8_t *temp_ptr =  handle->grs->coap->sn_coap_protocol_malloc(new_payload_len);
+                    if (temp_ptr) {
+                        // Skip the second last block data since it's still stored in mbed-coap list!
+                        memcpy(temp_ptr, coap_packet_ptr->payload_ptr + block_size, new_payload_len);
+                        handle->grs->coap->sn_coap_protocol_free(coap_packet_ptr->payload_ptr);
+                        coap_packet_ptr->payload_ptr = NULL;
+
+                        coap_packet_ptr->payload_ptr = handle->grs->coap->sn_coap_protocol_malloc(new_payload_len);
+                        if (coap_packet_ptr->payload_ptr) {
+                            memcpy(coap_packet_ptr->payload_ptr, temp_ptr, new_payload_len);
+                            coap_packet_ptr->payload_len = new_payload_len;
+                        }
+
+                        handle->grs->coap->sn_coap_protocol_free(temp_ptr);
+                    }
+                }
+            } else {
+                resource = NULL;
+            }
+        } else {
+            resource = NULL;
+        }
+    }
+#endif
+
+    // Handling of GET responses
+    if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CONTENT) {
+        bool data_updated = false;
+        if (coap_packet_ptr->options_list_ptr && coap_packet_ptr->options_list_ptr->block2 != -1) {
+            uint32_t block_number = coap_packet_ptr->options_list_ptr->block2 >> 4;
+            if (block_number) {
+                remove_previous_block_data(handle, src_ptr, block_number);
+            }
+
+            // Modify payload to have only last received block data
+            data_updated = update_last_block_data(handle, coap_packet_ptr, false);
+        }
+
+        handle->sn_nsdl_rx_callback(handle, coap_packet_ptr, src_ptr);
+        if (data_updated) {
+            handle->grs->coap->sn_coap_protocol_free(coap_packet_ptr->payload_ptr);
+        }
+
+#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+        // Remove sent blockwise message(GET request) from the linked list.
+        sn_coap_protocol_remove_sent_blockwise_message(handle->grs->coap, coap_packet_ptr->msg_id);
+#endif
+
+        sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
+        return SN_NSDL_SUCCESS;
+    }
+
+    /* Check, if coap itself sends response, or block receiving is ongoing... */
+    if (coap_packet_ptr->coap_status != COAP_STATUS_OK &&
+        coap_packet_ptr->coap_status != COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED &&
+        coap_packet_ptr &&
+        !resource) {
+        sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
+        return SN_NSDL_SUCCESS;
+    }
+
+    /* If proxy options added, return not supported */
+    if (coap_packet_ptr->options_list_ptr) {
+        if (coap_packet_ptr->options_list_ptr->proxy_uri_len) {
+            coap_response_ptr = sn_coap_build_response(handle->grs->coap, coap_packet_ptr, COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED);
+            if (coap_response_ptr) {
+                sn_nsdl_send_coap_message(handle, src_ptr, coap_response_ptr);
+                sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_response_ptr);
+                sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
+                return SN_NSDL_SUCCESS;
+            } else {
+                sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
+                return SN_NSDL_FAILURE;
+            }
+        }
+    }
+
+    /* * * * * * * * * * * * * * * * * * * * * * * * * * */
+    /* If message is response message, call RX callback  */
+    /* * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+    if (((coap_packet_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) ||
+            (coap_packet_ptr->msg_type >= COAP_MSG_TYPE_ACKNOWLEDGEMENT))) {
+        int8_t retval = sn_nsdl_local_rx_function(handle, coap_packet_ptr, src_ptr);
+        if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED &&
+                coap_packet_ptr->payload_ptr) {
+            handle->sn_nsdl_free(coap_packet_ptr->payload_ptr);
+            coap_packet_ptr->payload_ptr = 0;
+        }
+        sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
+        return retval;
+    }
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    /* * If OMA bootstrap message... * */
+    bool bootstrap_msg = handle->is_bs_server;
+
+    // Pass bootstrap data to application
+    if (bootstrap_msg) {
+        // If retval is 2 skip the freeing, it will be done in MBED_CLIENT_NSDLINTERFACE_BS_PUT_EVENT event
+        if (handle->sn_nsdl_rx_callback(handle, coap_packet_ptr,src_ptr) != 2) {
+            if (coap_packet_ptr &&
+                coap_packet_ptr->options_list_ptr &&
+                coap_packet_ptr->coap_status != COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED &&
+                coap_packet_ptr->options_list_ptr->block1 != -1) {
+                    handle->sn_nsdl_free(coap_packet_ptr->payload_ptr);
+                    coap_packet_ptr->payload_ptr = NULL;
+            }
+            sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, coap_packet_ptr);
+        }
+
+        return SN_NSDL_SUCCESS;
+    }
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+
+    /* * * * * * * * * * * * * * * */
+    /* Other messages are for GRS  */
+    /* * * * * * * * * * * * * * * */
+    return sn_grs_process_coap(handle, coap_packet_ptr, src_ptr);
+}
+
+int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time)
+{
+    if(!handle || !handle->grs){
+        return SN_NSDL_FAILURE;
+    }
+    /* Call CoAP execution function */
+    return sn_coap_protocol_exec(handle->grs->coap, time);
+}
+
+sn_nsdl_dynamic_resource_parameters_s *sn_nsdl_get_resource(struct nsdl_s *handle, const char *path_ptr)
+{
+    /* Check parameters */
+    if (handle == NULL) {
+        return NULL;
+    }
+
+    return sn_grs_search_resource(handle->grs, path_ptr, SN_GRS_SEARCH_METHOD);
+}
+
+
+/**
+ * \fn static int32_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr)
+ *
+ *
+ * \brief To send NSDL messages. Stores message id?s and message description to catch response from NSP server
+ * \param   *handle             Pointer to nsdl-library handle
+ * \param   *coap_header_ptr    Pointer to the CoAP message header to be sent
+ * \param   *dst_addr_ptr       Pointer to the address structure that contains destination address information
+ * \param   message_description Message description to be stored to list for waiting response
+ *
+ * \return  message id, <=0 if failed
+ */
+static int32_t sn_nsdl_internal_coap_send(struct nsdl_s *handle, sn_coap_hdr_s *coap_header_ptr, sn_nsdl_addr_s *dst_addr_ptr)
+{
+
+    tr_debug("sn_nsdl_internal_coap_send");
+    uint8_t     *coap_message_ptr   = NULL;
+    int32_t     coap_message_len    = 0;
+
+#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not used at all, this part of code will not be compiled */
+    int8_t ret_val = prepare_blockwise_message(handle->grs->coap, coap_header_ptr);
+    if( 0 != ret_val ) {
+        return 0;
+    }
+#endif
+
+    coap_message_len = sn_coap_builder_calc_needed_packet_data_size_2(coap_header_ptr, handle->grs->coap->sn_coap_block_data_size);
+    tr_debug("sn_nsdl_internal_coap_send - msg len after calc: %" PRId32 "", coap_message_len);
+    if (coap_message_len == 0) {
+        return 0;
+    }
+
+    coap_message_ptr = handle->sn_nsdl_alloc(coap_message_len);
+    if (!coap_message_ptr) {
+        return 0;
+    }
+
+    /* Build message */
+    int16_t ret = sn_coap_protocol_build(handle->grs->coap, dst_addr_ptr, coap_message_ptr, coap_header_ptr, (void *)handle);
+    if (ret < 0) {
+        handle->sn_nsdl_free(coap_message_ptr);
+        return ret;
+    }
+
+    handle->sn_nsdl_tx_callback(handle, SN_NSDL_PROTOCOL_COAP, coap_message_ptr, coap_message_len, dst_addr_ptr);
+    handle->sn_nsdl_free(coap_message_ptr);
+
+    return coap_header_ptr->msg_id;
+}
+
+/**
+ * \fn static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle)
+ *
+ * \brief Resolves NSP server address.
+ *
+ * \param *handle Pointer to nsdl-library handle
+ * \note Application must set NSP address with set_nsp_address
+ */
+static void sn_nsdl_resolve_nsp_address(struct nsdl_s *handle)
+{
+    memset(&handle->server_address, 0, sizeof(sn_nsdl_addr_s));
+    handle->server_address.type = SN_NSDL_ADDRESS_TYPE_NONE;
+}
+
+#ifdef RESOURCE_ATTRIBUTES_LIST
+static char *sn_nsdl_build_resource_attribute_str(char *dst, const sn_nsdl_attribute_item_s *attribute, const char *name, const size_t name_len)
+{
+    if (attribute != NULL && name != NULL && name_len > 0 && attribute->value) {
+        size_t attribute_len = strlen(attribute->value);
+        *dst++ = ';';
+        memcpy(dst, name, name_len);
+        dst += name_len;
+        *dst++ = '"';
+        memcpy(dst,
+               attribute->value,
+               attribute_len);
+        dst += attribute_len;
+        *dst++ = '"';
+    }
+    return dst;
+}
+#endif
+
+/**
+ * \fn int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration)
+ *
+ * \brief   To build GRS resources to registration message payload
+ * \param *handle Pointer to nsdl-library handle
+ * \param   *message_ptr Pointer to CoAP message header
+ *
+ * \return  SN_NSDL_SUCCESS = 0, Failed = -1
+ */
+int8_t sn_nsdl_build_registration_body(struct nsdl_s *handle, sn_coap_hdr_s *message_ptr, uint8_t updating_registeration)
+{
+    tr_debug("sn_nsdl_build_registration_body");
+    /* Local variables */
+    uint8_t                 *temp_ptr;
+    sn_nsdl_dynamic_resource_parameters_s   *resource_temp_ptr;
+
+    /* Calculate needed memory and allocate */
+    int8_t error = 0;
+    uint16_t msg_len = sn_nsdl_calculate_registration_body_size(handle, updating_registeration, &error);
+    if (SN_NSDL_FAILURE == error) {
+        return error;
+    }
+
+    if (!msg_len) {
+        return SN_NSDL_SUCCESS;
+    } else {
+        message_ptr->payload_len = msg_len;
+    }
+    tr_debug("sn_nsdl_build_registration_body - body size: [%d]", message_ptr->payload_len);
+    message_ptr->payload_ptr = handle->sn_nsdl_alloc(message_ptr->payload_len);
+    if (!message_ptr->payload_ptr) {
+        return SN_NSDL_FAILURE;
+    }
+
+    /* Build message */
+    temp_ptr = message_ptr->payload_ptr;
+
+    resource_temp_ptr = sn_grs_get_first_resource(handle->grs);
+
+    /* Loop trough all resources */
+    while (resource_temp_ptr) {
+        /* if resource needs to be registered */
+        if (resource_temp_ptr->publish_uri) {
+            if (!resource_temp_ptr->always_publish && updating_registeration && resource_temp_ptr->registered == SN_NDSL_RESOURCE_REGISTERED) {
+                resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr);
+                continue;
+            } else {
+                resource_temp_ptr->registered = SN_NDSL_RESOURCE_REGISTERED;
+            }
+
+            /* If not first resource, add '.' to separator */
+            if (temp_ptr != message_ptr->payload_ptr) {
+                *temp_ptr++ = ',';
+            }
+
+            *temp_ptr++ = '<';
+            *temp_ptr++ = '/';
+            size_t path_len = 0;
+            if (resource_temp_ptr->static_resource_parameters->path) {
+                path_len = strlen(resource_temp_ptr->static_resource_parameters->path);
+            }
+            memcpy(temp_ptr,
+                   resource_temp_ptr->static_resource_parameters->path,
+                   path_len);
+            temp_ptr += path_len;
+            *temp_ptr++ = '>';
+
+            /* Resource attributes */
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_RESOURCE_TYPE
+            size_t resource_type_len = 0;
+            if (resource_temp_ptr->static_resource_parameters->resource_type_ptr) {
+                resource_type_len = strlen(resource_temp_ptr->static_resource_parameters->resource_type_ptr);
+            }
+            if (resource_type_len) {
+                *temp_ptr++ = ';';
+                memcpy(temp_ptr, resource_type_parameter, RT_PARAMETER_LEN);
+                temp_ptr += RT_PARAMETER_LEN;
+                *temp_ptr++ = '"';
+                memcpy(temp_ptr,
+                       resource_temp_ptr->static_resource_parameters->resource_type_ptr,
+                       resource_type_len);
+                temp_ptr += resource_type_len;
+                *temp_ptr++ = '"';
+            }
+#endif
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+            size_t interface_description_len = 0;
+            if (resource_temp_ptr->static_resource_parameters->interface_description_ptr) {
+                interface_description_len = strlen(resource_temp_ptr->static_resource_parameters->interface_description_ptr);
+            }
+
+            if (interface_description_len) {
+                *temp_ptr++ = ';';
+                memcpy(temp_ptr, if_description_parameter, IF_PARAMETER_LEN);
+                temp_ptr += IF_PARAMETER_LEN;
+                *temp_ptr++ = '"';
+                memcpy(temp_ptr,
+                       resource_temp_ptr->static_resource_parameters->interface_description_ptr,
+                       interface_description_len);
+                temp_ptr += interface_description_len;
+                *temp_ptr++ = '"';
+            }
+#endif
+#else
+            size_t attribute_len = 0;
+            if (resource_temp_ptr->static_resource_parameters->attributes_ptr) {
+                sn_nsdl_attribute_item_s *attribute = resource_temp_ptr->static_resource_parameters->attributes_ptr;
+                while (attribute->attribute_name != ATTR_END) {
+                    switch (attribute->attribute_name) {
+                    case ATTR_RESOURCE_TYPE:
+                        temp_ptr = sn_nsdl_build_resource_attribute_str(temp_ptr, attribute, resource_type_parameter, RT_PARAMETER_LEN);
+                        break;
+                    case ATTR_INTERFACE_DESCRIPTION:
+                        temp_ptr = sn_nsdl_build_resource_attribute_str(temp_ptr, attribute, if_description_parameter, IF_PARAMETER_LEN);
+                        break;
+                    case ATTR_ENDPOINT_NAME:
+                        temp_ptr = sn_nsdl_build_resource_attribute_str(temp_ptr, attribute, name_parameter, NAME_PARAMETER_LEN);
+                        break;
+                    default:
+                        break;
+                    }
+                    attribute++;
+                }
+            }
+#endif
+            if (resource_temp_ptr->coap_content_type != 0) {
+                *temp_ptr++ = ';';
+                memcpy(temp_ptr, coap_con_type_parameter, COAP_CON_PARAMETER_LEN);
+                temp_ptr += COAP_CON_PARAMETER_LEN;
+                *temp_ptr++ = '"';
+                temp_ptr = sn_nsdl_itoa(temp_ptr,
+                                        resource_temp_ptr->coap_content_type);
+                *temp_ptr++ = '"';
+            }
+
+            /* ;v */
+            if ((resource_temp_ptr->publish_value > 0) && resource_temp_ptr->resource) {
+                // If the resource is Opaque then do Base64 encoding of data
+                if (resource_temp_ptr->publish_value == 2) {
+                    size_t dst_size = (((resource_temp_ptr->resource_len + 2) / 3) << 2) + 1;
+                    unsigned char *dst = (unsigned char*)handle->sn_nsdl_alloc(dst_size);
+                    size_t olen = 0;
+                    if (dst) {
+                        if (mbedtls_base64_encode(dst, dst_size, &olen,
+                            resource_temp_ptr->resource, resource_temp_ptr->resource_len) == 0) {
+                            *temp_ptr++ = ';';
+                            memcpy(temp_ptr, resource_value, RESOURCE_VALUE_PARAMETER_LEN);
+                            temp_ptr += RESOURCE_VALUE_PARAMETER_LEN;
+                            *temp_ptr++ = '"';
+                            memcpy(temp_ptr, dst, olen);
+                            temp_ptr += olen;
+                            *temp_ptr++ = '"';
+
+                        }
+                        handle->sn_nsdl_free(dst);
+                    }
+
+                } else {      // For resources which does not require Base64 encoding of data
+                    *temp_ptr++ = ';';
+                    memcpy(temp_ptr, resource_value, RESOURCE_VALUE_PARAMETER_LEN);
+                    temp_ptr += RESOURCE_VALUE_PARAMETER_LEN;
+                    *temp_ptr++ = '"';
+                    memcpy(temp_ptr, resource_temp_ptr->resource, resource_temp_ptr->resource_len);
+                    temp_ptr += resource_temp_ptr->resource_len;
+                    *temp_ptr++ = '"';
+                }
+            }
+
+            /* ;aobs / ;obs */
+            // This needs to be re-visited and may be need an API for maganging obs value for different server implementation
+#ifndef COAP_DISABLE_OBS_FEATURE
+            if (resource_temp_ptr->auto_observable) {
+                uint8_t token[MAX_TOKEN_SIZE] = {0};
+                uint8_t len = handle->sn_nsdl_auto_obs_token_callback(handle,
+                                                                      resource_temp_ptr->static_resource_parameters->path,
+                                                                      (uint8_t*)token);
+                if (len > 0) {
+                    *temp_ptr++ = ';';
+                    memcpy(temp_ptr, aobs_parameter, AOBS_PARAMETER_LEN);
+                    temp_ptr += AOBS_PARAMETER_LEN;
+                    *temp_ptr++ = '"';
+                    uint16_t temp = common_read_16_bit((uint8_t*)token);
+                    temp_ptr = sn_nsdl_itoa(temp_ptr, temp);
+                    *temp_ptr++ = '"';
+                }
+            }
+            else if (resource_temp_ptr->observable) {
+                *temp_ptr++ = ';';
+                memcpy(temp_ptr, obs_parameter, OBS_PARAMETER_LEN);
+                temp_ptr += OBS_PARAMETER_LEN;
+            }
+#endif
+        }
+        resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr);
+
+    }
+    return SN_NSDL_SUCCESS;
+}
+
+/**
+ * \fn static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration, int8_t *error)
+ *
+ *
+ * \brief   Calculates registration message payload size
+ * \param   *handle                 Pointer to nsdl-library handle
+ * \param   *updating_registeration Pointer to list of GRS resources
+ * \param   *error                  Error code, SN_NSDL_SUCCESS or SN_NSDL_FAILURE
+ *
+ * \return  Needed payload size
+ */
+static uint16_t sn_nsdl_calculate_registration_body_size(struct nsdl_s *handle, uint8_t updating_registeration, int8_t *error)
+{
+    tr_debug("sn_nsdl_calculate_registration_body_size");
+    /* Local variables */
+    uint16_t return_value = 0;
+    *error = SN_NSDL_SUCCESS;
+    const sn_nsdl_dynamic_resource_parameters_s *resource_temp_ptr;
+
+    /* check pointer */
+    resource_temp_ptr = sn_grs_get_first_resource(handle->grs);
+
+    while (resource_temp_ptr) {
+        if (resource_temp_ptr->publish_uri) {
+            if (!resource_temp_ptr->always_publish && updating_registeration && resource_temp_ptr->registered == SN_NDSL_RESOURCE_REGISTERED) {
+                resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr);
+                continue;
+            }
+            /* If not first resource, then '.' will be added */
+            if (return_value) {
+                if (sn_nsdl_check_uint_overflow(return_value, 1, 0)) {
+                    return_value++;
+                } else {
+                    *error = SN_NSDL_FAILURE;
+                    break;
+                }
+            }
+
+            /* Count length for the resource path </path> */
+            size_t path_len = 0;
+            if (resource_temp_ptr->static_resource_parameters->path) {
+                path_len = strlen(resource_temp_ptr->static_resource_parameters->path);
+            }
+
+            if (sn_nsdl_check_uint_overflow(return_value, 3, path_len)) {
+                return_value += (3 + path_len);
+            } else {
+                *error = SN_NSDL_FAILURE;
+                break;
+            }
+
+            /* Count lengths of the attributes */
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_RESOURCE_TYPE
+            /* Resource type parameter */
+            size_t resource_type_len = 0;
+            if (resource_temp_ptr->static_resource_parameters->resource_type_ptr) {
+                resource_type_len = strlen(resource_temp_ptr->static_resource_parameters->resource_type_ptr);
+            }
+
+            if (resource_type_len) {
+                /* ;rt="restype" */
+                if (sn_nsdl_check_uint_overflow(return_value,
+                                                6,
+                                                resource_type_len)) {
+                    return_value += (6 + resource_type_len);
+                } else {
+                    *error = SN_NSDL_FAILURE;
+                    break;
+                }
+            }
+#endif
+
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+            /* Interface description parameter */
+            size_t interface_description_len = 0;
+            if (resource_temp_ptr->static_resource_parameters->interface_description_ptr) {
+                interface_description_len = strlen(resource_temp_ptr->static_resource_parameters->interface_description_ptr);
+            }
+            if (interface_description_len) {
+                /* ;if="iftype" */
+                if (sn_nsdl_check_uint_overflow(return_value,
+                                                6,
+                                                interface_description_len)) {
+                    return_value += (6 + interface_description_len);
+                } else {
+                    *error = SN_NSDL_FAILURE;
+                    break;
+                }
+            }
+#endif
+#else
+            /* All attributes */
+            if (resource_temp_ptr->static_resource_parameters->attributes_ptr) {
+                size_t attribute_len = 0;
+                size_t attribute_desc_len = 0;
+                uint8_t success = 1;
+                sn_nsdl_attribute_item_s *item = resource_temp_ptr->static_resource_parameters->attributes_ptr;
+                while (item->attribute_name != ATTR_END) {
+                    switch(item->attribute_name) {
+                    case ATTR_RESOURCE_TYPE:
+                        /* ;rt="restype" */
+                        attribute_desc_len = 6;
+                        attribute_len = strlen(item->value);
+                        break;
+                    case ATTR_INTERFACE_DESCRIPTION:
+                        /* ;if="iftype" */
+                        attribute_desc_len = 6;
+                        attribute_len = strlen(item->value);
+                        break;
+                    case ATTR_ENDPOINT_NAME:
+                        /* ;name="name" */
+                        attribute_desc_len = 8;
+                        attribute_len = strlen(item->value);
+                        break;
+                    default:
+                        break;
+                    }
+                    if (sn_nsdl_check_uint_overflow(return_value,
+                                                    attribute_desc_len,
+                                                    attribute_len)) {
+                        return_value += (attribute_desc_len + attribute_len);
+                    } else {
+                        success = 0;
+                        break;
+                    }
+                    item++;
+                }
+                if (!success) {
+                    *error = SN_NSDL_FAILURE;
+                    break;
+                }
+            }
+#endif
+            if (resource_temp_ptr->coap_content_type != 0) {
+                /* ;if="content" */
+                uint8_t len = sn_nsdl_itoa_len(resource_temp_ptr->coap_content_type);
+                if (sn_nsdl_check_uint_overflow(return_value, 6, len)) {
+                    return_value += (6 + len);
+                } else {
+                    *error = SN_NSDL_FAILURE;
+                    break;
+                }
+            }
+
+            if ((resource_temp_ptr->publish_value > 0) && resource_temp_ptr->resource) {
+                /* ;v="" */
+                uint16_t len = resource_temp_ptr->resource_len;
+                if (resource_temp_ptr->publish_value == 2) {
+                    len = (((resource_temp_ptr->resource_len + 2) / 3) << 2);
+                }
+                if (sn_nsdl_check_uint_overflow(return_value, 5, len)) {
+                    return_value += 5 + len;
+                } else {
+                    *error = SN_NSDL_FAILURE;
+                    break;
+                }
+                /* ;v="" */
+            }
+
+#ifndef COAP_DISABLE_OBS_FEATURE
+            // Auto obs will take higher priority
+            // This needs to be re-visited and may be need an API for maganging obs value for different server implementation
+            if (resource_temp_ptr->auto_observable) {
+                /* ;aobs="" */
+                uint8_t token[MAX_TOKEN_SIZE] = {0};
+                uint8_t len = handle->sn_nsdl_auto_obs_token_callback(handle,
+                                                                      resource_temp_ptr->static_resource_parameters->path,
+                                                                      (uint8_t*)token);
+
+                if (len > 0) {
+                    uint16_t temp = common_read_16_bit((uint8_t*)token);
+                    uint8_t token_len = sn_nsdl_itoa_len(temp);
+                    if (sn_nsdl_check_uint_overflow(return_value, 8, token_len)) {
+                        return_value += (8 + token_len);
+                    } else {
+                        *error = SN_NSDL_FAILURE;
+                        break;
+                    }
+                } else {
+                    *error = SN_NSDL_FAILURE;
+                    break;
+                }
+            }
+            else if (resource_temp_ptr->observable) {
+                if (sn_nsdl_check_uint_overflow(return_value, 4, 0)) {
+                    return_value += 4;
+                } else {
+                    *error = SN_NSDL_FAILURE;
+                    break;
+                }
+            }
+#endif
+        }
+        resource_temp_ptr = sn_grs_get_next_resource(handle->grs, resource_temp_ptr);
+    }
+    return return_value;
+}
+
+/**
+ * \fn static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr, uint8_t msg_type)
+ *
+ *
+ * \brief Calculates needed uri query option length
+ *
+ * \param *endpoint_info_ptr    Pointer to endpoint info structure
+ * \param msg_type              Message type
+ *
+ * \return  number of parameters in uri query
+ */
+static uint8_t sn_nsdl_calculate_uri_query_option_len(sn_nsdl_ep_parameters_s *endpoint_info_ptr,
+                                                      uint8_t msg_type,
+                                                      const char *uri_query)
+{
+    uint16_t return_value = 0;
+    uint8_t number_of_parameters = 0;
+
+
+    if ((endpoint_info_ptr->endpoint_name_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && endpoint_info_ptr->endpoint_name_ptr != 0) {
+        return_value += endpoint_info_ptr->endpoint_name_len;
+        return_value += EP_NAME_PARAMETERS_LEN; //ep=
+        number_of_parameters++;
+    }
+
+    if ((endpoint_info_ptr->type_len != 0) &&
+        (msg_type == SN_NSDL_EP_REGISTER_MESSAGE || msg_type == SN_NSDL_EP_UPDATE_MESSAGE) &&
+        (endpoint_info_ptr->type_ptr != 0)) {
+        return_value += endpoint_info_ptr->type_len;
+        return_value += ET_PARAMETER_LEN;       //et=
+        number_of_parameters++;
+    }
+
+    if ((endpoint_info_ptr->lifetime_len != 0) && (endpoint_info_ptr->lifetime_ptr != 0)) {
+        return_value += endpoint_info_ptr->lifetime_len;
+        return_value += LT_PARAMETER_LEN;       //lt=
+        number_of_parameters++;
+    }
+
+    if ((endpoint_info_ptr->domain_name_len != 0) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE) && (endpoint_info_ptr->domain_name_ptr != 0)) {
+        return_value += endpoint_info_ptr->domain_name_len;
+        return_value += DOMAIN_PARAMETER_LEN;       //d=
+        number_of_parameters++;
+    }
+
+    if (((endpoint_info_ptr->binding_and_mode & 0x04) || (endpoint_info_ptr->binding_and_mode & 0x01)) && (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) {
+        return_value += BS_QUEUE_MODE_PARAMETER_LEN;
+
+        if (endpoint_info_ptr->binding_and_mode & 0x01) {
+            return_value++;
+        }
+        if (endpoint_info_ptr->binding_and_mode & 0x04) {
+            return_value++;
+        }
+        if ((endpoint_info_ptr->binding_and_mode & 0x02) && ((endpoint_info_ptr->binding_and_mode & 0x04) || (endpoint_info_ptr->binding_and_mode & 0x01))) {
+            return_value++;
+        }
+
+        number_of_parameters++;
+    }
+
+    if (number_of_parameters != 0) {
+        return_value += (number_of_parameters - 1);
+    }
+
+    if (uri_query) {
+        return_value += strlen(uri_query);
+    }
+
+    if (return_value > MAX_URI_QUERY_LEN) {
+        tr_error("sn_nsdl_calculate_uri_query_option_len - max param length reached (%d)", return_value);
+        return_value = 0;
+    }
+
+    return return_value;
+}
+
+/**
+ * \fn static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *parameter_ptr, sn_coap_hdr_s *source_msg_ptr, uint8_t msg_type)
+ *
+ *
+ * \brief Fills uri-query options to message header struct
+ * \param *handle           Pointer to nsdl-library handle
+ * \param *parameter_ptr    Pointer to endpoint parameters struct
+ * \param *source_msg_ptr   Pointer to CoAP header struct
+ * \param msg_type          Message type
+ *
+ * \return  SN_NSDL_SUCCESS = 0, Failed = -1
+ */
+static int8_t sn_nsdl_fill_uri_query_options(struct nsdl_s *handle,
+                                             sn_nsdl_ep_parameters_s *parameter_ptr,
+                                             sn_coap_hdr_s *source_msg_ptr,
+                                             uint8_t msg_type,
+                                             const char *uri_query)
+{
+    uint8_t *temp_ptr = NULL;
+    if( !validateParameters(parameter_ptr) ){
+        return SN_NSDL_FAILURE;
+    }
+
+    size_t query_len = sn_nsdl_calculate_uri_query_option_len(parameter_ptr, msg_type, uri_query);
+    if (query_len == 0) {
+        return 0;
+    }
+
+    source_msg_ptr->options_list_ptr->uri_query_len = query_len;
+    source_msg_ptr->options_list_ptr->uri_query_ptr = handle->sn_nsdl_alloc(query_len);
+
+    if (source_msg_ptr->options_list_ptr->uri_query_ptr == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+    memset(source_msg_ptr->options_list_ptr->uri_query_ptr, 0, source_msg_ptr->options_list_ptr->uri_query_len);
+
+    temp_ptr = source_msg_ptr->options_list_ptr->uri_query_ptr;
+
+    /******************************************************/
+    /* If endpoint name is configured, fill needed fields */
+    /******************************************************/
+
+    if ((parameter_ptr->endpoint_name_len != 0) &&
+        (parameter_ptr->endpoint_name_ptr != 0) &&
+        (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) {
+        /* fill endpoint name, first ?ep=, then endpoint name */
+        memcpy(temp_ptr, ep_name_parameter_string, sizeof(ep_name_parameter_string));
+        temp_ptr += EP_NAME_PARAMETERS_LEN;
+        memcpy(temp_ptr, parameter_ptr->endpoint_name_ptr, parameter_ptr->endpoint_name_len);
+        temp_ptr += parameter_ptr->endpoint_name_len;
+    }
+
+    /******************************************************/
+    /* If endpoint type is configured, fill needed fields */
+    /******************************************************/
+
+    if ((parameter_ptr->type_len != 0) &&
+        (parameter_ptr->type_ptr != 0) &&
+        (msg_type == SN_NSDL_EP_REGISTER_MESSAGE || msg_type == SN_NSDL_EP_UPDATE_MESSAGE)) {
+        if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) {
+            *temp_ptr++ = '&';
+        }
+
+        memcpy(temp_ptr, et_parameter, sizeof(et_parameter));
+        temp_ptr += ET_PARAMETER_LEN;
+        memcpy(temp_ptr, parameter_ptr->type_ptr, parameter_ptr->type_len);
+        temp_ptr += parameter_ptr->type_len;
+    }
+
+
+    /******************************************************/
+    /* If lifetime is configured, fill needed fields */
+    /******************************************************/
+
+    if ((parameter_ptr->lifetime_len != 0) && (parameter_ptr->lifetime_ptr != 0)) {
+        if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) {
+            *temp_ptr++ = '&';
+        }
+
+        memcpy(temp_ptr, ep_lifetime_parameter, sizeof(ep_lifetime_parameter));
+        temp_ptr += LT_PARAMETER_LEN;
+        memcpy(temp_ptr, parameter_ptr->lifetime_ptr, parameter_ptr->lifetime_len);
+        temp_ptr += parameter_ptr->lifetime_len;
+    }
+
+    /******************************************************/
+    /* If domain is configured, fill needed fields */
+    /******************************************************/
+
+    if ((parameter_ptr->domain_name_len != 0) &&
+        (parameter_ptr->domain_name_ptr != 0) &&
+        (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) {
+        if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) {
+            *temp_ptr++ = '&';
+        }
+
+        memcpy(temp_ptr, ep_domain_parameter, sizeof(ep_domain_parameter));
+        temp_ptr += DOMAIN_PARAMETER_LEN;
+        memcpy(temp_ptr, parameter_ptr->domain_name_ptr, parameter_ptr->domain_name_len);
+        temp_ptr += parameter_ptr->domain_name_len;
+    }
+
+    /******************************************************/
+    /* If queue-mode is configured, fill needed fields    */
+    /******************************************************/
+
+    if (((parameter_ptr->binding_and_mode & 0x01) ||
+         (parameter_ptr->binding_and_mode & 0x04)) &&
+         (msg_type == SN_NSDL_EP_REGISTER_MESSAGE)) {
+        if (temp_ptr != source_msg_ptr->options_list_ptr->uri_query_ptr) {
+            *temp_ptr++ = '&';
+        }
+
+        memcpy(temp_ptr, bs_queue_mode, sizeof(bs_queue_mode));
+        temp_ptr += BS_QUEUE_MODE_PARAMETER_LEN;
+
+        if (parameter_ptr->binding_and_mode & 0x01) {
+            *temp_ptr++ = 'U';
+            if (parameter_ptr->binding_and_mode & 0x02) {
+                *temp_ptr++ = 'Q';
+            }
+        }
+
+        if (parameter_ptr->binding_and_mode & 0x04) {
+            *temp_ptr++ = 'S';
+            if ((parameter_ptr->binding_and_mode & 0x02) && !(parameter_ptr->binding_and_mode & 0x01)) {
+                *temp_ptr++ = 'Q';
+            }
+        }
+    }
+
+    if (uri_query) {
+        memcpy(temp_ptr, uri_query, strlen(uri_query));
+    }
+
+    return SN_NSDL_SUCCESS;
+}
+
+static bool validateParameters(sn_nsdl_ep_parameters_s *parameter_ptr)
+{
+    if( !validate( parameter_ptr->domain_name_ptr, parameter_ptr->domain_name_len, '&' ) ){
+        return false;
+    }
+
+    if( !validate( parameter_ptr->endpoint_name_ptr, parameter_ptr->endpoint_name_len, '&' ) ){
+        return false;
+    }
+
+    if( !validate( parameter_ptr->lifetime_ptr, parameter_ptr->lifetime_len, '&' ) ){
+        return false;
+    }
+
+    if( !validate( parameter_ptr->type_ptr, parameter_ptr->type_len, '&' ) ){
+        return false;
+    }
+    return true;
+}
+
+static bool validate(uint8_t* ptr, uint32_t len, char illegalChar)
+{
+    if( ptr ){
+        for( uint32_t i=0; i < len; i++ ){
+            if( ptr[i] == illegalChar ){
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+/**
+ * \fn static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr)
+ *
+ * \brief If received message is reply for the message that NSDL has been sent, it is processed here. Else, packet will be sent to application.
+ * \param *handle           Pointer to nsdl-library handle
+ * \param *coap_packet_ptr  Pointer to received CoAP packet
+ * \param *address_ptr      Pointer to source address struct
+ *
+ * \return      SN_NSDL_SUCCESS = 0, Failed = -1
+ */
+static int8_t sn_nsdl_local_rx_function(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, sn_nsdl_addr_s *address_ptr)
+{
+    if ((coap_packet_ptr == 0) || (address_ptr == 0)) {
+        return -1;
+    }
+
+    bool is_reg_msg = false;
+    bool is_update_reg_msg = false;
+    bool is_unreg_msg = false;
+    bool is_bs_msg = false;
+
+    if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CREATED &&
+        coap_packet_ptr->token_len == sizeof(handle->register_token) &&
+        memcmp(coap_packet_ptr->token_ptr, &handle->register_token, coap_packet_ptr->token_len) == 0) {
+        handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_IS_REGISTERED;
+        sn_grs_mark_resources_as_registered(handle);
+        is_reg_msg = true;
+        if (sn_nsdl_resolve_ep_information(handle, coap_packet_ptr) != SN_NSDL_SUCCESS) {
+            return SN_NSDL_FAILURE;
+        }
+    }
+
+    else if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_CHANGED &&
+             coap_packet_ptr->token_len == sizeof(handle->update_register_token) &&
+             memcmp(coap_packet_ptr->token_ptr,
+                    &handle->update_register_token,
+                    coap_packet_ptr->token_len) == 0) {
+        is_update_reg_msg = true;
+    }
+
+    else if (coap_packet_ptr->msg_code == COAP_MSG_CODE_RESPONSE_DELETED &&
+             coap_packet_ptr->token_len == sizeof(handle->unregister_token) &&
+             memcmp(coap_packet_ptr->token_ptr, &handle->unregister_token, coap_packet_ptr->token_len) == 0) {
+        is_unreg_msg = true;
+        handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr);
+        handle->ep_information_ptr->endpoint_name_ptr = 0;
+        handle->ep_information_ptr->endpoint_name_len = 0;
+
+        handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr);
+        handle->ep_information_ptr->domain_name_ptr = 0;
+        handle->ep_information_ptr->domain_name_len = 0;
+    }
+    else if (coap_packet_ptr->token_len == sizeof(handle->bootstrap_token) &&
+             memcmp(coap_packet_ptr->token_ptr, &handle->bootstrap_token, coap_packet_ptr->token_len) == 0) {
+        is_bs_msg = true;
+    }
+
+    /* Store the current message token so that we can identify if same operation was initiated from callback */
+    uint32_t temp_token = 0;
+    if (is_reg_msg) {
+        temp_token = handle->register_token;
+    }
+    else if (is_unreg_msg) {
+        temp_token = handle->unregister_token;
+    }
+    else if (is_update_reg_msg) {
+        temp_token = handle->update_register_token;
+    }
+    else if (is_bs_msg) {
+        temp_token = handle->bootstrap_token;
+    }
+
+    /* No messages to wait for, or message was not response to our request */
+    int ret = handle->sn_nsdl_rx_callback(handle, coap_packet_ptr, address_ptr);
+
+    /* If callback initiated same operation then token is updated in handle and temp_token won't match.
+       This means we don't clear the handle token here because we will wait for response to new request. */
+    if (is_reg_msg && temp_token == handle->register_token) {
+        handle->register_token = 0;
+    }
+    else if (is_unreg_msg && temp_token == handle->unregister_token) {
+        handle->unregister_token = 0;
+    }
+    else if (is_update_reg_msg && temp_token == handle->update_register_token) {
+        handle->update_register_token = 0;
+    }
+    else if (is_bs_msg && temp_token == handle->bootstrap_token) {
+        handle->bootstrap_token = 0;
+    }
+    return ret;
+}
+
+/**
+ * \fn static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr)
+ *
+ *
+ * \brief Resolves endpoint information from received CoAP message
+ * \param *handle           Pointer to nsdl-library handle
+ * \param *coap_packet_ptr  Pointer to received CoAP message
+ *
+ * \return  SN_NSDL_SUCCESS = 0, Failed = -1
+ */
+static int8_t sn_nsdl_resolve_ep_information(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr)
+{
+    uint8_t     *temp_ptr;
+    uint8_t     parameter_count     = 0;
+    uint16_t    parameter_len       = 0;
+
+    if (!coap_packet_ptr || !coap_packet_ptr->options_list_ptr ||
+        !coap_packet_ptr->options_list_ptr->location_path_ptr) {
+        return SN_NSDL_FAILURE;
+    }
+
+    temp_ptr = coap_packet_ptr->options_list_ptr->location_path_ptr;
+
+    while (temp_ptr <= (coap_packet_ptr->options_list_ptr->location_path_ptr + coap_packet_ptr->options_list_ptr->location_path_len)) {
+
+        if ((temp_ptr == (coap_packet_ptr->options_list_ptr->location_path_ptr + coap_packet_ptr->options_list_ptr->location_path_len)) || (*temp_ptr == '/')) {
+
+            parameter_count++;
+            if (parameter_count == 2) {
+                if (!handle->ep_information_ptr->domain_name_ptr) {
+                    handle->ep_information_ptr->domain_name_len = parameter_len - 1;
+                    handle->ep_information_ptr->domain_name_ptr = handle->sn_nsdl_alloc(handle->ep_information_ptr->domain_name_len);
+                    if (!handle->ep_information_ptr->domain_name_ptr) {
+                        return SN_NSDL_FAILURE;
+                    }
+                    memcpy(handle->ep_information_ptr->domain_name_ptr, temp_ptr - handle->ep_information_ptr->domain_name_len, handle->ep_information_ptr->domain_name_len);
+                }
+
+            }
+            if (parameter_count == 3) {
+                if (!handle->ep_information_ptr->endpoint_name_ptr) {
+                    handle->ep_information_ptr->endpoint_name_len = parameter_len - 1;
+                    handle->ep_information_ptr->endpoint_name_ptr = handle->sn_nsdl_alloc(handle->ep_information_ptr->endpoint_name_len);
+                    if (!handle->ep_information_ptr->endpoint_name_ptr) {
+                        if (handle->ep_information_ptr->domain_name_ptr) {
+                            handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr);
+                            handle->ep_information_ptr->domain_name_ptr = NULL;
+                            handle->ep_information_ptr->domain_name_len = 0;
+                        }
+
+                        return SN_NSDL_FAILURE;
+
+                    }
+                    memcpy(handle->ep_information_ptr->endpoint_name_ptr, temp_ptr - handle->ep_information_ptr->endpoint_name_len, handle->ep_information_ptr->endpoint_name_len);
+                }
+            }
+            parameter_len = 0;
+        }
+        parameter_len++;
+        temp_ptr++;
+    }
+
+
+    return SN_NSDL_SUCCESS;
+}
+
+extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint8_t address_length, uint16_t port, sn_nsdl_addr_type_e address_type)
+{
+    /* Check parameters and source pointers */
+    if (!handle || !NSP_address) {
+        return SN_NSDL_FAILURE;
+    }
+
+    handle->server_address.type = address_type;
+
+    handle->sn_nsdl_free(handle->server_address.addr_ptr);
+
+    handle->server_address.addr_len = address_length;
+
+    handle->server_address.addr_ptr = handle->sn_nsdl_alloc(handle->server_address.addr_len);
+    if (!handle->server_address.addr_ptr) {
+        return SN_NSDL_FAILURE;
+    }
+
+    memcpy(handle->server_address.addr_ptr, NSP_address, handle->server_address.addr_len);
+    handle->server_address.port = port;
+
+    return SN_NSDL_SUCCESS;
+}
+
+
+static uint8_t sn_nsdl_itoa_len(uint32_t value)
+{
+    uint8_t i = 0;
+
+    do {
+        i++;
+    } while ((value /= 10) > 0);
+
+    return i;
+}
+
+static uint8_t *sn_nsdl_itoa(uint8_t *ptr, uint32_t value)
+{
+
+    uint8_t start = 0;
+    uint8_t end = 0;
+    uint8_t i;
+
+    i = 0;
+
+    /* ITOA */
+    do {
+        ptr[i++] = (value % 10) + '0';
+    } while ((value /= 10) > 0);
+
+    end = i - 1;
+
+    /* reverse (part of ITOA) */
+    while (start < end) {
+        uint8_t chr;
+
+        chr = ptr[start];
+        ptr[start] = ptr[end];
+        ptr[end] = chr;
+
+        start++;
+        end--;
+
+    }
+    return (ptr + i);
+}
+
+static int8_t set_endpoint_info(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr)
+{
+    handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr);
+    handle->ep_information_ptr->domain_name_ptr = 0;
+    handle->ep_information_ptr->domain_name_len = 0;
+
+    handle->sn_nsdl_free(handle->ep_information_ptr->endpoint_name_ptr);
+    handle->ep_information_ptr->endpoint_name_ptr = 0;
+    handle->ep_information_ptr->endpoint_name_len = 0;
+
+    handle->sn_nsdl_free(handle->ep_information_ptr->type_ptr);
+    handle->ep_information_ptr->type_ptr = 0;
+    handle->ep_information_ptr->type_len = 0;
+
+    if (endpoint_info_ptr->domain_name_ptr && endpoint_info_ptr->domain_name_len) {
+        handle->ep_information_ptr->domain_name_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->domain_name_len);
+
+        if (!handle->ep_information_ptr->domain_name_ptr) {
+            return -1;
+        }
+
+        memcpy(handle->ep_information_ptr->domain_name_ptr, endpoint_info_ptr->domain_name_ptr, endpoint_info_ptr->domain_name_len);
+        handle->ep_information_ptr->domain_name_len = endpoint_info_ptr->domain_name_len;
+    }
+
+    if (endpoint_info_ptr->endpoint_name_ptr && endpoint_info_ptr->endpoint_name_len) {
+        handle->ep_information_ptr->endpoint_name_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->endpoint_name_len);
+
+        if (!handle->ep_information_ptr->endpoint_name_ptr) {
+            handle->sn_nsdl_free(handle->ep_information_ptr->domain_name_ptr);
+            handle->ep_information_ptr->domain_name_ptr = 0;
+            handle->ep_information_ptr->domain_name_len = 0;
+            return -1;
+        }
+
+        memcpy(handle->ep_information_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_ptr, endpoint_info_ptr->endpoint_name_len);
+        handle->ep_information_ptr->endpoint_name_len = endpoint_info_ptr->endpoint_name_len;
+    }
+
+    if (endpoint_info_ptr->type_ptr && endpoint_info_ptr->type_len) {
+        handle->ep_information_ptr->type_ptr = handle->sn_nsdl_alloc(endpoint_info_ptr->type_len);
+        if (handle->ep_information_ptr->type_ptr) {
+            memcpy(handle->ep_information_ptr->type_ptr, endpoint_info_ptr->type_ptr, endpoint_info_ptr->type_len);
+            handle->ep_information_ptr->type_len = endpoint_info_ptr->type_len;
+        }
+    }
+
+    handle->ep_information_ptr->binding_and_mode = endpoint_info_ptr->binding_and_mode;
+    handle->ep_information_ptr->ds_register_mode = endpoint_info_ptr->ds_register_mode;
+
+    return 0;
+}
+
+extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr)
+{
+    /* Check parameters */
+    if (handle == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+
+    int8_t ret = sn_grs_send_coap_message(handle, address_ptr, coap_hdr_ptr);
+
+    return ret;
+}
+
+extern int8_t sn_nsdl_handle_block2_response_internally(struct nsdl_s *handle, uint8_t build_response)
+{
+    /* Check parameters */
+    if (handle == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+
+    return sn_coap_protocol_handle_block2_response_internally(handle->grs->coap, build_response);
+}
+
+extern int8_t sn_nsdl_clear_coap_sent_blockwise_messages(struct nsdl_s *handle)
+{
+    /* Check parameters */
+    if (handle == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+
+    // Enable function once new CoAP API is released to mbed-os
+    sn_coap_protocol_clear_sent_blockwise_messages(handle->grs->coap);
+
+    return SN_NSDL_SUCCESS;
+}
+
+extern int32_t sn_nsdl_send_request(struct nsdl_s *handle,
+                                    const sn_coap_msg_code_e msg_code,
+                                    const char *uri_path,
+                                    const uint32_t token,
+                                    const size_t offset,
+                                    const uint16_t payload_len,
+                                    uint8_t* payload_ptr)
+{
+    sn_coap_hdr_s  req_message;
+    int32_t        message_id;
+
+    if (handle == NULL || uri_path == NULL) {
+        return 0;
+    }
+
+    memset(&req_message, 0, sizeof(sn_coap_hdr_s));
+
+    // Fill message fields
+    req_message.msg_type = COAP_MSG_TYPE_CONFIRMABLE;
+    req_message.msg_code = msg_code;
+    req_message.uri_path_len = (uint16_t)strlen(uri_path);
+    req_message.uri_path_ptr = (uint8_t*)uri_path;
+    req_message.token_ptr = (uint8_t*)&token;
+    req_message.token_len = sizeof(token);
+    if (msg_code == COAP_MSG_CODE_REQUEST_POST || msg_code == COAP_MSG_CODE_REQUEST_PUT) {
+        // Use payload only if POST or PUT request
+        req_message.payload_ptr = payload_ptr;
+        req_message.payload_len = payload_len;
+    }
+
+// Skip block options if feature is not enabled
+#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+    if (sn_coap_parser_alloc_options(handle->grs->coap, &req_message) == NULL) {
+        handle->grs->coap->sn_coap_protocol_free(req_message.options_list_ptr);
+        return 0;
+    }
+
+    // Add block number
+    req_message.options_list_ptr->block2 = 0;
+    if (offset > 0) {
+        req_message.options_list_ptr->block2 = ((offset / handle->grs->coap->sn_coap_block_data_size) << 4);
+    }
+    // Add block size
+    req_message.options_list_ptr->block2 |= sn_coap_convert_block_size(handle->grs->coap->sn_coap_block_data_size);
+#else
+    (void)offset;
+#endif
+
+    // Build and send coap message
+    message_id = sn_nsdl_internal_coap_send(handle, &req_message, &handle->server_address);
+    handle->grs->coap->sn_coap_protocol_free(req_message.options_list_ptr);
+
+    return message_id;
+}
+
+extern int8_t sn_nsdl_put_resource(struct nsdl_s *handle, sn_nsdl_dynamic_resource_parameters_s *res)
+{
+    if (!handle) {
+        return SN_NSDL_FAILURE;
+    }
+
+    return sn_grs_put_resource(handle->grs, res);
+}
+
+extern int8_t sn_nsdl_pop_resource(struct nsdl_s *handle, sn_nsdl_dynamic_resource_parameters_s *res)
+{
+    if (!handle) {
+        return SN_NSDL_FAILURE;
+    }
+
+    return sn_grs_pop_resource(handle->grs, res);
+}
+
+extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, const char *path)
+{
+    /* Check parameters */
+    if (handle == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+
+    return sn_grs_delete_resource(handle->grs, path);
+}
+extern const sn_nsdl_dynamic_resource_parameters_s *sn_nsdl_get_first_resource(struct nsdl_s *handle)
+{
+    /* Check parameters */
+    if (handle == NULL) {
+        return NULL;
+    }
+
+    return sn_grs_get_first_resource(handle->grs);
+}
+extern const sn_nsdl_dynamic_resource_parameters_s *sn_nsdl_get_next_resource(struct nsdl_s *handle, const sn_nsdl_dynamic_resource_parameters_s *resource)
+{
+    /* Check parameters */
+    if (handle == NULL) {
+        return NULL;
+    }
+
+    return sn_grs_get_next_resource(handle->grs, resource);
+}
+
+extern sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)
+{
+    if (handle == NULL) {
+        return NULL;
+    }
+
+    return sn_coap_build_response(handle->grs->coap, coap_packet_ptr, msg_code);
+}
+
+extern sn_coap_options_list_s *sn_nsdl_alloc_options_list(struct nsdl_s *handle, sn_coap_hdr_s *coap_msg_ptr)
+{
+    if (handle == NULL || coap_msg_ptr == NULL) {
+        return NULL;
+    }
+    return sn_coap_parser_alloc_options(handle->grs->coap, coap_msg_ptr);
+}
+
+extern void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr)
+{
+    if (handle == NULL) {
+        return;
+    }
+
+    sn_coap_parser_release_allocated_coap_msg_mem(handle->grs->coap, freed_coap_msg_ptr);
+}
+
+extern int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *handle,
+    uint8_t resending_count, uint8_t resending_interval)
+{
+    if (handle == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+    return sn_coap_protocol_set_retransmission_parameters(handle->grs->coap,
+                                                          resending_count,resending_interval);
+}
+
+extern int8_t sn_nsdl_set_retransmission_buffer(struct nsdl_s *handle,
+        uint8_t buffer_size_messages, uint16_t buffer_size_bytes)
+{
+    if (handle == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+    return sn_coap_protocol_set_retransmission_buffer(handle->grs->coap,
+                                                      buffer_size_messages, buffer_size_bytes);
+}
+
+extern int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size)
+{
+    if (handle == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+    return sn_coap_protocol_set_block_size(handle->grs->coap, block_size);
+}
+
+extern int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle, uint8_t message_count)
+{
+    if (handle == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+    return sn_coap_protocol_set_duplicate_buffer_size(handle->grs->coap, message_count);
+}
+
+bool sn_nsdl_check_uint_overflow(uint16_t resource_size, uint16_t param_a, uint16_t param_b)
+{
+    uint16_t first_check = param_a + param_b;
+    if (first_check < param_b) {
+        return false;
+    } else {
+        uint16_t total = resource_size + first_check;
+        if (total < first_check) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+}
+
+extern int8_t sn_nsdl_set_context(struct nsdl_s * const handle, void * const context)
+{
+    if (handle == NULL) {
+        return SN_NSDL_FAILURE;
+    }
+    handle->context = context;
+    return SN_NSDL_SUCCESS;
+}
+
+extern void *sn_nsdl_get_context(const struct nsdl_s * const handle)
+{
+    if (handle == NULL) {
+        return NULL;
+    }
+    return handle->context;
+}
+
+
+int8_t sn_nsdl_clear_coap_resending_queue(struct nsdl_s *handle)
+{
+    if (handle == NULL || handle->grs == NULL) {
+        tr_err("sn_nsdl_clear_coap_resending_queue failed.");
+        return SN_NSDL_FAILURE;
+    }
+    sn_coap_protocol_clear_retransmission_buffer(handle->grs->coap);
+    return SN_NSDL_SUCCESS;
+}
+
+#ifdef RESOURCE_ATTRIBUTES_LIST
+static void sn_nsdl_free_attribute_value(sn_nsdl_attribute_item_s *attribute)
+{
+    switch (attribute->attribute_name) {
+    case ATTR_RESOURCE_TYPE:
+    case ATTR_INTERFACE_DESCRIPTION:
+    case ATTR_ENDPOINT_NAME:
+        free(attribute->value);
+        attribute->value = NULL;
+        break;
+    case ATTR_NOP:
+    case ATTR_END:
+    default:
+        break;
+    }
+}
+
+void sn_nsdl_free_resource_attributes_list(sn_nsdl_static_resource_parameters_s *params)
+{
+    if (params == NULL || params->free_on_delete == false) {
+        return;
+    }
+    sn_nsdl_attribute_item_s *item = params->attributes_ptr;
+    if (item) {
+        while (item->attribute_name != ATTR_END) {
+            sn_nsdl_free_attribute_value(item);
+            item++;
+        }
+        free(params->attributes_ptr);
+        params->attributes_ptr = NULL;
+    }
+}
+
+bool sn_nsdl_set_resource_attribute(sn_nsdl_static_resource_parameters_s *params, const sn_nsdl_attribute_item_s *attribute)
+{
+    if (params == NULL || params->free_on_delete == false) {
+        return false;
+    }
+    unsigned int item_count = 0;
+    sn_nsdl_attribute_item_s *item = params->attributes_ptr;
+    // Count the number of attributes for reallocation, update in place though
+    // if the attribute already existed
+    while (item != NULL) {
+        item_count++;
+        if (item->attribute_name == ATTR_END) {
+            break;
+        }
+        // Check if attribute already exists or if there is NOP we can overwrite
+        if (item->attribute_name == attribute->attribute_name || item->attribute_name == ATTR_NOP) {
+            // Found attribute or NOP, overwrite it
+            sn_nsdl_free_attribute_value(item);
+            item->attribute_name = attribute->attribute_name;
+            item->value = attribute->value;
+            return true;
+        }
+        item++;
+    }
+    // Attribute did not yet exist (ptr was null or ATTR_END was first one)
+    if (item_count > 0) {
+        // List already had some attributes, so reallocate
+        size_t new_size = (item_count + 1) * sizeof(sn_nsdl_attribute_item_s);
+        item = params->attributes_ptr;
+        params->attributes_ptr = realloc(item, new_size);
+        if (params->attributes_ptr == NULL) {
+            // realloc failed, put back original pointer and return false
+            params->attributes_ptr = item;
+            return false;
+        }
+        // And move item ptr to ATTR_END to update that and last attribute
+        item = &(params->attributes_ptr[item_count - 1]);
+    }
+    else {
+        // No attributes, so allocate first time (1 struct for attribute and 1 struct for ATTR_END)
+        params->attributes_ptr = (char*)malloc(2 * sizeof(sn_nsdl_attribute_item_s));
+        if (params->attributes_ptr == NULL) {
+            return false;
+        }
+        item = params->attributes_ptr;
+    }
+    item->attribute_name = attribute->attribute_name;
+    item->value = attribute->value;
+    item++;
+    item->attribute_name = ATTR_END;
+    item->value = NULL;
+    return true;
+}
+
+const char *sn_nsdl_get_resource_attribute(const sn_nsdl_static_resource_parameters_s *params, sn_nsdl_resource_attribute_t attribute_name)
+{
+    char *value = NULL;
+    if (params != NULL) {
+        sn_nsdl_attribute_item_s *item = params->attributes_ptr;
+        while (item != NULL && item->attribute_name != ATTR_END) {
+            if (item->attribute_name == attribute_name) {
+                value = item->value;
+                break;
+            }
+            item++;
+        }
+    }
+    return value;
+}
+
+bool sn_nsdl_remove_resource_attribute(sn_nsdl_static_resource_parameters_s *params, sn_nsdl_resource_attribute_t attribute_name)
+{
+    if (params == NULL || params->free_on_delete == false) {
+        return false;
+    }
+
+    bool found = false;
+    sn_nsdl_attribute_item_s *item = params->attributes_ptr;
+    while (item != NULL) {
+        if (item->attribute_name == ATTR_END) {
+            break;
+        }
+        // Remove if attribute name matches
+        if (item->attribute_name == attribute_name) {
+            // Currently only pointer values, need to free and set as NOP
+            sn_nsdl_free_attribute_value(item);
+            item->attribute_name = ATTR_NOP;
+            found = true;
+            break;
+        }
+        item++;
+    }
+
+    return found;
+
+}
+
+#endif
+
+
+void sn_nsdl_print_coap_data(sn_coap_hdr_s *coap_header_ptr, bool outgoing)
+{
+#if defined(FEA_TRACE_SUPPORT) || MBED_CONF_MBED_TRACE_ENABLE || YOTTA_CFG_MBED_TRACE || (defined(YOTTA_CFG) && !defined(NDEBUG))
+    if (!coap_header_ptr) {
+        return;
+    }
+
+    if (outgoing) {
+        tr_info("======== Outgoing CoAP package ========");
+    } else {
+        tr_info("======== Incoming CoAP package ========");
+    }
+
+    if (coap_header_ptr->uri_path_len > 0 && coap_header_ptr->uri_path_ptr) {
+        tr_info("Uri-Path:\t\t%.*s", coap_header_ptr->uri_path_len, coap_header_ptr->uri_path_ptr);
+    }
+    tr_info("Status:\t\t%s", sn_nsdl_coap_status_description(coap_header_ptr->coap_status));
+    tr_info("Code:\t\t%s", sn_nsdl_coap_message_code_desc(coap_header_ptr->msg_code));
+    tr_info("Type:\t\t%s", sn_nsdl_coap_message_type_desc(coap_header_ptr->msg_type));
+    tr_info("Id:\t\t%d", coap_header_ptr->msg_id);
+    if (coap_header_ptr->token_ptr && coap_header_ptr->token_len > 0) {
+        tr_info("Token:\t\t%s", tr_array(coap_header_ptr->token_ptr, coap_header_ptr->token_len));
+    }
+    if (coap_header_ptr->content_format != -1) {
+        tr_info("Content-type:\t%d", coap_header_ptr->content_format);
+    }
+    tr_info("Payload len:\t%d", coap_header_ptr->payload_len);
+#ifdef MBED_CLIENT_PRINT_COAP_PAYLOAD
+    if (coap_header_ptr->payload_ptr && coap_header_ptr->payload_len > 0) {
+        int i = 0;
+        int row_len = 40;
+        int max_length = 2048;
+        while (i < coap_header_ptr->payload_len && i < max_length) {
+            if (i + row_len > coap_header_ptr->payload_len) {
+                row_len = coap_header_ptr->payload_len - i;
+            }
+            tr_info("Payload:\t\t%s", tr_array( coap_header_ptr->payload_ptr + i, row_len));
+            i += row_len;
+        }
+        if (i >= max_length)
+            tr_info("Payload:\t\t.....");
+    }
+#endif
+
+    if (coap_header_ptr->options_list_ptr) {
+        if (coap_header_ptr->options_list_ptr->etag_ptr && coap_header_ptr->options_list_ptr->etag_len > 0) {
+            tr_info("E-tag:\t%.*s", coap_header_ptr->options_list_ptr->etag_len, coap_header_ptr->options_list_ptr->etag_ptr);
+        }
+        if (coap_header_ptr->options_list_ptr->proxy_uri_ptr && coap_header_ptr->options_list_ptr->proxy_uri_len > 0) {
+            tr_info("Proxy uri:\t%.*s", coap_header_ptr->options_list_ptr->proxy_uri_len, coap_header_ptr->options_list_ptr->proxy_uri_ptr);
+        }
+
+        if (coap_header_ptr->options_list_ptr->uri_host_ptr && coap_header_ptr->options_list_ptr->uri_host_len > 0) {
+            tr_info("Uri host:\t%.*s", coap_header_ptr->options_list_ptr->uri_host_len, coap_header_ptr->options_list_ptr->uri_host_ptr);
+        }
+
+        if (coap_header_ptr->options_list_ptr->location_path_ptr && coap_header_ptr->options_list_ptr->location_path_len > 0) {
+            tr_info("Location path:\t%.*s", coap_header_ptr->options_list_ptr->location_path_len, coap_header_ptr->options_list_ptr->location_path_ptr);
+        }
+
+        if (coap_header_ptr->options_list_ptr->location_query_ptr && coap_header_ptr->options_list_ptr->location_query_len > 0) {
+            tr_info("Location query:\t%.*s", coap_header_ptr->options_list_ptr->location_query_len, coap_header_ptr->options_list_ptr->location_query_ptr);
+        }
+
+        if (coap_header_ptr->options_list_ptr->uri_query_ptr && coap_header_ptr->options_list_ptr->uri_query_len > 0) {
+            tr_info("Uri query:\t%.*s", coap_header_ptr->options_list_ptr->uri_query_len, coap_header_ptr->options_list_ptr->uri_query_ptr);
+        }
+
+        tr_info("Max-age:\t\t%" PRIu32"", coap_header_ptr->options_list_ptr->max_age);
+        if (coap_header_ptr->options_list_ptr->use_size1) {
+            tr_info("Size 1:\t\t%" PRIu32"", coap_header_ptr->options_list_ptr->size1);
+        }
+        if (coap_header_ptr->options_list_ptr->use_size2) {
+            tr_info("Size 2:\t\t%" PRIu32"", coap_header_ptr->options_list_ptr->size2);
+        }
+        if (coap_header_ptr->options_list_ptr->accept != -1) {
+            tr_info("Accept:\t\t%d", coap_header_ptr->options_list_ptr->accept);
+        }
+        if (coap_header_ptr->options_list_ptr->uri_port != -1) {
+            tr_info("Uri port:\t%" PRId32"", coap_header_ptr->options_list_ptr->uri_port);
+        }
+        if (coap_header_ptr->options_list_ptr->observe != -1) {
+            tr_info("Observe:\t\t%" PRId32"", coap_header_ptr->options_list_ptr->observe);
+        }
+        if (coap_header_ptr->options_list_ptr->block1 != -1) {
+            tr_info("Block1 number:\t%" PRId32"", coap_header_ptr->options_list_ptr->block1 >> 4);
+            uint8_t temp = (coap_header_ptr->options_list_ptr->block1 & 0x07);
+            uint16_t block_size = 1u << (temp + 4);
+            tr_info("Block1 size:\t%d", block_size);
+            tr_info("Block1 more:\t%d", (coap_header_ptr->options_list_ptr->block1) & 0x08 ? true : false);
+        }
+        if (coap_header_ptr->options_list_ptr->block2 != -1) {
+            tr_info("Block2 number:\t%" PRId32"", coap_header_ptr->options_list_ptr->block2 >> 4);
+            uint8_t temp = (coap_header_ptr->options_list_ptr->block2 & 0x07);
+            uint16_t block_size = 1u << (temp + 4);
+            tr_info("Block2 size:\t%d", block_size);
+            tr_info("Block2 more:\t%d", (coap_header_ptr->options_list_ptr->block2) & 0x08 ? true : false);
+        }
+    }
+    tr_info("======== End of CoAP package ========");
+#else
+    (void) coap_header_ptr;
+    (void) outgoing;
+#endif
+}
+
+#if defined(FEA_TRACE_SUPPORT) || MBED_CONF_MBED_TRACE_ENABLE || YOTTA_CFG_MBED_TRACE || (defined(YOTTA_CFG) && !defined(NDEBUG))
+const char *sn_nsdl_coap_status_description(sn_coap_status_e status)
+{
+    switch(status) {
+        case COAP_STATUS_OK:
+            return "COAP_STATUS_OK";
+        case COAP_STATUS_PARSER_ERROR_IN_HEADER:
+            return "COAP_STATUS_PARSER_ERROR_IN_HEADER";
+        case COAP_STATUS_PARSER_DUPLICATED_MSG:
+            return "COAP_STATUS_PARSER_DUPLICATED_MSG";
+        case COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING:
+            return "COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING";
+        case COAP_STATUS_PARSER_BLOCKWISE_ACK:
+            return "COAP_STATUS_PARSER_BLOCKWISE_ACK";
+        case COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED:
+            return "COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED";
+        case COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED:
+            return "COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED";
+        case COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED:
+            return "COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED";
+        default:
+            return "";
+    }
+}
+
+const char *sn_nsdl_coap_message_code_desc(int msg_code)
+{
+    switch(msg_code) {
+        case COAP_MSG_CODE_EMPTY:
+            return "COAP_MSG_CODE_EMPTY";
+        case COAP_MSG_CODE_REQUEST_GET:
+            return "COAP_MSG_CODE_REQUEST_GET";
+        case COAP_MSG_CODE_REQUEST_POST:
+            return "COAP_MSG_CODE_REQUEST_POST";
+        case COAP_MSG_CODE_REQUEST_PUT:
+            return "COAP_MSG_CODE_REQUEST_PUT";
+        case COAP_MSG_CODE_REQUEST_DELETE:
+            return "COAP_MSG_CODE_REQUEST_DELETE";
+        case COAP_MSG_CODE_RESPONSE_CREATED:
+            return "COAP_MSG_CODE_RESPONSE_CREATED";
+        case COAP_MSG_CODE_RESPONSE_DELETED:
+            return "COAP_MSG_CODE_RESPONSE_DELETED";
+        case COAP_MSG_CODE_RESPONSE_VALID:
+            return "COAP_MSG_CODE_RESPONSE_VALID";
+        case COAP_MSG_CODE_RESPONSE_CHANGED:
+            return "COAP_MSG_CODE_RESPONSE_CHANGED";
+        case COAP_MSG_CODE_RESPONSE_CONTENT:
+            return "COAP_MSG_CODE_RESPONSE_CONTENT";
+        case COAP_MSG_CODE_RESPONSE_CONTINUE:
+            return "COAP_MSG_CODE_RESPONSE_CONTINUE";
+        case COAP_MSG_CODE_RESPONSE_BAD_REQUEST:
+            return "COAP_MSG_CODE_RESPONSE_BAD_REQUEST";
+        case COAP_MSG_CODE_RESPONSE_UNAUTHORIZED:
+            return "COAP_MSG_CODE_RESPONSE_UNAUTHORIZED";
+        case COAP_MSG_CODE_RESPONSE_BAD_OPTION:
+            return "COAP_MSG_CODE_RESPONSE_BAD_OPTION";
+        case COAP_MSG_CODE_RESPONSE_FORBIDDEN:
+            return "COAP_MSG_CODE_RESPONSE_FORBIDDEN";
+        case COAP_MSG_CODE_RESPONSE_NOT_FOUND:
+            return "COAP_MSG_CODE_RESPONSE_NOT_FOUND";
+        case COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED:
+            return "COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED";
+        case COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE:
+            return "COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE";
+        case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE:
+            return "COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE";
+        case COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED:
+            return "COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED";
+        case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE:
+            return "COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE";
+        case COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT:
+            return "COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT";
+        case COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR:
+            return "COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR";
+        case COAP_MSG_CODE_RESPONSE_NOT_IMPLEMENTED:
+            return "COAP_MSG_CODE_RESPONSE_NOT_IMPLEMENTED";
+        case COAP_MSG_CODE_RESPONSE_BAD_GATEWAY:
+            return "COAP_MSG_CODE_RESPONSE_BAD_GATEWAY";
+        case COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE:
+            return "COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE";
+        case COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT:
+            return "COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT";
+        case COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED:
+            return "COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED";
+        default:
+            return "";
+    }
+}
+
+const char *sn_nsdl_coap_message_type_desc(int msg_type)
+{
+    switch(msg_type) {
+        case COAP_MSG_TYPE_CONFIRMABLE:
+            return "COAP_MSG_TYPE_CONFIRMABLE";
+        case COAP_MSG_TYPE_NON_CONFIRMABLE:
+            return "COAP_MSG_TYPE_NON_CONFIRMABLE";
+        case COAP_MSG_TYPE_ACKNOWLEDGEMENT:
+            return "COAP_MSG_TYPE_ACKNOWLEDGEMENT";
+        case COAP_MSG_TYPE_RESET:
+            return "COAP_MSG_TYPE_RESET";
+        default:
+            return "";
+    }
+}
+#endif
+
+void remove_previous_block_data(struct nsdl_s *handle, sn_nsdl_addr_s *src_ptr, const uint32_t block_number)
+{
+#if SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+    ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->grs->coap->linked_list_blockwise_received_payloads) {
+        uint32_t stored_number = stored_payload_info_ptr->block_number;
+        // Remove the previous block data
+        if (block_number - 1 == stored_number) {
+            sn_coap_protocol_block_remove(handle->grs->coap,
+                    src_ptr,
+                    stored_payload_info_ptr->payload_len,
+                    stored_payload_info_ptr->payload_ptr);
+            break;
+        }
+    }
+#endif
+}
+
+bool update_last_block_data(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, bool block1)
+{
+    bool data_updated = false;
+    // Whole message received --> pass only the last block data to application
+    if (coap_packet_ptr->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) {
+        // Get the block size
+        uint8_t temp = 0;
+        if (block1) {
+            temp = (coap_packet_ptr->options_list_ptr->block1 & 0x07);
+        } else {
+            temp = (coap_packet_ptr->options_list_ptr->block2 & 0x07);
+        }
+        uint16_t block_size = 1u << (temp + 4);
+
+        uint32_t new_payload_len = coap_packet_ptr->payload_len - block_size;
+        uint8_t *temp_ptr =  handle->grs->coap->sn_coap_protocol_malloc(new_payload_len);
+        if (temp_ptr) {
+            // Skip the second last block data since it's still stored in mbed-coap list!
+            memcpy(temp_ptr, coap_packet_ptr->payload_ptr + block_size, new_payload_len);
+            handle->grs->coap->sn_coap_protocol_free(coap_packet_ptr->payload_ptr);
+            coap_packet_ptr->payload_ptr = temp_ptr;
+            coap_packet_ptr->payload_len = new_payload_len;
+            data_updated = true;
+        }
+    }
+
+    return data_updated;
+}
+
+static void sn_nsdl_add_token(struct nsdl_s *handle, uint32_t *token, sn_coap_hdr_s *message_ptr)
+{
+    handle->token_seed++;
+    if (handle->token_seed == 0) {
+        handle->token_seed++;
+    }
+
+    *token = handle->token_seed;
+
+    message_ptr->token_ptr = (uint8_t*)token;
+    message_ptr->token_len = sizeof(*token);
+}
+
+uint16_t sn_nsdl_get_block_size(const struct nsdl_s *handle)
+{
+    if (handle == NULL) {
+        return 0;
+    }
+
+    return handle->grs->coap->sn_coap_block_data_size;
+}
+
+extern uint8_t sn_nsdl_get_retransmission_count(struct nsdl_s *handle)
+{
+#if ENABLE_RESENDINGS
+    if (handle == NULL) {
+        return 0;
+    }
+
+    return handle->grs->coap->sn_coap_resending_count;
+#else
+    (void) handle;
+    return 0;
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+test/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/mbed-client-classic/m2mconnectionhandlerpimpl.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_CONNECTION_HANDLER_PIMPL_H__
+#define M2M_CONNECTION_HANDLER_PIMPL_H__
+
+#include "ns_types.h"
+#include "ns_list.h"
+#include "eventOS_event.h"
+#include "mbed-client/m2mconfig.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2minterface.h"
+#include "mbed-client/m2mconnectionobserver.h"
+#include "mbed-client/m2mconnectionsecurity.h"
+#include "nsdl-c/sn_nsdl.h"
+#include "pal.h"
+
+
+class M2MConnectionSecurity;
+class M2MConnectionHandler;
+class M2MSecurity;
+
+/**
+ * @brief M2MConnectionHandlerPimpl.
+ * This class handles the socket connection for LWM2M Client
+ */
+
+
+class M2MConnectionHandlerPimpl {
+public:
+
+    enum SocketEvent {
+        ESocketIdle          = 0x00,
+        ESocketCallback      = 0x02,
+        ESocketConnect       = 0x04,
+        ESocketSend          = 0x08,
+        ESocketDnsResolved   = 0x10,
+        ESocketDnsError      = 0x20,
+        ESocketClose         = 0x40,
+        ESocketTimerCallback = 0x80
+    };
+
+    /**
+    * @brief Constructor
+    */
+    M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer,
+                              M2MConnectionSecurity* sec,
+                              M2MInterface::BindingMode mode,
+                              M2MInterface::NetworkStack /*stack*/);
+
+    /**
+    * @brief Destructor
+    */
+    ~M2MConnectionHandlerPimpl();
+
+    void start_timer(void);
+
+    /**
+    * @brief This binds the socket connection.
+    * @param listen_port Port to listen for incoming connection.
+    * @return true if successful else false.
+    */
+    bool bind_connection(const uint16_t listen_port);
+
+    /**
+    * @brief This resolves the server address. Output is
+    * returned through callback
+    * @param String server address.
+    * @param uint16_t Server port.
+    * @param ServerType, Server Type to be resolved.
+    * @return true if address is valid else false.
+    */
+    bool resolve_server_address(const String& server_address,
+                                const uint16_t server_port,
+                                M2MConnectionObserver::ServerType server_type,
+                                const M2MSecurity* security);
+
+    /**
+    * @brief Sends data, to the connected sent to server.
+    * @param data, Data to be sent.
+    */
+    bool send_data(uint8_t *data_ptr,
+                   uint16_t data_len,
+                   sn_nsdl_addr_s *address_ptr);
+
+    /**
+    * @brief Listens for incoming data from remote server
+    * @return true if successful else false.
+    */
+    bool start_listening_for_data();
+
+    /**
+    * @brief Stops listening for incoming data
+    */
+    void stop_listening();
+
+    /**
+    * @brief Error handling for DTLS connectivity.
+    * @param error, Error code from TLS library
+    */
+    void handle_connection_error(int error);
+
+    /**
+     * \brief Sets the network interface handler that is used by client to connect
+     * to a network over IP..
+     * \param handler A network interface handler that is used by client to connect.
+     *  This API is optional but provides a mechanism for different platforms to
+     * manage usage of underlying network interface by client.
+     */
+    void set_platform_network_handler(void *handler = NULL);
+
+    /**
+    * \brief Claims mutex to prevent thread clashes
+    * in multithreaded environment.
+    */
+    void claim_mutex();
+
+    /**
+    * \brief Releases mutex to prevent thread clashes
+    * in multithreaded environment.
+    */
+    void release_mutex();
+
+    /**
+    * @brief Callback handler for receiving data over socket.
+    */
+    void receive_handler();
+
+    /**
+    * @brief Returns true if DTLS handshake is still ongoing.
+    */
+    bool is_handshake_ongoing() const;
+
+    /**
+    * @brief Sends data to socket through event loop.
+    */
+    void send_socket_data();
+
+    /**
+    * @brief This function is used for generating socket events.
+    */
+    void send_socket_event(SocketEvent event_type);
+
+    /**
+    * @brief Does DNS resolving. Return true if DNS has been resolved
+    * or triggered though DNS thread.
+    */
+    bool address_resolver(void);
+
+    /**
+     * @brief handler for eventloop events. Note, this needs to be public as it is called
+     * from C wrapper.
+     */
+    void event_handler(arm_event_s *event);
+
+    /**
+    * \brief Closes the open connection.
+    * \note This must be called from the same event loop context!
+    */
+    void force_close();
+
+private:
+
+    /**
+    * @brief Terminate the DNS thread, if any is used. The #ifdef magic is inside this
+    * method, so it can be used without ifdef guards.
+     */
+    void terminate_dns_thread();
+
+    /**
+    * @brief Handles socket initialization and connect phase.
+    */
+    void socket_connect_handler();
+
+    /**
+    * @brief Callback handler for receiving data for secured connection.
+    */
+    void receive_handshake_handler();
+
+    /**
+    * @brief Callback handler for socket events.
+    */
+    void socket_event();
+
+    /**
+    * @brief Handles the result set by address_resolver.
+    */
+    void handle_dns_result(bool success);
+
+
+    /**
+    * @brief Initialize socket
+    */
+    bool init_socket();
+
+    /**
+    * @brief Check socket type
+    * @return True if TCP connection otherwise false
+    */
+    bool is_tcp_connection() const;
+
+    /**
+    * @brief Close and delete socket
+    */
+    void close_socket();
+
+public:
+
+    /**
+     * @brief Internal helper for sending an event.
+     */
+    bool send_event(SocketEvent event_type);
+
+private:
+    typedef struct send_data_queue {
+        uint8_t *data;
+        uint16_t offset;
+        uint16_t data_len;
+        ns_list_link_t link;
+    } send_data_queue_s;
+
+    /**
+     * @brief Get first item from the queue list.
+     */
+    send_data_queue_s* get_item_from_list();
+
+    /**
+     * @brief Add queue data back to list.
+     */
+    void add_item_to_list(send_data_queue_s* data);
+
+private:
+    enum SocketState {
+
+        /* NOTE: Order of these values does matter, do not make unplanned changes to it. */
+
+        /** Socket has not been initialized/connected yet. */
+        ESocketStateDisconnected,
+
+        /** pal_close() is in progress. */
+        ESocketStateCloseBeingCalled,
+
+        /** DNS resolving in progress. */
+        ESocketStateDNSResolving,
+
+        /** DNS resolving done, connection needs to be initialized.  */
+        EsocketStateInitializeConnection,
+
+        /** pal_connect() is in progress. */
+        ESocketStateConnectBeingCalled,
+
+        /** pal_connect() has been called and we are waiting for asynchronous response. */
+        ESocketStateConnecting,
+
+        /** pal_connect is complete and the (D)TLS handshake is to be done if in secure mode. */
+        ESocketStateConnected,
+
+        /** (D)TLS Handshaking in progress */
+        ESocketStateHandshaking,
+
+        /** Unsecure Connection to the server has been established */
+        ESocketStateUnsecureConnection,
+
+        /** Secure Connection to the server has been established */
+        ESocketStateSecureConnection
+    };
+
+    typedef NS_LIST_HEAD(send_data_queue_s, link) send_data_list_t;
+
+    M2MConnectionHandler                        *_base;
+    M2MConnectionObserver                       &_observer;
+    M2MConnectionSecurity                       *_security_impl; //owned
+    const M2MSecurity                           *_security; //non-owned
+    M2MInterface::BindingMode                   _binding_mode;
+    M2MConnectionObserver::SocketAddress        _address;
+
+    // _address._address will point to one of these two
+    palIpV4Addr_t                               _ipV4Addr;
+    palIpV6Addr_t                               _ipV6Addr;
+
+    palSocket_t                                 _socket;
+    M2MConnectionObserver::ServerType           _server_type;
+    uint16_t                                    _server_port;
+    uint16_t                                    _listen_port;
+    uint32_t                                    _net_iface;
+#if (PAL_DNS_API_VERSION < 2)
+    palSocketLength_t                           _socket_address_len;
+#endif
+#if MBED_CONF_MBED_CLIENT_DNS_USE_THREAD
+#if (PAL_DNS_API_VERSION == 2)
+    palDNSQuery_t                                _handler_async_DNS;
+#endif
+#endif
+    volatile palSocketAddress_t                 _socket_address;
+    static int8_t                               _tasklet_id;
+    String                                      _server_address;
+
+    // A state variable for the socket itself, which is needed to handle the
+    // asynchronous events and callbacks. Note: the state may be accessed from
+    // event sender and receiver threads.
+    SocketState                                 _socket_state;
+    uint8_t                                     _handshake_retry;
+
+    /**
+     * This is a flag which is set before sending a socket callback event
+     * and cleared when the event handler side is started. It is meant to get rid of
+     * event storm which happens whenever one socket transfers data and spurious
+     * events are sent to all the other sockets.
+     */
+    volatile bool                               _suppressable_event_in_flight;
+
+    send_data_list_t                            _linked_list_send_data;
+
+    bool                                        _secure_connection;
+
+friend class Test_M2MConnectionHandlerPimpl;
+friend class Test_M2MConnectionHandlerPimpl_mbed;
+friend class Test_M2MConnectionHandlerPimpl_classic;
+friend class M2MConnection_TestObserver;
+};
+
+#endif //M2M_CONNECTION_HANDLER_PIMPL_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/mbed-client-classic/m2mtimerpimpl.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifndef M2M_TIMER_PIMPL_H__
+#define M2M_TIMER_PIMPL_H__
+
+#include "ns_types.h"
+#include "eventOS_event.h"
+#include "mbed-client/m2mtimerobserver.h"
+
+class M2MTimerPimpl {
+private:
+
+    // Prevents the use of assignment operator
+    M2MTimerPimpl& operator=(const M2MTimerPimpl& other);
+
+    // Prevents the use of copy constructor
+    M2MTimerPimpl(const M2MTimerPimpl& other);
+public:
+
+    /**
+     * Constructor.
+     */
+    M2MTimerPimpl(M2MTimerObserver& _observer);
+
+    /**
+     * Destructor.
+     */
+    virtual ~M2MTimerPimpl();
+
+    /**
+     * Starts timer
+     * @param interval Timer's interval in milliseconds
+     * @param single_shot defines if timer is ticked
+     * once or is it restarted everytime timer is expired.
+     */
+    void start_timer(uint64_t interval, M2MTimerObserver::Type type, bool single_shot = true);
+
+    /**
+     * @brief Starts timer in DTLS manner
+     * @param intermediate_interval Intermediate interval to use, must be smaller than tiotal (usually 1/4 of total)
+     * @param total_interval Total interval to use; This is the timeout value of a DTLS packet
+     * @param type Type of the timer
+     */
+    void start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type);
+
+    /**
+     * Stops timer.
+     * This cancels the ongoing timer.
+     */
+    void stop_timer();
+
+    /**
+     * @brief Checks if the intermediate interval has passed
+     * @return true if interval has passed, false otherwise
+     */
+    bool is_intermediate_interval_passed() const;
+
+    /**
+     * @brief Checks if the total interval has passed
+     * @return true if interval has passed, false otherwise
+     */
+    bool is_total_interval_passed() const;
+
+    /**
+     * @brief Get still left time
+     * @return Time left in milliseconds
+     */
+    uint64_t get_still_left_time() const;
+
+    /**
+     * Tasklet's internal event handler, which needs to be public as it is used from C wrapper side.
+     * This makes it possible to at least keep the member variables private.
+     */
+    void handle_timer_event(const arm_event_s &event);
+
+private:
+
+    /**
+     * Second phase of initialization, which will create the tasklet upon first call to
+     * to any of the M2MTimerPimpl instances a start_timer() or start_dtls_timer().
+     */
+    void initialize_tasklet();
+
+    /**
+     * @brief Start long period timer
+     */
+    void start_still_left_timer();
+
+    /**
+     * Function handling the timer completion.
+     */
+    void timer_expired();
+
+    void start();
+    void cancel();
+
+    /**
+     * Internal helper to request a event after given amount of milliseconds.
+     * @param delay_ms requested delay in milliseconds
+     */
+    void request_event_in(int32_t delay_ms);
+
+private:
+    M2MTimerObserver&   _observer;
+    uint64_t            _interval;
+
+    uint64_t            _intermediate_interval;
+    uint64_t            _total_interval;
+    uint64_t            _still_left;
+
+    // pointer to the current timer event pending, NULL if none is in flight
+    arm_event_storage_t *_timer_event;
+
+    M2MTimerObserver::Type  _type : 4;
+
+    unsigned int        _status : 2;
+
+    bool                _dtls_type : 1;
+
+    bool                _single_shot : 1;
+
+    static int8_t       _tasklet_id;
+
+    friend class M2MTimer;
+    friend class Test_M2MTimerPimpl_classic;
+};
+
+#endif //M2M_TIMER_PIMPL_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/source/m2mconnectionhandler.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "mbed-client-classic/m2mconnectionhandlerpimpl.h"
+#include "mbed-client/m2mconnectionobserver.h"
+#include "mbed-client/m2mconnectionhandler.h"
+#include "mbed-client/m2mconstants.h"
+
+M2MConnectionHandler::M2MConnectionHandler(M2MConnectionObserver &observer,
+                                           M2MConnectionSecurity* sec,
+                                           M2MInterface::BindingMode mode,
+                                           M2MInterface::NetworkStack stack)
+:_observer(observer)
+{
+    _private_impl = new M2MConnectionHandlerPimpl(this, observer, sec, mode, stack);
+}
+
+M2MConnectionHandler::~M2MConnectionHandler()
+{
+    delete _private_impl;
+}
+
+bool M2MConnectionHandler::bind_connection(const uint16_t listen_port)
+{
+
+    return _private_impl->bind_connection(listen_port);
+}
+
+bool M2MConnectionHandler::resolve_server_address(const String& server_address,
+                                                      const uint16_t server_port,
+                                                      M2MConnectionObserver::ServerType server_type,
+                                                      const M2MSecurity* security)
+{
+    return _private_impl->resolve_server_address(server_address, server_port,
+                                                 server_type, security);
+}
+
+bool M2MConnectionHandler::start_listening_for_data()
+{
+    return _private_impl->start_listening_for_data();
+}
+
+void M2MConnectionHandler::stop_listening()
+{
+    _private_impl->stop_listening();
+}
+
+bool M2MConnectionHandler::send_data(uint8_t *data,
+                                     uint16_t data_len,
+                                     sn_nsdl_addr_s *address)
+{
+    return _private_impl->send_data(data, data_len, address);
+}
+
+void M2MConnectionHandler::handle_connection_error(int error)
+{
+    _private_impl->handle_connection_error(error);
+}
+
+void M2MConnectionHandler::set_platform_network_handler(void *handler)
+{
+    _private_impl->set_platform_network_handler(handler);
+}
+
+void M2MConnectionHandler::claim_mutex()
+{
+    _private_impl->claim_mutex();
+}
+
+void M2MConnectionHandler::release_mutex()
+{
+    _private_impl->release_mutex();
+}
+
+void M2MConnectionHandler::force_close()
+{
+    _private_impl->force_close();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/source/m2mconnectionhandlerpimpl.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,958 @@
+/*
+ * Copyright (c) 2015 - 2017 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+// fixup the compilation on ARMCC for PRIu32
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include "mbed-client-classic/m2mconnectionhandlerpimpl.h"
+#include "mbed-client/m2mconnectionobserver.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2msecurity.h"
+#include "mbed-client/m2mconnectionhandler.h"
+
+#include "pal.h"
+
+#include "eventOS_scheduler.h"
+
+#include "eventOS_event_timer.h"
+
+#include "mbed-trace/mbed_trace.h"
+
+#include <stdlib.h> // free() and malloc()
+
+#define TRACE_GROUP "mClt"
+
+#ifndef MBED_CONF_MBED_CLIENT_TLS_MAX_RETRY
+#define MBED_CONF_MBED_CLIENT_TLS_MAX_RETRY 60
+#endif
+
+#ifndef MBED_CONF_MBED_CLIENT_DNS_USE_THREAD
+#define MBED_CONF_MBED_CLIENT_DNS_USE_THREAD 0
+#endif
+
+int8_t M2MConnectionHandlerPimpl::_tasklet_id = -1;
+
+// This is called from event loop, but as it is static C function, this is just a wrapper
+// which calls C++ on the instance.
+extern "C" void eventloop_event_handler(arm_event_s *event)
+{
+    tr_debug("M2MConnectionHandlerPimpl::eventloop_event_handler %d", event->event_type);
+    if (event->event_type != M2MConnectionHandlerPimpl::ESocketIdle) {
+        if(!event->data_ptr) {
+            tr_error("M2MConnectionHandlerPimpl::eventloop_event_handler event->data_ptr=NULL !!!!");
+            assert(event->data_ptr);
+        }
+        M2MConnectionHandlerPimpl* instance = (M2MConnectionHandlerPimpl*)event->data_ptr;
+        instance->event_handler(event);
+    }
+}
+
+// event handler that forwards the event according to its type and/or connection state
+void M2MConnectionHandlerPimpl::event_handler(arm_event_s *event)
+{
+    switch (event->event_type) {
+
+        // Event from socket callback method
+        case M2MConnectionHandlerPimpl::ESocketCallback:
+        case M2MConnectionHandlerPimpl::ESocketTimerCallback:
+
+            // this will enable sending more events during this event processing, but that is less evil than missing one
+            _suppressable_event_in_flight = false;
+
+            if (_socket_state == M2MConnectionHandlerPimpl::ESocketStateHandshaking) {
+                receive_handshake_handler();
+            } else if ((_socket_state == M2MConnectionHandlerPimpl::ESocketStateUnsecureConnection) ||
+                       (_socket_state == M2MConnectionHandlerPimpl::ESocketStateSecureConnection)) {
+                // the connection is established
+                receive_handler();
+            } else {
+                socket_connect_handler();
+            }
+
+            // Receive processing could have changed state, so recheck
+            if ((_socket_state == M2MConnectionHandlerPimpl::ESocketStateUnsecureConnection) ||
+                (_socket_state == M2MConnectionHandlerPimpl::ESocketStateSecureConnection)) {
+                // the connection is established
+                send_socket_data();
+            }
+            break;
+
+        // Data send request from client side
+        case M2MConnectionHandlerPimpl::ESocketSend:
+            send_socket_data();
+            break;
+
+        // DNS resolved successfully
+        case M2MConnectionHandlerPimpl::ESocketDnsResolved:
+            handle_dns_result(true);
+            break;
+
+            // DNS resolving failed
+        case M2MConnectionHandlerPimpl::ESocketDnsError:
+            handle_dns_result(false);
+            break;
+
+        // Establish the connection by connecting the socket
+        case M2MConnectionHandlerPimpl::ESocketConnect:
+            socket_connect_handler();
+            break;
+
+        case M2MConnectionHandlerPimpl::ESocketClose:
+            close_socket();
+            break;
+
+        default:
+            tr_debug("M2MConnectionHandlerPimpl::connection_event_handler: default type: %d", (int)event->event_type);
+            break;
+    }
+}
+
+// This callback is used from PAL sockets, it is called with object instance as argument.
+// This is received from "some" socket event from "some" socket and the C++ side is responsible
+// of forwarding it or ignoring the event completely.
+extern "C" void socket_event_handler(void* arg)
+{
+    M2MConnectionHandlerPimpl* instance = (M2MConnectionHandlerPimpl*)arg;
+
+    if (!instance) {
+        tr_error("Invalid callback argument");
+        return;
+    }
+
+    instance->send_socket_event(M2MConnectionHandlerPimpl::ESocketCallback);
+}
+
+void M2MConnectionHandlerPimpl::send_socket_event(SocketEvent event_type)
+{
+    // the socket callback events can safely be suppressed, the receiving end must tolerate that
+    if (event_type == ESocketCallback) {
+        // only the socket connected state supports retries somehow
+        if (_suppressable_event_in_flight == false) {
+            _suppressable_event_in_flight = true;
+        } else {
+            // XXX: DO NOT ADD FOLLOWING LINE TO OFFICIAL GIT, THIS WILL KILL SOME NETWORK STACKS
+            // IF EVENT IS SENT FROM A INTERRUPT CONTEXT
+            // tr_debug("** SKIPPING event");
+            return;
+        }
+    }
+
+    if (!send_event(event_type)) {
+        // TODO: give a proper error based on state instead of this
+        _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
+    }
+}
+
+M2MConnectionHandlerPimpl::M2MConnectionHandlerPimpl(M2MConnectionHandler* base, M2MConnectionObserver &observer,
+                                                     M2MConnectionSecurity* sec,
+                                                     M2MInterface::BindingMode mode,
+                                                     M2MInterface::NetworkStack stack)
+:_base(base),
+ _observer(observer),
+ _security_impl(sec),
+ _security(NULL),
+ _binding_mode(mode),
+ _socket(0),
+ _server_type(M2MConnectionObserver::LWM2MServer),
+ _server_port(0),
+ _listen_port(0),
+ _net_iface(0),
+#if (PAL_DNS_API_VERSION == 2)
+  _handler_async_DNS(0),
+#endif
+ _socket_state(ESocketStateDisconnected),
+ _handshake_retry(0),
+ _suppressable_event_in_flight(false),
+ _secure_connection(false)
+#if (PAL_DNS_API_VERSION < 2)
+ ,_socket_address_len(0)
+#endif
+{
+#ifndef PAL_NET_TCP_AND_TLS_SUPPORT
+    if (is_tcp_connection()) {
+        tr_error("ConnectionHandler: TCP support not available.");
+        return;
+    }
+#endif
+
+    if (PAL_SUCCESS != pal_init()) {
+        tr_error("PAL init failed.");
+    }
+
+    memset(&_address, 0, sizeof _address);
+    memset((void*)&_socket_address, 0, sizeof _socket_address);
+    memset(&_ipV4Addr, 0, sizeof(palIpV4Addr_t));
+    memset(&_ipV6Addr, 0, sizeof(palIpV6Addr_t));
+    ns_list_init(&_linked_list_send_data);
+
+    eventOS_scheduler_mutex_wait();
+    if (M2MConnectionHandlerPimpl::_tasklet_id == -1) {
+        M2MConnectionHandlerPimpl::_tasklet_id = eventOS_event_handler_create(&eventloop_event_handler, ESocketIdle);
+    }
+    eventOS_scheduler_mutex_release();
+}
+
+M2MConnectionHandlerPimpl::~M2MConnectionHandlerPimpl()
+{
+    tr_debug("~M2MConnectionHandlerPimpl()");
+#if MBED_CONF_MBED_CLIENT_DNS_USE_THREAD
+#if (PAL_DNS_API_VERSION == 2)
+    if ( _handler_async_DNS > 0) {
+        pal_cancelAddressInfoAsync(_handler_async_DNS);
+    }
+#endif
+#endif
+
+    close_socket();
+    delete _security_impl;
+    _security_impl = NULL;
+    pal_destroy();
+    tr_debug("~M2MConnectionHandlerPimpl() - OUT");
+}
+
+bool M2MConnectionHandlerPimpl::bind_connection(const uint16_t listen_port)
+{
+    _listen_port = listen_port;
+    return true;
+}
+
+bool M2MConnectionHandlerPimpl::send_event(SocketEvent event_type)
+{
+    arm_event_s event = {0};
+
+    event.receiver = M2MConnectionHandlerPimpl::_tasklet_id;
+    event.sender = 0;
+    event.event_type = event_type;
+    event.data_ptr = this;
+    event.event_data = 0;
+    event.priority = ARM_LIB_HIGH_PRIORITY_EVENT;
+    return !eventOS_event_send(&event);
+}
+
+// This callback is used from PAL pal_getAddressInfoAsync,
+#if MBED_CONF_MBED_CLIENT_DNS_USE_THREAD
+#if (PAL_DNS_API_VERSION < 2)
+extern "C" void address_resolver_cb(const char* url, palSocketAddress_t* address, palSocketLength_t* addressLength, palStatus_t status, void* callbackArgument)
+#else
+extern "C" void address_resolver_cb(const char* url, palSocketAddress_t* address, palStatus_t status, void* callbackArgument)
+#endif
+{
+    tr_debug("M2MConnectionHandlerPimpl::address_resolver callback");
+    M2MConnectionHandlerPimpl* instance = (M2MConnectionHandlerPimpl*)callbackArgument;
+
+    if (PAL_SUCCESS != status) {
+        tr_error("M2MConnectionHandlerPimpl::address_resolver callback failed with 0x%X", status);
+        if (!(instance->send_event(M2MConnectionHandlerPimpl::ESocketDnsError))) {
+            tr_error("M2MConnectionHandlerPimpl::address_resolver callback, error event alloc fail.");
+        }
+    } else {
+        if (!(instance->send_event(M2MConnectionHandlerPimpl::ESocketDnsResolved))) {
+            tr_error("M2MConnectionHandlerPimpl::address_resolver callback, resolved event alloc fail.");
+        }
+    }
+}
+#endif
+
+bool M2MConnectionHandlerPimpl::address_resolver(void)
+{
+    palStatus_t status;
+    bool ret = false;
+
+#if MBED_CONF_MBED_CLIENT_DNS_USE_THREAD
+    tr_debug("M2MConnectionHandlerPimpl::address_resolver:asynchronous DNS");
+
+#if (PAL_DNS_API_VERSION < 2)
+    status = pal_getAddressInfoAsync(_server_address.c_str(), (palSocketAddress_t*)&_socket_address, &_socket_address_len, &address_resolver_cb, this);
+#else
+    _handler_async_DNS = 0;
+    status = pal_getAddressInfoAsync(_server_address.c_str(), (palSocketAddress_t*)&_socket_address, &address_resolver_cb, this, &_handler_async_DNS);
+#endif
+    if (PAL_SUCCESS != status) {
+       tr_error("M2MConnectionHandlerPimpl::address_resolver, pal_getAddressInfoAsync fail. 0x%X", status);
+       _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR);
+    }
+    else {
+        ret = true;
+    }
+#else
+    tr_debug("M2MConnectionHandlerPimpl::address_resolver:synchronous DNS");
+    status = pal_getAddressInfo(_server_address.c_str(), (palSocketAddress_t*)&_socket_address, &_socket_address_len);
+    if (PAL_SUCCESS != status) {
+        tr_error("M2MConnectionHandlerPimpl::getAddressInfo failed with 0x%X", status);
+        if (!send_event(ESocketDnsError)) {
+            tr_error("M2MConnectionHandlerPimpl::address_resolver, error event alloc fail.");
+        }
+    } else {
+        if (!send_event(ESocketDnsResolved)) {
+            tr_error("M2MConnectionHandlerPimpl::address_resolver, resolved event alloc fail.");
+        }
+        else {
+            ret = true;
+        }
+    }
+#endif
+    return ret;
+}
+
+void M2MConnectionHandlerPimpl::handle_dns_result(bool success)
+{
+#if MBED_CONF_MBED_CLIENT_DNS_USE_THREAD
+#if (PAL_DNS_API_VERSION == 2)
+    _handler_async_DNS = 0;
+#endif
+#endif
+    if (_socket_state != ESocketStateDNSResolving) {
+        tr_warn("M2MConnectionHandlerPimpl::handle_dns_result() called, not in ESocketStateDNSResolving state!");
+        return;
+    }
+
+    if (success) {
+        _socket_state = EsocketStateInitializeConnection;
+        socket_connect_handler();
+
+    } else {
+        _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR);
+    }
+}
+
+bool M2MConnectionHandlerPimpl::resolve_server_address(const String& server_address,
+                                                       const uint16_t server_port,
+                                                       M2MConnectionObserver::ServerType server_type,
+                                                       const M2MSecurity* security)
+{
+#if MBED_CONF_MBED_CLIENT_DNS_USE_THREAD
+#if (PAL_DNS_API_VERSION == 2)
+    if ( _handler_async_DNS > 0) {
+        if (pal_cancelAddressInfoAsync(_handler_async_DNS) != PAL_SUCCESS) {
+            return false;
+        }
+    }
+#endif
+#endif
+    _socket_state = ESocketStateDNSResolving;
+    _security = security;
+
+    int32_t security_instance_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
+    if (server_type == M2MConnectionObserver::Bootstrap) {
+        security_instance_id = _security->get_security_instance_id(M2MSecurity::Bootstrap);
+    }
+
+    if (_security &&
+        security_instance_id >= 0 &&
+        (_security->resource_value_int(M2MSecurity::SecurityMode, security_instance_id) == M2MSecurity::Certificate ||
+         _security->resource_value_int(M2MSecurity::SecurityMode, security_instance_id) == M2MSecurity::Psk)) {
+        _secure_connection = true;
+    }
+
+    _server_port = server_port;
+    _server_type = server_type;
+    _server_address = server_address;
+
+
+    return address_resolver();
+}
+
+void M2MConnectionHandlerPimpl::socket_connect_handler()
+{
+    palStatus_t status;
+    int32_t security_instance_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
+    if (_server_type == M2MConnectionObserver::Bootstrap) {
+        security_instance_id = _security->get_security_instance_id(M2MSecurity::Bootstrap);
+    }
+
+    tr_debug("M2MConnectionHandlerPimpl::socket_connect_handler - _socket_state = %d", _socket_state);
+
+    switch (_socket_state) {
+        case ESocketStateCloseBeingCalled:
+        case ESocketStateDNSResolving:
+        case ESocketStateDisconnected:
+        case ESocketStateHandshaking:
+        case ESocketStateUnsecureConnection:
+        case ESocketStateSecureConnection:
+            // Ignore these events
+            break;
+
+        case EsocketStateInitializeConnection:
+
+            // Initialize the socket to stable state
+            close_socket();
+
+            status = pal_setSockAddrPort((palSocketAddress_t*)&_socket_address, _server_port);
+
+            if (PAL_SUCCESS != status) {
+                tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - setSockAddrPort err: %d", (int)status);
+            } else {
+                tr_debug("address family: %d", (int)_socket_address.addressType);
+            }
+
+            if (_socket_address.addressType == PAL_AF_INET) {
+                status = pal_getSockAddrIPV4Addr((palSocketAddress_t*)&_socket_address,_ipV4Addr);
+                if (PAL_SUCCESS != status) {
+                    tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - sockAddr4, err: %d", (int)status);
+                    _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR);
+                    return;
+                }
+
+                tr_info("M2MConnectionHandlerPimpl::socket_connect_handler - IPv4 Address %d.%d.%d.%d",
+                        _ipV4Addr[0], _ipV4Addr[1], _ipV4Addr[2], _ipV4Addr[3]);
+
+                _address._address = (void*)_ipV4Addr;
+                _address._length = PAL_IPV4_ADDRESS_SIZE;
+                _address._port = _server_port;
+            } else if (_socket_address.addressType == PAL_AF_INET6) {
+                status = pal_getSockAddrIPV6Addr((palSocketAddress_t*)&_socket_address,_ipV6Addr);
+                if (PAL_SUCCESS != status) {
+                    tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - sockAddr6, err: %d", (int)status);
+                    _observer.socket_error(M2MConnectionHandler::DNS_RESOLVING_ERROR);
+                    return;
+                }
+
+                tr_info("M2MConnectionHandlerPimpl::socket_connect_handler - IPv6 Address: %s", mbed_trace_ipv6(_ipV6Addr));
+
+                _address._address = (void*)_ipV6Addr;
+                _address._length = PAL_IPV6_ADDRESS_SIZE;
+                _address._port = _server_port;
+            } else {
+                tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - socket config error, stack: %d", (int)_socket_address.addressType);
+                _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
+                return;
+            }
+
+            if (!init_socket()) {
+                tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - socket init error");
+                // The init_socket() calls the socket_error() -callback directly, so it must not be
+                // done here too.
+                return;
+            }
+
+            // This state was used to ignore the spurious events _during_ the call of non-blocking pal_connect().
+            // Now that we just retry connect when it is not yet succeeded anyway this state might be removed completely.
+            _socket_state = ESocketStateConnectBeingCalled;
+
+        // fall through is intentional
+        case ESocketStateConnectBeingCalled:
+        case ESocketStateConnecting:
+            if (is_tcp_connection()) {
+#ifdef PAL_NET_TCP_AND_TLS_SUPPORT
+                tr_info("M2MConnectionHandlerPimpl::socket_connect_handler - Using TCP");
+
+                status = pal_connect(_socket, (palSocketAddress_t*)&_socket_address, sizeof(_socket_address));
+
+                if ((status == PAL_ERR_SOCKET_IN_PROGRES) || (status == PAL_ERR_SOCKET_WOULD_BLOCK)) {
+                    // In this case the connect is done asynchronously, and the pal_socketMiniSelect()
+                    // will be used to detect the end of connect.
+                    tr_debug("M2MConnectionHandlerPimpl::socket_connect_handler - pal_connect(): %d, async connect started", (int)status);
+                    // we need to wait for the event
+                    _socket_state = ESocketStateConnecting;
+                    break;
+
+                } else if (status == PAL_SUCCESS || status == PAL_ERR_SOCKET_ALREADY_CONNECTED) {
+
+                    tr_debug("M2MConnectionHandlerPimpl::socket_connect_handler - pal_connect(): success");
+                    _socket_state = ESocketStateConnected;
+
+                } else {
+                    tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - pal_connect(): failed: %d", (int)status);
+                    close_socket();
+                    _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
+                    return;
+                }
+#else
+                tr_error("socket_connect_handler() - TCP not configured"
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+            } else {
+                tr_info("M2MConnectionHandlerPimpl::socket_connect_handler - Using UDP");
+                _socket_state = ESocketStateConnected;
+            }
+
+        // fall through is a normal flow in case the UDP was used or pal_connect() happened to return immediately with PAL_SUCCESS
+        case ESocketStateConnected:
+            if (_security && security_instance_id >= 0) {
+                if (_secure_connection) {
+                    if ( _security_impl != NULL ) {
+                        _security_impl->reset();
+
+                        if (_security_impl->init(_security, security_instance_id) == 0) {
+                            // Initiate handshake. Perhaps there could be a separate event type for this?
+                            _socket_state = ESocketStateHandshaking;
+                            send_socket_event(ESocketCallback);
+                        } else {
+                            tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - init failed");
+                            close_socket();
+                            _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, true);
+                            return;
+                        }
+                    } else {
+                        tr_error("M2MConnectionHandlerPimpl::socket_connect_handler - sec is null");
+                        close_socket();
+                        _observer.socket_error(M2MConnectionHandler::SSL_CONNECTION_ERROR, true);
+                        return;
+                    }
+                }
+            }
+            if (_socket_state != ESocketStateHandshaking) {
+                _socket_state = ESocketStateUnsecureConnection;
+                _observer.address_ready(_address,
+                                        _server_type,
+                                        _address._port);
+            }
+            break;
+
+    }
+}
+
+bool M2MConnectionHandlerPimpl::send_data(uint8_t *data,
+                                          uint16_t data_len,
+                                          sn_nsdl_addr_s *address)
+{
+    if (address == NULL || data == NULL || !data_len || _socket_state < ESocketStateUnsecureConnection) {
+        tr_warn("M2MConnectionHandlerPimpl::send_data() - too early");
+        return false;
+    }
+
+    send_data_queue_s* out_data = (send_data_queue_s*)malloc(sizeof(send_data_queue_s));
+    if (!out_data) {
+        return false;
+    }
+
+    memset(out_data, 0, sizeof(send_data_queue_s));
+
+    uint8_t offset = 0;
+#ifdef PAL_NET_TCP_AND_TLS_SUPPORT
+    if (is_tcp_connection() && !_secure_connection ) {
+        offset = 4;
+    }
+#endif
+
+    out_data->data = (uint8_t*)malloc(data_len + offset);
+    if (!out_data->data) {
+        free(out_data);
+        return false;
+    }
+
+    // TCP non-secure
+    // We need to "shim" the length in front
+#ifdef PAL_NET_TCP_AND_TLS_SUPPORT
+    if (is_tcp_connection() && !_secure_connection ) {
+        out_data->data[0] = 0;
+        out_data->data[1] = 0;
+        out_data->data[2] = (data_len >> 8 ) & 0xff;
+        out_data->data[3] = data_len & 0xff;
+    }
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+
+    memcpy(out_data->data + offset, data, data_len);
+    out_data->data_len = data_len + offset;
+
+    claim_mutex();
+    ns_list_add_to_end(&_linked_list_send_data, out_data);
+    release_mutex();
+
+    if (!send_event(ESocketSend)) {
+        // Event push failed, free the buffer
+        claim_mutex();
+        ns_list_remove(&_linked_list_send_data, out_data);
+        release_mutex();
+        free(out_data->data);
+        free(out_data);
+        return false;
+    }
+
+    return true;
+}
+
+void M2MConnectionHandlerPimpl::send_socket_data()
+{
+    tr_debug("M2MConnectionHandlerPimpl::send_socket_data()");
+    int bytes_sent = 0;
+    bool success = true;
+
+    send_data_queue_s* out_data = get_item_from_list();
+    if (!out_data) {
+        return;
+    }
+
+    if (!out_data->data || !out_data->data_len || _socket_state < ESocketStateUnsecureConnection) {
+        tr_warn("M2MConnectionHandlerPimpl::send_socket_data() - too early");
+        add_item_to_list(out_data);
+        return;
+    }
+
+    // Loop until all the data is sent
+    for (; out_data->offset < out_data->data_len; out_data->offset += bytes_sent) {
+        // Secure send
+        if (_socket_state == ESocketStateSecureConnection) {
+            // TODO! Change the send_message API to take bytes_sent as a out param like the pal send API's.
+            while ((bytes_sent = _security_impl->send_message(out_data->data + out_data->offset,
+                                                            out_data->data_len - out_data->offset)) <= 0) {
+                if (bytes_sent == M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE) {
+                    // Return and wait the next event
+                    add_item_to_list(out_data);
+                    return;
+                }
+
+                if (bytes_sent != M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ) {
+                    tr_error("M2MConnectionHandlerPimpl::send_socket_data() - secure, failed %d", bytes_sent);
+                    success = false;
+                    break;
+                }
+            }
+            if (!success) {
+                break;
+            }
+        }
+        // Unsecure send
+        else {
+            bytes_sent = 0;
+            palStatus_t ret;
+            if (is_tcp_connection()) {
+#ifdef PAL_NET_TCP_AND_TLS_SUPPORT
+                ret = pal_send(_socket,
+                               out_data->data + out_data->offset,
+                               out_data->data_len - out_data->offset,
+                               (size_t*)&bytes_sent);
+#endif
+            } else {
+                ret = pal_sendTo(_socket,
+                                 out_data->data + out_data->offset,
+                                 out_data->data_len - out_data->offset,
+                                 (palSocketAddress_t*)&_socket_address,
+                                 sizeof(_socket_address),
+                                 (size_t*)&bytes_sent);
+            }
+            if (ret == PAL_ERR_SOCKET_WOULD_BLOCK) {
+                // Return and wait next event
+                add_item_to_list(out_data);
+                return;
+            }
+            if (ret < 0) {
+                tr_error("M2MConnectionHandlerPimpl::send_socket_data() - unsecure failed %d", (int)ret);
+                success = false;
+                break;
+            }
+        }
+    }
+
+    free(out_data->data);
+    free(out_data);
+
+    if (!success) {
+        if (bytes_sent == M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY) {
+            _observer.socket_error(M2MConnectionHandler::SSL_PEER_CLOSED, true);
+        } else {
+            tr_error("M2MConnectionHandlerPimpl::send_socket_data() - SOCKET_SEND_ERROR");
+            _observer.socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR, true);
+        }
+        close_socket();
+    } else {
+        _observer.data_sent();
+    }
+}
+
+bool M2MConnectionHandlerPimpl::start_listening_for_data()
+{
+    return true;
+}
+
+void M2MConnectionHandlerPimpl::stop_listening()
+{
+    // Do not call close_socket() directly here.
+    // This can be called from multiple locations.
+    send_socket_event(ESocketClose);
+}
+
+void M2MConnectionHandlerPimpl::handle_connection_error(int error)
+{
+    tr_error("M2MConnectionHandlerPimpl::handle_connection_error - error %d", error);
+    _observer.socket_error(error);
+}
+
+void M2MConnectionHandlerPimpl::set_platform_network_handler(void *handler)
+{
+    tr_debug("M2MConnectionHandlerPimpl::set_platform_network_handler");
+    if (PAL_SUCCESS != pal_registerNetworkInterface(handler, &_net_iface)) {
+        tr_error("M2MConnectionHandlerPimpl::set_platform_network_handler - Interface registration failed.");
+    }
+}
+
+void M2MConnectionHandlerPimpl::receive_handshake_handler()
+{
+    int return_value;
+    tr_debug("M2MConnectionHandlerPimpl::receive_handshake_handler()");
+
+    // assert(_socket_state == ESocketStateHandshaking);
+
+    return_value = _security_impl->connect(_base);
+
+    if (!return_value) {
+
+        _handshake_retry = 0;
+        _socket_state = ESocketStateSecureConnection;
+        _observer.address_ready(_address,
+                                _server_type,
+                                _server_port);
+
+    } else if (return_value == M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY) {
+        _handshake_retry = 0;
+        _observer.socket_error(M2MConnectionHandler::SSL_PEER_CLOSED, true);
+        close_socket();
+
+    } else if (return_value != M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ) {
+
+        tr_error("M2MConnectionHandlerPimpl::receive_handshake_handler() - SSL_HANDSHAKE_ERROR");
+        _handshake_retry = 0;
+        _observer.socket_error(M2MConnectionHandler::SSL_HANDSHAKE_ERROR, true);
+        close_socket();
+
+    } else {
+
+        if (_handshake_retry++ > MBED_CONF_MBED_CLIENT_TLS_MAX_RETRY) {
+
+            tr_error("M2MConnectionHandlerPimpl::receive_handshake_handler() - Max TLS retry fail");
+            _handshake_retry = 0;
+            _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT, true);
+            close_socket();
+
+        }
+        eventOS_event_timer_cancel(ESocketTimerCallback, M2MConnectionHandlerPimpl::_tasklet_id);
+
+        // There is required to set event.data_ptr for eventloop_event_handler.
+        arm_event_s event = {0};
+        event.receiver = M2MConnectionHandlerPimpl::_tasklet_id;
+        event.sender = 0;
+        event.event_id = ESocketTimerCallback;
+        event.event_type = ESocketTimerCallback;
+        event.data_ptr = this;
+        event.event_data = 0;
+        event.priority = ARM_LIB_HIGH_PRIORITY_EVENT;
+        eventOS_event_timer_request_in(&event, eventOS_event_timer_ms_to_ticks(1000));
+    }
+}
+
+bool M2MConnectionHandlerPimpl::is_handshake_ongoing() const
+{
+    return (_socket_state == ESocketStateHandshaking);
+}
+
+void M2MConnectionHandlerPimpl::receive_handler()
+{
+    // assert(_socket_state > ESocketStateHandshaking);
+
+    if (_socket_state == ESocketStateSecureConnection) {
+
+        int rcv_size;
+        unsigned char recv_buffer[BUFFER_LENGTH];
+
+        // we need to read as much as there is data available as the events may or may not be suppressed
+        do {
+            tr_debug("M2MConnectionHandlerPimpl::receive_handler()..");
+            rcv_size = _security_impl->read(recv_buffer, sizeof(recv_buffer));
+            tr_debug("M2MConnectionHandlerPimpl::receive_handler() res: %d", rcv_size);
+            if (rcv_size > 0) {
+                _observer.data_available((uint8_t*)recv_buffer,
+                                         rcv_size, _address);
+
+            } else if (M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY == rcv_size) {
+                _observer.socket_error(M2MConnectionHandler::SSL_PEER_CLOSED, true);
+                return;
+            } else if (M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ != rcv_size && rcv_size < 0) {
+                tr_error("M2MConnectionHandlerPimpl::receive_handler() - secure SOCKET_READ_ERROR");
+                _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
+                close_socket();
+                return;
+            }
+        } while (rcv_size > 0 && _socket_state == ESocketStateSecureConnection);
+
+    } else {
+        size_t recv;
+        palStatus_t status;
+        unsigned char recv_buffer[BUFFER_LENGTH];
+        do {
+            if (is_tcp_connection()) {
+#ifdef PAL_NET_TCP_AND_TLS_SUPPORT
+                status = pal_recv(_socket, recv_buffer, sizeof(recv_buffer), &recv);
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+            } else {
+                status = pal_receiveFrom(_socket, recv_buffer, sizeof(recv_buffer), NULL, NULL, &recv);
+            }
+
+            if (status == PAL_ERR_SOCKET_WOULD_BLOCK) {
+                return;
+            } else if (status != PAL_SUCCESS) {
+                tr_error("M2MConnectionHandlerPimpl::receive_handler() - SOCKET_READ_ERROR (%d)", (int)status);
+                _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
+                close_socket();
+                return;
+            }
+
+            tr_debug("M2MConnectionHandlerPimpl::receive_handler() - data received, len: %zu", recv);
+
+            if (!is_tcp_connection()) { // Observer for UDP plain mode
+                _observer.data_available((uint8_t*)recv_buffer, recv, _address);
+            } else {
+#ifdef PAL_NET_TCP_AND_TLS_SUPPORT
+                if ( recv < 4 ) {
+                    tr_error("M2MConnectionHandlerPimpl::receive_handler() - TCP SOCKET_READ_ERROR");
+                    _observer.socket_error(M2MConnectionHandler::SOCKET_READ_ERROR, true);
+                    close_socket();
+                    return;
+                }
+
+                //We need to "shim" out the length from the front
+                uint32_t len = (recv_buffer[0] << 24 & 0xFF000000) + (recv_buffer[1] << 16 & 0xFF0000);
+                len += (recv_buffer[2] << 8 & 0xFF00) + (recv_buffer[3] & 0xFF);
+                if (len > 0 && len <= recv - 4) {
+                    // Observer for TCP plain mode
+                    _observer.data_available(recv_buffer + 4, len, _address);
+                }
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+            }
+        } while (recv > 0 && _socket_state == ESocketStateUnsecureConnection);
+    }
+}
+
+void M2MConnectionHandlerPimpl::claim_mutex()
+{
+    eventOS_scheduler_mutex_wait();
+}
+
+void M2MConnectionHandlerPimpl::release_mutex()
+{
+    eventOS_scheduler_mutex_release();
+}
+
+
+bool M2MConnectionHandlerPimpl::init_socket()
+{
+    palSocketType_t socket_type = PAL_SOCK_DGRAM;
+    palStatus_t status;
+    palSocketAddress_t bind_address;
+    palIpV4Addr_t interface_address4;
+    palIpV6Addr_t interface_address6;
+
+    memset(&bind_address, 0, sizeof(palSocketAddress_t));
+    memset(&interface_address4, 0, sizeof(interface_address4));
+    memset(&interface_address6, 0, sizeof(interface_address6));
+
+    if (is_tcp_connection()) {
+#ifdef PAL_NET_TCP_AND_TLS_SUPPORT
+        socket_type = PAL_SOCK_STREAM;
+#else
+        // Somebody has built code without TCP support but tries to use it.
+        // Perhaps a "assert(false)" would be sufficient.
+        tr_error("M2MConnectionHandlerPimpl::init_socket() - TCP config error");
+        _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
+        return;
+#endif //PAL_NET_TCP_AND_TLS_SUPPORT
+    }
+    status = pal_asynchronousSocketWithArgument((palSocketDomain_t)_socket_address.addressType,
+                                                socket_type, true, _net_iface, &socket_event_handler,
+                                                this, &_socket);
+
+    if (PAL_SUCCESS != status) {
+        tr_error("M2MConnectionHandlerPimpl::init_socket() - socket create error : %d", (int)status);
+        _observer.socket_error(M2MConnectionHandler::SOCKET_ABORT);
+        return false;
+    }
+
+    if (_socket_address.addressType == PAL_AF_INET) {
+        status = pal_setSockAddrIPV4Addr(&bind_address, interface_address4);
+    } else if (_socket_address.addressType == PAL_AF_INET6) {
+        status = pal_setSockAddrIPV6Addr(&bind_address, interface_address6);
+    } else {
+        tr_warn("M2MConnectionHandlerPimpl::init_socket() - stack type: %d", (int)_socket_address.addressType);
+    }
+    if (PAL_SUCCESS != status) {
+        tr_error("M2MConnectionHandlerPimpl::init_socket - setSockAddrIPV err: %d", (int)status);
+        return false;
+    }
+    status = pal_setSockAddrPort(&bind_address, _listen_port);
+    if (PAL_SUCCESS != status) {
+        tr_error("M2MConnectionHandlerPimpl::init_socket - setSockAddrPort err: %d", (int)status);
+        return false;
+    }
+    pal_bind(_socket, &bind_address, sizeof(bind_address));
+
+    _security_impl->set_socket(_socket, (palSocketAddress_t*)&_socket_address);
+
+    return true;
+}
+
+bool M2MConnectionHandlerPimpl::is_tcp_connection() const
+{
+    return ( _binding_mode == M2MInterface::TCP ||
+             _binding_mode == M2MInterface::TCP_QUEUE );
+}
+
+void M2MConnectionHandlerPimpl::close_socket()
+{
+    _suppressable_event_in_flight = false;
+
+    if (_socket) {
+        // At least on mbed-os the pal_close() will perform callbacks even during it
+        // is called, which we will ignore when this state is set.
+        _socket_state = ESocketStateCloseBeingCalled;
+        pal_close(&_socket);
+        _socket = 0;
+    }
+
+    // make sure the socket connection statemachine is reset too.
+    _socket_state = ESocketStateDisconnected;
+
+    if (_security_impl) {
+        _security_impl->reset();
+    }
+
+    claim_mutex();
+    /*ns_list_foreach_safe(M2MConnectionHandlerPimpl::send_data_queue_s, tmp, &_linked_list_send_data) {
+        ns_list_remove(&_linked_list_send_data, tmp);
+        free(tmp->data);
+        free(tmp);
+    }*/
+    // Workaround for IAR compilation issue. ns_list_foreach does not compile with IAR.
+    // Error[Pe144]: a value of type "void *" cannot be used to initialize an entity of type "M2MConnectionHandlerPimpl::send_data_queue *"
+    while (!ns_list_is_empty(&_linked_list_send_data)) {
+        send_data_queue_s* data = (send_data_queue_s*)ns_list_get_first(&_linked_list_send_data);
+        ns_list_remove(&_linked_list_send_data, data);
+        free(data->data);
+        free(data);
+    }
+    release_mutex();
+}
+
+M2MConnectionHandlerPimpl::send_data_queue_s* M2MConnectionHandlerPimpl::get_item_from_list()
+{
+    claim_mutex();
+    send_data_queue_s* out_data = (send_data_queue_s*)ns_list_get_first(&_linked_list_send_data);
+    if (out_data) {
+        ns_list_remove(&_linked_list_send_data, out_data);
+    }
+    release_mutex();
+    return out_data;
+}
+
+void M2MConnectionHandlerPimpl::add_item_to_list(M2MConnectionHandlerPimpl::send_data_queue_s *data)
+{
+    claim_mutex();
+    ns_list_add_to_start(&_linked_list_send_data, data);
+    release_mutex();
+}
+
+void M2MConnectionHandlerPimpl::force_close()
+{
+    close_socket();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/source/m2mtimer.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "mbed-client/m2mtimer.h"
+#include "mbed-client/m2mtimerobserver.h"
+#include "mbed-client-classic/m2mtimerpimpl.h"
+
+
+M2MTimer::M2MTimer(M2MTimerObserver& observer)
+: _observer(observer)
+{
+    _private_impl = new M2MTimerPimpl(observer);
+}
+
+M2MTimer::~M2MTimer()
+{
+    delete _private_impl;
+    //_private_impl = NULL;
+}
+
+void M2MTimer::start_timer( uint64_t interval,
+                            M2MTimerObserver::Type type,
+                            bool single_shot)
+{
+    _private_impl->start_timer(interval,
+                               type,
+                               single_shot);
+}
+
+void M2MTimer::start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type){
+    _private_impl->start_dtls_timer(intermediate_interval, total_interval, type);
+}
+
+void M2MTimer::stop_timer()
+{
+    _private_impl->stop_timer();
+}
+
+bool M2MTimer::is_intermediate_interval_passed(){
+    return _private_impl->is_intermediate_interval_passed();
+}
+
+bool M2MTimer::is_total_interval_passed(){
+    return _private_impl->is_total_interval_passed();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-classic/source/m2mtimerpimpl.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2015-2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#include "mbed-client-classic/m2mtimerpimpl.h"
+#include "mbed-client/m2mtimerobserver.h"
+
+#include "eventOS_event_timer.h"
+#include "eventOS_scheduler.h"
+
+#include <assert.h>
+#include <string.h>
+
+
+#define MBED_CLIENT_TIMER_TASKLET_INIT_EVENT 0 // Tasklet init occurs always when generating a tasklet
+#define MBED_CLIENT_TIMER_EVENT 10
+
+// This is set to _status on constructor, which forces the lazy second phase initialization
+// to happen once in initialize_tasklet(). Whole scheme is there to avoid overhead or
+// unwanted serialization on event OS scheduler mutex, as the whole tasklet needs to be initialized
+// just once for the whole lifecycle of cloud client.
+#define STATUS_INIT_NOT_DONE_YET 3
+
+
+int8_t M2MTimerPimpl::_tasklet_id = -1;
+
+extern "C" void tasklet_func(arm_event_s *event)
+{
+    // skip the init event as there will be a timer event after
+    if (event->event_type == MBED_CLIENT_TIMER_EVENT) {
+
+        M2MTimerPimpl* timer = (M2MTimerPimpl*)event->data_ptr;
+        assert(timer);
+        timer->handle_timer_event(*event);
+    }
+}
+
+void M2MTimerPimpl::handle_timer_event(const arm_event_s &event)
+{
+    // Clear the reference to timer event which is now received and handled.
+    // This avoids the useless work from canceling a event if the timer is restarted
+    // and also lets the assertions verify the object state correctly.
+    _timer_event = NULL;
+
+    if (get_still_left_time() > 0) {
+        start_still_left_timer();
+    } else {
+        timer_expired();
+    }
+}
+
+M2MTimerPimpl::M2MTimerPimpl(M2MTimerObserver& observer)
+: _observer(observer),
+  _interval(0),
+  _intermediate_interval(0),
+  _total_interval(0),
+  _still_left(0),
+  _timer_event(NULL),
+  _type(M2MTimerObserver::Notdefined),
+  _status(STATUS_INIT_NOT_DONE_YET),
+  _dtls_type(false),
+  _single_shot(true)
+{
+}
+
+M2MTimerPimpl::~M2MTimerPimpl()
+{
+    // cancel the timer request, if any is pending
+    cancel();
+
+    // there is no turning back, event os does not have eventOS_event_handler_delete() or similar,
+    // so the tasklet is lost forever.
+}
+
+void M2MTimerPimpl::initialize_tasklet()
+{
+    // A micro-optimization to avoid operations on mutex on every time the timer is started.
+    // After all, the tasklet needs to be created just once for the lifecyle of whole Mbed cloud client.
+    if (_status == STATUS_INIT_NOT_DONE_YET) {
+
+        eventOS_scheduler_mutex_wait();
+
+        if (_tasklet_id < 0) {
+            _tasklet_id = eventOS_event_handler_create(tasklet_func, MBED_CLIENT_TIMER_TASKLET_INIT_EVENT);
+            assert(_tasklet_id >= 0);
+        }
+
+        _status = 0;
+
+        eventOS_scheduler_mutex_release();
+    }
+}
+
+void M2MTimerPimpl::start_timer(uint64_t interval,
+                                M2MTimerObserver::Type type,
+                                bool single_shot)
+{
+    initialize_tasklet();
+
+    _dtls_type = false;
+    _intermediate_interval = 0;
+    _total_interval = 0;
+    _status = 0;
+    _single_shot = single_shot;
+    _interval = interval;
+    _type = type;
+    _still_left = 0;
+    start();
+}
+
+void M2MTimerPimpl::start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type)
+{
+    initialize_tasklet();
+
+    _dtls_type = true;
+    _intermediate_interval = intermediate_interval;
+    _total_interval = total_interval;
+    _interval = _intermediate_interval;
+    _status = 0;
+    _single_shot = false;
+    _type = type;
+    start();
+}
+
+void M2MTimerPimpl::start()
+{
+    // Cancel ongoing events before creating a new one.
+    // Otherwise it can happen that there are multiple events running at the same time.
+    cancel();
+
+    int32_t wait_time;
+
+    if (_interval > INT32_MAX) {
+        _still_left = _interval - INT32_MAX;
+        wait_time = INT32_MAX;
+    } else {
+        wait_time = _interval;
+    }
+
+    request_event_in(wait_time);
+}
+
+void M2MTimerPimpl::request_event_in(int32_t delay_ms)
+{
+    // init struct to zero to avoid hassle when new fields are added to it
+    arm_event_t event = { 0 };
+
+    event.receiver = _tasklet_id;
+    event.sender = _tasklet_id;
+    event.event_type = MBED_CLIENT_TIMER_EVENT;
+    event.data_ptr = this;
+    event.priority = ARM_LIB_MED_PRIORITY_EVENT;
+
+    // check first, that there is no timer event still pending
+    assert(_timer_event == NULL);
+
+    const uint32_t delay_ticks = eventOS_event_timer_ms_to_ticks(delay_ms);
+
+    _timer_event = eventOS_event_timer_request_in(&event, delay_ticks);
+
+    // The timer request may fail only if the system is out of pre-allocated
+    // timers and it can not allocate more.
+    assert(_timer_event != NULL);
+}
+
+void M2MTimerPimpl::cancel()
+{
+    // NULL event is ok to cancel
+    eventOS_cancel(_timer_event);
+
+    _timer_event = NULL;
+}
+
+void M2MTimerPimpl::stop_timer()
+{
+    _interval = 0;
+    _single_shot = true;
+    _still_left = 0;
+    cancel();
+}
+
+void M2MTimerPimpl::timer_expired()
+{
+    _status++;
+
+    // The code is  expecting that the expiration has happened 0, 1 or more times,
+    // and we also need to check for overflow as the _status is stored in 2 bits slot.
+    if (_status > 2) {
+        _status = 2;
+    }
+
+    _observer.timer_expired(_type);
+
+    if ((!_dtls_type) && (!_single_shot)) {
+        // start next round of periodic timer
+        start();
+    } else if ((_dtls_type) && (!is_total_interval_passed())) {
+        // if only the intermediate time has passed, we need still wait up to total time
+        _interval = _total_interval - _intermediate_interval;
+        start();
+    }
+}
+
+bool M2MTimerPimpl::is_intermediate_interval_passed() const
+{
+    if (_status > 0) {
+        return true;
+    }
+    return false;
+}
+
+bool M2MTimerPimpl::is_total_interval_passed() const
+{
+    if (_status > 1) {
+        return true;
+    }
+    return false;
+}
+
+uint64_t M2MTimerPimpl::get_still_left_time() const
+{
+   return _still_left;
+}
+
+void M2MTimerPimpl::start_still_left_timer()
+{
+    if (_still_left > 0) {
+
+        int32_t wait_time;
+
+        if (_still_left > INT32_MAX) {
+            _still_left = _still_left - INT32_MAX;
+            wait_time = INT32_MAX;
+        } else {
+            wait_time = _still_left;
+            _still_left = 0;
+        }
+
+        request_event_in(wait_time);
+
+    } else {
+        _observer.timer_expired(_type);
+        if (!_single_shot) {
+            start_timer(_interval, _type, _single_shot);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-mbed-tls/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+test/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-mbed-tls/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+Unless specifically indicated otherwise in a file, files are licensed
+under the Apache 2.0 license, as can be found in: apache-2.0.txt
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-mbed-tls/apache-2.0.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,56 @@
+
+
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+    You must give any other recipients of the Work or Derivative Works a copy of this License; and
+    You must cause any modified files to carry prominent notices stating that You changed the files; and
+    You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+    If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+    You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-mbed-tls/mbed-client-mbedtls/m2mconnectionsecuritypimpl.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2015 - 2017 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifndef __M2M_CONNECTION_SECURITY_PIMPL_H__
+#define __M2M_CONNECTION_SECURITY_PIMPL_H__
+
+#include "mbed-client/m2mconnectionsecurity.h"
+#include "mbed-client/m2mtimerobserver.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2msecurity.h"
+#include "mbed-client/m2mconfig.h"
+
+#include "pal.h"
+
+#include <time.h>
+
+/**
+ * @brief The M2MConnectionSecurityPimpl class
+ */
+class M2MConnectionSecurityPimpl{
+
+private:
+
+    enum{
+        INIT_NOT_STARTED = 0,
+        INIT_CONFIGURING,
+        INIT_DONE
+    };
+
+    // Prevents the use of assignment operator by accident.
+    M2MConnectionSecurityPimpl& operator=( const M2MConnectionSecurityPimpl& /*other*/ );
+    // Prevents the use of copy constructor by accident
+    M2MConnectionSecurityPimpl( const M2MConnectionSecurityPimpl& /*other*/ );
+
+public:
+
+    /**
+     * @brief Constructor
+     */
+    M2MConnectionSecurityPimpl(M2MConnectionSecurity::SecurityMode mode);
+
+    /**
+    * @brief Destructor
+    */
+    virtual ~M2MConnectionSecurityPimpl();
+
+    /**
+     * \brief Resets the socket connection states.
+     */
+    void reset();
+
+    /**
+     * \brief Initiatlizes the socket connection states.
+     */
+    int init(const M2MSecurity *security, uint16_t security_instance_id);
+
+    /**
+     * \brief Connects the client to the server.
+     * \param connHandler The ConnectionHandler object that maintains the socket.
+     * \return Returns the state of the connection. Successful or not.
+     *         If 2MConnectionHandler::CONNECTION_ERROR_WANTS_READ is returned
+     *         this function must be called again later to continue the handshake.
+     */
+    int connect(M2MConnectionHandler* connHandler);
+
+    /**
+     * \brief Sends data to the server.
+     * \param message The data to be sent.
+     * \param len The length of the data.
+     * @return Indicates whether the data is sent successfully or not.
+     */
+    int send_message(unsigned char *message, int len);
+
+    /**
+     * \brief Reads the data received from the server.
+     * \param message The data to be read.
+     * \param len The length of the data.
+     * \return Indicates whether the data is read successfully or not.
+     */
+    int read(unsigned char* buffer, uint16_t len);
+
+    /**
+     * This function is no longer used.
+     */
+    void set_random_number_callback(random_number_cb callback);
+
+    /**
+     * \brief Sets the function callback that will be called by mbed-client for
+     * providing entropy source from application for ensuring strong entropy.
+     * \param entropy_callback A function pointer that will be called by mbed-client
+     * while performing secure handshake.
+     * Function signature , if using mbed-client-mbedtls should be
+     * int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output,
+     *                                     size_t len, size_t *olen);
+     *
+     * NOTE: This function is only used if MBED_CLOUD_CLIENT_CUSTOM_MBEDTLS_ENTROPY is defined
+     *       and mbed TLS is used.
+     */
+    void set_entropy_callback(entropy_cb callback);
+
+    /**
+     * \brief Set socket information for this secure connection.
+     * \param socket Socket used with this TLS session.
+     * \param address Pointer to the address of the server.
+     * \return Indicates whether the data is read successfully or not.
+     */
+    void set_socket(palSocket_t socket, palSocketAddress_t *address);
+
+private:
+
+    int start_handshake();
+
+    /**
+    *  \brief Returns certificate expiration time in epoch format.
+    *  \param certificate, The certificate to be extracted.
+    *  \param cert_len, Length of the certificate.
+    *  \return epoch time or 0 if failure.
+    */
+    uint32_t certificate_expiration_time(const unsigned char *certificate, const uint32_t cert_len);
+
+    /**
+    *  \brief Returns certificate validFrom time in epoch format.
+    *  \param certificate, The certificate to be extracted.
+    *  \param cert_len, Length of the certificate.
+    *  \return epoch time or 0 if failure.
+    */
+    uint32_t certificate_validfrom_time(const unsigned char *certificate, const uint32_t cert_len);
+
+    /**
+    *  \brief Returns certificate validFrom and validTo times in epoch format.
+    *  \param certificate, The certificate to be extracted.
+    *  \param valid_from ValidFrom time will be written to this parameter on success.
+    *  \param valid_to ValidTo time will be written to this parameter on success.
+    *  \return true on success or false on failure.
+    */
+    bool certificate_parse_valid_time(const char *certificate, uint32_t certificate_len, uint64_t *valid_from, uint64_t *valid_to);
+
+private:
+
+    uint8_t                             _init_done;
+    palTLSConfHandle_t                  _conf;
+    palTLSHandle_t                      _ssl;
+    M2MConnectionSecurity::SecurityMode _sec_mode;
+    palTLSSocket_t                      _tls_socket;
+    entropy_cb                          _entropy;
+
+    friend class Test_M2MConnectionSecurityPimpl;
+};
+
+#endif //__M2M_CONNECTION_SECURITY_PIMPL_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-mbed-tls/source/m2mconnectionsecurity.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#include <string.h>
+#include "mbed-client/m2mconnectionhandler.h"
+#include "mbed-client/m2mconnectionsecurity.h"
+#include "mbed-client-mbedtls/m2mconnectionsecuritypimpl.h"
+
+M2MConnectionSecurity::M2MConnectionSecurity(SecurityMode mode)
+{
+    _private_impl = new M2MConnectionSecurityPimpl(mode);
+}
+
+M2MConnectionSecurity::~M2MConnectionSecurity(){
+    delete _private_impl;
+}
+
+void M2MConnectionSecurity::reset(){
+    _private_impl->reset();
+}
+
+int M2MConnectionSecurity::init(const M2MSecurity *security, uint16_t security_instance_id){
+    return _private_impl->init(security, security_instance_id);
+}
+
+int M2MConnectionSecurity::connect(M2MConnectionHandler* connHandler){
+    return _private_impl->connect(connHandler);
+}
+
+int M2MConnectionSecurity::send_message(unsigned char *message, int len){
+    return _private_impl->send_message(message, len);
+}
+
+int M2MConnectionSecurity::read(unsigned char* buffer, uint16_t len){
+    return _private_impl->read(buffer, len);
+}
+
+void M2MConnectionSecurity::set_random_number_callback(random_number_cb callback)
+{
+    _private_impl->set_random_number_callback(callback);
+}
+
+void M2MConnectionSecurity::set_entropy_callback(entropy_cb callback)
+{
+    _private_impl->set_entropy_callback(callback);
+}
+
+void M2MConnectionSecurity::set_socket(void *socket, void *address)
+{
+    _private_impl->set_socket((palSocket_t) socket, (palSocketAddress_t*) address);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client-mbed-tls/source/m2mconnectionsecuritypimpl.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2015 - 2017 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+// Needed for PRIu64 on FreeRTOS
+#include <stdio.h>
+// Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+
+// Note: this macro is needed on armcc to get the the PRI*32 macros
+// from inttypes.h in a C++ code.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include "mbed-client/m2mconnectionhandler.h"
+#include "mbed-client-mbedtls/m2mconnectionsecuritypimpl.h"
+#include "mbed-client/m2msecurity.h"
+#include "mbed-trace/mbed_trace.h"
+#include "mbed-client/m2mconstants.h"
+#include "pal.h"
+#include "m2mdevice.h"
+#include "m2minterfacefactory.h"
+#include <string.h>
+
+#define TRACE_GROUP "mClt"
+
+M2MConnectionSecurityPimpl::M2MConnectionSecurityPimpl(M2MConnectionSecurity::SecurityMode mode)
+    :_init_done(M2MConnectionSecurityPimpl::INIT_NOT_STARTED),
+     _conf(0),
+     _ssl(0),
+     _sec_mode(mode)
+{
+    memset(&_entropy, 0, sizeof(entropy_cb));
+    memset(&_tls_socket, 0, sizeof(palTLSSocket_t));
+}
+
+M2MConnectionSecurityPimpl::~M2MConnectionSecurityPimpl()
+{
+    if(_ssl) {
+        pal_freeTLS(&_ssl);
+    }
+    if(_conf) {
+        pal_tlsConfigurationFree(&_conf);
+    }
+}
+
+void M2MConnectionSecurityPimpl::reset()
+{
+    if(_ssl) {
+        pal_freeTLS(&_ssl);
+    }
+    if(_conf) {
+        pal_tlsConfigurationFree(&_conf);
+    }
+    _init_done = M2MConnectionSecurityPimpl::INIT_NOT_STARTED;
+}
+
+int M2MConnectionSecurityPimpl::init(const M2MSecurity *security, uint16_t security_instance_id)
+{
+    tr_debug("M2MConnectionSecurityPimpl::init");
+
+    if(!security){
+        tr_error("M2MConnectionSecurityPimpl Security NULL.");
+        return -1;
+    }
+
+    if(_entropy.entropy_source_ptr) {
+        if(PAL_SUCCESS != pal_addEntropySource(_entropy.entropy_source_ptr)){
+            return -1;
+        }
+    }
+
+    palTLSTransportMode_t mode = PAL_DTLS_MODE;
+    if(_sec_mode == M2MConnectionSecurity::TLS){
+        mode = PAL_TLS_MODE;
+    }
+
+    if(PAL_SUCCESS != pal_initTLSConfiguration(&_conf, mode)){
+        tr_error("pal_initTLSConfiguration failed");
+        return -1;
+    }
+
+    _init_done = M2MConnectionSecurityPimpl::INIT_CONFIGURING;
+
+
+    if(_sec_mode == M2MConnectionSecurity::DTLS){
+        // PAL divides the defined MAX_TIMEOUT by 2
+        pal_setHandShakeTimeOut(_conf, MBED_CLIENT_DTLS_PEER_MAX_TIMEOUT*2);
+    }
+
+    M2MSecurity::SecurityModeType cert_mode =
+        (M2MSecurity::SecurityModeType)security->resource_value_int(M2MSecurity::SecurityMode, security_instance_id);
+
+    if( cert_mode == M2MSecurity::Certificate || cert_mode == M2MSecurity::EST ){
+
+        palX509_t owncert;
+        palPrivateKey_t privateKey;
+        palX509_t caChain;
+
+        uint8_t certificate[MAX_CERTIFICATE_SIZE];
+        uint8_t *certificate_ptr = (uint8_t *)&certificate;
+
+        caChain.size = MAX_CERTIFICATE_SIZE;
+        int ret_code = security->resource_value_buffer(M2MSecurity::ServerPublicKey, certificate_ptr, security_instance_id, (size_t*)&caChain.size);
+        caChain.buffer = certificate_ptr;
+
+        if (ret_code < 0 || PAL_SUCCESS != pal_setCAChain(_conf, &caChain, NULL)){
+            tr_error("pal_setCAChain failed");
+            return -1;
+        }
+
+        privateKey.size = MAX_CERTIFICATE_SIZE;
+        ret_code = security->resource_value_buffer(M2MSecurity::Secretkey, certificate_ptr, security_instance_id, (size_t*)&privateKey.size);
+        privateKey.buffer = certificate_ptr;
+        if (ret_code < 0 || PAL_SUCCESS != pal_setOwnPrivateKey(_conf, &privateKey)) {
+            tr_error("pal_setOwnPrivateKey failed");
+            return -1;
+        }
+
+        void *dummy;
+
+        // Open certificate chain, size parameter contains the depth of certificate chain
+        size_t cert_chain_size = 0;
+        security->resource_value_buffer(M2MSecurity::OpenCertificateChain, (uint8_t *&)dummy, security_instance_id, &cert_chain_size);
+        tr_info("M2MConnectionSecurityPimpl::init - cert chain length: %" PRIu32, cert_chain_size);
+
+        int index = 0;
+        while (index < cert_chain_size) {
+            owncert.size = MAX_CERTIFICATE_SIZE;
+            ret_code = security->resource_value_buffer(M2MSecurity::ReadDeviceCertificateChain, certificate_ptr, security_instance_id, (size_t*)&owncert.size);
+            owncert.buffer = certificate_ptr;
+
+            if (ret_code < 0 || PAL_SUCCESS != pal_setOwnCertChain(_conf, &owncert)){
+                tr_error("pal_setOwnCertChain failed");
+                security->resource_value_buffer(M2MSecurity::CloseCertificateChain, (uint8_t *&)dummy, security_instance_id, &cert_chain_size);
+                return -1;
+            }
+
+            index++;
+        }
+        security->resource_value_buffer(M2MSecurity::CloseCertificateChain, (uint8_t *&)dummy, security_instance_id, &cert_chain_size);
+
+    } else if (cert_mode == M2MSecurity::Psk){
+
+        uint8_t identity[MAX_CERTIFICATE_SIZE];
+        uint8_t *identity_ptr = (uint8_t *)&identity;
+        uint32_t identity_len;
+        uint8_t psk[MAX_CERTIFICATE_SIZE];
+        uint8_t *psk_ptr = (uint8_t *)&psk;
+        uint32_t psk_len;
+
+        security->resource_value_buffer(M2MSecurity::PublicKey, identity_ptr, security_instance_id, (size_t*)&identity_len);
+        security->resource_value_buffer(M2MSecurity::Secretkey, psk_ptr, security_instance_id, (size_t*)&psk_len);
+        palStatus_t ret = pal_setPSK(_conf, identity_ptr, identity_len, psk_ptr, psk_len);
+
+
+        if(PAL_SUCCESS != ret){
+            tr_error("pal_setPSK failed");
+            return -1;
+        }
+
+    }else{
+        tr_error("Security mode not set");
+        return -1;
+
+    }
+
+    if(PAL_SUCCESS != pal_initTLS(_conf, &_ssl)){
+        tr_error("pal_initTLS failed");
+        return -1;
+    }
+
+    if(PAL_SUCCESS != pal_tlsSetSocket(_conf, &_tls_socket)){
+        tr_error("pal_tlsSetSocket failed");
+        return -1;
+    }
+
+    _init_done = M2MConnectionSecurityPimpl::INIT_DONE;
+
+#ifdef MBED_CONF_MBED_TRACE_ENABLE
+    // Note: This call is not enough, one also needs the MBEDTLS_DEBUG_C to be defined globally
+    // on build and if using default mbedtls configuration file, the
+    // "#undef MBEDTLS_DEBUG_C" -line needs to be removed from mbedtls_mbed_client_config.h
+    pal_sslSetDebugging(_conf, 1);
+#endif
+
+    tr_debug("M2MConnectionSecurityPimpl::init - out");
+    return 0;
+}
+
+int M2MConnectionSecurityPimpl::start_handshake()
+{
+    tr_debug("M2MConnectionSecurityPimpl::start_handshake");
+
+    palStatus_t ret;
+
+    ret = pal_handShake(_ssl, _conf);
+
+    if(ret == PAL_ERR_TLS_WANT_READ || ret == PAL_ERR_TLS_WANT_WRITE || ret == PAL_ERR_TIMEOUT_EXPIRED){
+        return M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ;
+    }
+    else if(ret == PAL_ERR_TLS_PEER_CLOSE_NOTIFY) {
+        return M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY;
+    }
+
+    if(ret != PAL_SUCCESS){ //We loose the original error here!
+        tr_debug("M2MConnectionSecurityPimpl::start_handshake pal_handShake() error %" PRId32, ret);
+        return -1;
+    }
+
+    ret = pal_sslGetVerifyResult(_ssl);
+    if(PAL_SUCCESS != ret){
+        tr_debug("M2MConnectionSecurityPimpl::start_handshake pal_sslGetVerifyResult() error %" PRId32, ret);
+        return -1;
+    }
+
+    return ret;
+}
+
+int M2MConnectionSecurityPimpl::connect(M2MConnectionHandler* connHandler)
+{
+    tr_debug("M2MConnectionSecurityPimpl::connect");
+    int ret = -1;
+
+    if(M2MConnectionSecurityPimpl::INIT_DONE != _init_done){
+        return ret;
+    }
+
+    ret = start_handshake();
+    tr_debug("M2MConnectionSecurityPimpl::connect - handshake ret: %d", ret);
+    return ret;
+}
+
+
+int M2MConnectionSecurityPimpl::send_message(unsigned char *message, int len)
+{
+    tr_debug("M2MConnectionSecurityPimpl::send_message");
+    int ret = -1;
+    palStatus_t return_value;
+    uint32_t len_write;
+
+    if(M2MConnectionSecurityPimpl::INIT_DONE != _init_done){
+        return ret;
+    }
+
+
+    if(PAL_SUCCESS == (return_value = pal_sslWrite(_ssl, message, len, &len_write))){
+        ret = (int)len_write;
+    }
+    else if(return_value == PAL_ERR_TLS_WANT_READ || return_value == PAL_ERR_TIMEOUT_EXPIRED){
+        ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ;
+    }
+    else if(return_value == PAL_ERR_TLS_WANT_WRITE) {
+        ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_WRITE;
+    }
+    else if(return_value == PAL_ERR_TLS_PEER_CLOSE_NOTIFY) {
+        ret = M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY;
+    }
+
+    tr_debug("M2MConnectionSecurityPimpl::send_message - ret: %d", ret);
+    return ret; //bytes written
+}
+
+int M2MConnectionSecurityPimpl::read(unsigned char* buffer, uint16_t len)
+{
+    int ret = -1;
+    palStatus_t return_value;
+    uint32_t len_read;
+
+    if(M2MConnectionSecurityPimpl::INIT_DONE != _init_done){
+        tr_error("M2MConnectionSecurityPimpl::read - init not done!");
+        return ret;
+    }
+
+    if(PAL_SUCCESS == (return_value = pal_sslRead(_ssl, buffer, len, &len_read))){
+        ret = (int)len_read;
+    }
+
+    else if(return_value == PAL_ERR_TLS_WANT_READ || return_value == PAL_ERR_TLS_WANT_WRITE || return_value == PAL_ERR_TIMEOUT_EXPIRED){
+        ret = M2MConnectionHandler::CONNECTION_ERROR_WANTS_READ;
+    }
+
+    else if(return_value == PAL_ERR_TLS_PEER_CLOSE_NOTIFY) {
+        ret = M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY;
+    }
+
+    return ret;
+}
+
+void M2MConnectionSecurityPimpl::set_random_number_callback(random_number_cb callback)
+{
+    (void)callback;
+}
+
+void M2MConnectionSecurityPimpl::set_entropy_callback(entropy_cb callback)
+{
+
+    _entropy = callback;
+
+}
+
+void M2MConnectionSecurityPimpl::set_socket(palSocket_t socket, palSocketAddress_t *address)
+{
+    _tls_socket.socket = socket;
+    _tls_socket.socketAddress = address;
+    _tls_socket.addressLength = sizeof(palSocketAddress_t);
+
+    if(_sec_mode == M2MConnectionSecurity::TLS){
+        _tls_socket.transportationMode = PAL_TLS_MODE;
+    }
+    else{
+        _tls_socket.transportationMode = PAL_DTLS_MODE;
+    }
+}
+
+bool M2MConnectionSecurityPimpl::certificate_parse_valid_time(const char *certificate, uint32_t certificate_len, uint64_t *valid_from, uint64_t *valid_to)
+{
+    palX509Handle_t cert = 0;
+    size_t len;
+    palStatus_t ret;
+
+    tr_debug("certificate_validfrom_time");
+
+    ret = pal_x509Initiate(&cert);
+    if(PAL_SUCCESS != ret) {
+        tr_error("certificate_validfrom_time - cert init failed: %u", (int)ret);
+        pal_x509Free(&cert);
+        return false;
+    }
+    if(PAL_SUCCESS != (ret = pal_x509CertParse(cert, (const unsigned char*)certificate, certificate_len))) {
+        tr_error("certificate_validfrom_time - cert parse failed: %u", (int)ret);
+        pal_x509Free(&cert);
+        return false;
+    }
+    if(PAL_SUCCESS != (ret = pal_x509CertGetAttribute(cert, PAL_X509_VALID_FROM, valid_from, sizeof(uint64_t), &len))) {
+        tr_error("certificate_validfrom_time - cert attr get failed: %u", (int)ret);
+        pal_x509Free(&cert);
+        return false;
+    }
+    if(PAL_SUCCESS != (ret = pal_x509CertGetAttribute(cert, PAL_X509_VALID_TO, valid_to, sizeof(uint64_t), &len))) {
+        tr_error("certificate_validto_time - cert attr get failed: %u", (int)ret);
+        pal_x509Free(&cert);
+        return false;
+    }
+
+    pal_x509Free(&cert);
+    return true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/functionpointer.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef FUNCTIONPOINTER_H
+#define FUNCTIONPOINTER_H
+
+#include <string.h>
+#include <stdint.h>
+
+/*! \file functionpointer.h
+* \brief A class for storing and calling a pointer to a static or member void function.
+ */
+
+template <typename R>
+class FP0{
+public:
+    /** Create a function pointer, attaching a static function.
+     *
+     *  \param function The void static function to attach (default is none).
+     */
+    FP0(R (*function)(void) = 0) {
+        memset(_member,0,sizeof(_member));
+        attach(function);
+    }
+
+    /** Create a function pointer, attaching a member function.
+     *
+     *  \param object The object pointer to invoke the member function on (the "this" pointer).
+     *  \param function The address of the void member function to attach.
+     */
+    template<typename T>
+    FP0(T *object, R (T::*member)(void)) {
+        attach(object, member);
+    }
+
+    /** Attach a static function.
+     *
+     *  \param function The void static function to attach (default is none).
+     */
+    void attach(R (*function)(void)) {
+        _p.function = function;
+        _membercaller = 0;
+    }
+
+    /** Attach a member function.
+     *
+     *  \param object The object pointer to invoke the member function on (the "this" pointer).
+     *  \param function The address of the void member function to attach.
+     */
+    template<typename T>
+    void attach(T *object, R (T::*member)(void)) {
+        _p.object = static_cast<void*>(object);
+        *reinterpret_cast<R (T::**)(void)>(_member) = member;
+        _membercaller = &FP0::membercaller<T>;
+    }
+
+    /** Call the attached static or member function.
+     */
+    R call(){
+        if (_membercaller == 0 && _p.function) {
+            return _p.function();
+        } else if (_membercaller && _p.object) {
+            return _membercaller(_p.object, _member);
+        }
+        return (R)0;
+    }
+
+    typedef R (*static_fp)();
+    static_fp get_function() const {
+        return (R(*)())_p.function;
+    }
+
+    R operator ()(void) {
+        return call();
+    }
+    operator bool(void) {
+        void *q = &_p.function;
+        return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
+    }
+
+private:
+    template<typename T>
+    static void membercaller(void *object, uintptr_t *member) {
+        T* o = static_cast<T*>(object);
+        R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member);
+        (o->**m)();
+    }
+
+    union {
+        R (*function)(void);               // static function pointer - 0 if none attached
+        void *object;                         // object this pointer - 0 if none attached
+    } _p;
+    uintptr_t _member[2];                     // aligned raw member function pointer storage - converted back by registered _membercaller
+    R (*_membercaller)(void*, uintptr_t*); // registered membercaller function to convert back and call _m.member on _object
+};
+
+/* If we had variadic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */
+
+/** A class for storing and calling a pointer to a static or member void function
+ */
+template <typename R, typename A1>
+class FP1{
+public:
+    /** Create a function pointer, attaching a static function.
+     *
+     *  \param function The void static function to attach (default is none).
+     */
+    FP1(R (*function)(A1) = 0) {
+        memset(_member,0,sizeof(_member));
+        attach(function);
+    }
+
+    /** Create a function pointeer, attaching a member function.
+     *
+     *  \param object The object pointer to invoke the member function on (the "this" pointer).
+     *  \param function The address of the void member function to attach.
+     */
+    template<typename T>
+    FP1(T *object, R (T::*member)(A1)) {
+        attach(object, member);
+    }
+
+    /** Attach a static function.
+     *
+     *  \param function The void static function to attach (default is none).
+     */
+    void attach(R (*function)(A1)) {
+        _p.function = function;
+        _membercaller = 0;
+    }
+
+    /** Attach a member function.
+     *
+     *  \param object The object pointer to invoke the member function on (the "this" pointer).
+     *  \param function The address of the void member function to attach.
+     */
+    template<typename T>
+    void attach(T *object, R (T::*member)(A1)) {
+        _p.object = static_cast<void*>(object);
+        *reinterpret_cast<R (T::**)(A1)>(_member) = member;
+        _membercaller = &FP1::membercaller<T>;
+    }
+
+    /** Call the attached static or member function.
+     */
+    R call(A1 a){
+        if (_membercaller == 0 && _p.function) {
+           return _p.function(a);
+        } else if (_membercaller && _p.object) {
+           return _membercaller(_p.object, _member, a);
+        }
+        return (R)0;
+    }
+
+    typedef R (*static_fp)();
+    static_fp get_function() const {
+        return (R(*)())_p.function;
+    }
+
+    R operator ()(A1 a) {
+        return call(a);
+    }
+    operator bool(void)
+    {
+        void *q = &_p.function;
+        return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
+    }
+private:
+    template<typename T>
+    static void membercaller(void *object, uintptr_t *member, A1 a) {
+        T* o = static_cast<T*>(object);
+        R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
+        (o->**m)(a);
+    }
+
+    union {
+        R (*function)(A1);               // static function pointer - 0 if none attached
+        void *object;                         // object this pointer - 0 if none attached
+    } _p;
+    uintptr_t _member[2];                     // aligned raw member function pointer storage - converted back by registered _membercaller
+    R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object
+};
+
+/** A class for storing and calling a pointer to a static or member void function.
+ */
+template <typename R, typename A1, typename A2>
+class FP2{
+public:
+    /** Create a function pointer, attaching a static function.
+     *
+     *  \param function The void static function to attach (default is none).
+     */
+    FP2(R (*function)(A1, A2) = 0) {
+        memset(_member,0,sizeof(_member));
+        attach(function);
+    }
+
+    /** Create a function pointer, attaching a member function.
+     *
+     *  \param object The object pointer to invoke the member function on (the "this" pointer).
+     *  \param function The address of the void member function to attach.
+     */
+    template<typename T>
+    FP2(T *object, R (T::*member)(A1, A2)) {
+        attach(object, member);
+    }
+
+    /** Attach a static function.
+     *
+     *  \param function The void static function to attach (default is none).
+     */
+    void attach(R (*function)(A1, A2)) {
+        _p.function = function;
+        _membercaller = 0;
+    }
+
+    /** Attach a member function
+     *
+     *  \param object The object pointer to invoke the member function on (the "this" pointer).
+     *  \param function The address of the void member function to attach.
+     */
+    template<typename T>
+    void attach(T *object, R (T::*member)(A1, A2)) {
+        _p.object = static_cast<void*>(object);
+        *reinterpret_cast<R (T::**)(A1, A2)>(_member) = member;
+        _membercaller = &FP2::membercaller<T>;
+    }
+
+    /** Call the attached static or member function.
+     */
+    R call(A1 a1, A2 a2){
+        if (_membercaller == 0 && _p.function) {
+           return _p.function(a1, a2);
+        } else if (_membercaller && _p.object) {
+           return _membercaller(_p.object, _member, a1, a2);
+        }
+        return (R)0;
+    }
+
+    typedef R (*static_fp)();
+    static_fp get_function() const {
+        return (R(*)())_p.function;
+    }
+
+    R operator ()(A1 a1, A2 a2) {
+        return call(a1, a2);
+    }
+    operator bool(void)
+    {
+        void *q = &_p.function;
+        return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
+    }
+private:
+    template<typename T>
+    static void membercaller(void *object, uintptr_t *member, A1 a1, A2 a2) {
+        T* o = static_cast<T*>(object);
+        R (T::**m)(A1, A2) = reinterpret_cast<R (T::**)(A1, A2)>(member);
+        (o->**m)(a1, a2);
+    }
+
+    union {
+        R (*function)(A1, A2);               // static function pointer - 0 if none attached
+        void *object;                         // object this pointer - 0 if none attached
+    } _p;
+    uintptr_t _member[2];                     // aligned raw member function pointer storage - converted back by registered _membercaller
+    R (*_membercaller)(void*, uintptr_t*, A1, A2); // registered membercaller function to convert back and call _m.member on _object
+};
+
+/** A class for storing and calling a pointer to a static or member void function.
+ */
+template <typename R, typename A1, typename A2, typename A3>
+class FP3{
+public:
+    /** Create a function pointer, attaching a static function.
+     *
+     *  \param function The void static function to attach (default is none).
+     */
+    FP3(R (*function)(A1, A2, A3) = 0) {
+        memset(_member,0,sizeof(_member));
+        attach(function);
+    }
+
+    /** Create a function pointer, attaching a member function.
+     *
+     *  \param object The object pointer to invoke the member function on (the "this" pointer).
+     *  \param function The address of the void member function to attach.
+     */
+    template<typename T>
+    FP3(T *object, R (T::*member)(A1, A2, A3)) {
+        attach(object, member);
+    }
+
+    /** Attach a static function.
+     *
+     *  \param function The void static function to attach (default is none).
+     */
+    void attach(R (*function)(A1, A2, A3)) {
+        _p.function = function;
+        _membercaller = 0;
+    }
+
+    /** Attach a member function.
+     *
+     *  \param object The object pointer to invoke the member function on (the "this" pointer).
+     *  \param function The address of the void member function to attach.
+     */
+    template<typename T>
+    void attach(T *object, R (T::*member)(A1, A2, A3)) {
+        _p.object = static_cast<void*>(object);
+        *reinterpret_cast<R (T::**)(A1, A2, A3)>(_member) = member;
+        _membercaller = &FP3::membercaller<T>;
+    }
+
+    /** Call the attached static or member function.
+     */
+    R call(A1 a1, A2 a2, A3 a3){
+        if (_membercaller == 0 && _p.function) {
+           return _p.function(a1, a2, a3);
+        } else if (_membercaller && _p.object) {
+           return _membercaller(_p.object, _member, a1, a2, a3);
+        }
+        return (R)0;
+    }
+
+    typedef R (*static_fp)();
+    static_fp get_function() const {
+        return (R(*)())_p.function;
+    }
+
+    R operator ()(A1 a1, A2 a2, A3 a3) {
+        return call(a1, a2, a3);
+    }
+    operator bool(void)
+    {
+        void *q = &_p.function;
+        return (_membercaller != NULL) && _p.object != NULL && (*static_cast<void **>(q) != NULL);
+    }
+private:
+    template<typename T>
+    static void membercaller(void *object, uintptr_t *member, A1 a1, A2 a2, A3 a3) {
+        T* o = static_cast<T*>(object);
+        R (T::**m)(A1, A2, A3) = reinterpret_cast<R (T::**)(A1, A2, A3)>(member);
+        (o->**m)(a1, a2, a3);
+    }
+
+    union {
+        R (*function)(A1, A2, A3);               // static function pointer - 0 if none attached
+        void *object;                         // object this pointer - 0 if none attached
+    } _p;
+    uintptr_t _member[2];                     // aligned raw member function pointer storage - converted back by registered _membercaller
+    R (*_membercaller)(void*, uintptr_t*, A1, A2, A3); // registered membercaller function to convert back and call _m.member on _object
+};
+
+typedef FP0<void> FP;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mbase.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,676 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_BASE_H
+#define M2M_BASE_H
+
+// Support for std args
+#include <stdint.h>
+#include "mbed-client/m2mconfig.h"
+#include "mbed-client/m2mreportobserver.h"
+#include "mbed-client/functionpointer.h"
+#include "mbed-client/m2mstringbuffer.h"
+#include "nsdl-c/sn_nsdl.h"
+#include "sn_coap_header.h"
+#include "nsdl-c/sn_nsdl_lib.h"
+
+//FORWARD DECLARATION
+struct sn_coap_hdr_;
+typedef sn_coap_hdr_ sn_coap_hdr_s;
+struct nsdl_s;
+struct sn_nsdl_addr_;
+typedef sn_nsdl_addr_ sn_nsdl_addr_s;
+
+typedef FP1<void, const char*> value_updated_callback;
+typedef void(*value_updated_callback2) (const char* object_name);
+class M2MObservationHandler;
+class M2MReportHandler;
+
+class M2MObjectInstance;
+class M2MObject;
+class M2MResource;
+class M2MEndpoint;
+
+
+/*! \file m2mbase.h
+ *  \brief M2MBase.
+ *  This class is the base class based on which all LWM2M object models
+ *  can be created. This serves base class for Object, ObjectInstances and Resources.
+ */
+class M2MBase : public M2MReportObserver {
+
+public:
+
+    /**
+      * Enum to define the type of object.
+      */
+    typedef enum {
+        Object = 0x0,
+        Resource = 0x1,
+        ObjectInstance = 0x2,
+        ResourceInstance = 0x3
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+        ,ObjectDirectory = 0x4
+#endif
+    } BaseType;
+
+    /**
+      * Enum to define observation level.
+      */
+    typedef enum {
+        None                 = 0x0,
+        R_Attribute          = 0x01,
+        OI_Attribute         = 0x02,
+        OIR_Attribute        = 0x03,
+        O_Attribute          = 0x04,
+        OR_Attribute         = 0x05,
+        OOI_Attribute        = 0x06,
+        OOIR_Attribute       = 0x07
+    } Observation;
+
+
+    /**
+     * \brief Enum defining a resource type.
+    */
+    typedef enum {
+        Static,
+        Dynamic,
+        Directory
+    }Mode;
+
+    /**
+     * \brief Enum defining a resource data type.
+    */
+    typedef enum {
+        STRING,
+        INTEGER,
+        FLOAT,
+        BOOLEAN,
+        OPAQUE,
+        TIME,
+        OBJLINK
+    }DataType;
+
+    /**
+     * Enum defining an operation that can be
+     * supported by a given resource.
+    */
+    typedef enum {
+        NOT_ALLOWED                 = 0x00,
+        GET_ALLOWED                 = 0x01,
+        PUT_ALLOWED                 = 0x02,
+        GET_PUT_ALLOWED             = 0x03,
+        POST_ALLOWED                = 0x04,
+        GET_POST_ALLOWED            = 0x05,
+        PUT_POST_ALLOWED            = 0x06,
+        GET_PUT_POST_ALLOWED        = 0x07,
+        DELETE_ALLOWED              = 0x08,
+        GET_DELETE_ALLOWED          = 0x09,
+        PUT_DELETE_ALLOWED          = 0x0A,
+        GET_PUT_DELETE_ALLOWED      = 0x0B,
+        POST_DELETE_ALLOWED         = 0x0C,
+        GET_POST_DELETE_ALLOWED     = 0x0D,
+        PUT_POST_DELETE_ALLOWED     = 0x0E,
+        GET_PUT_POST_DELETE_ALLOWED = 0x0F
+    }Operation;
+
+    enum MaxPathSize {
+        MAX_NAME_SIZE = 64,
+        MAX_INSTANCE_SIZE = 5,
+
+        MAX_PATH_SIZE = ((MAX_NAME_SIZE * 2) + (MAX_INSTANCE_SIZE * 2) + 3 + 1),
+        MAX_PATH_SIZE_2 = ((MAX_NAME_SIZE * 2) + MAX_INSTANCE_SIZE + 2 + 1),
+        MAX_PATH_SIZE_3 = (MAX_NAME_SIZE + (MAX_INSTANCE_SIZE * 2) + 2 + 1),
+        MAX_PATH_SIZE_4 = (MAX_NAME_SIZE + MAX_INSTANCE_SIZE + 1 + 1)
+    };
+
+    typedef void(*notification_delivery_status_cb) (const M2MBase& base,
+                                                    const NotificationDeliveryStatus status,
+                                                    void *client_args);
+
+    typedef struct lwm2m_parameters {
+        //add multiple_instances
+        uint32_t            max_age; // todo: add flag
+        union {
+            char*               name; //for backwards compatibility
+            uint16_t            instance_id; // XXX: this is not properly aligned now, need to reorder these after the elimination is done
+        } identifier;
+        sn_nsdl_dynamic_resource_parameters_s *dynamic_resource_params;
+        BaseType            base_type : 3;
+        M2MBase::DataType   data_type : 3;
+        bool                multiple_instance;
+        bool                free_on_delete;   /**< true if struct is dynamically allocated and it
+                                                 and its members (name) are to be freed on destructor.
+                                                 Note: the sn_nsdl_dynamic_resource_parameters_s has
+                                                 its own similar, independent flag.
+                                                 Note: this also serves as a read-only flag. */
+       bool                 identifier_int_type;
+       bool                 read_write_callback_set; /** If set all the read and write operations are handled in callbacks
+                                                         and the resource value is not stored anymore in M2MResourceBase. */
+    } lwm2m_parameters_s;
+
+protected:
+
+    // Prevents the use of default constructor.
+    M2MBase();
+
+    // Prevents the use of assignment operator.
+    M2MBase& operator=( const M2MBase& /*other*/ );
+
+    // Prevents the use of copy constructor
+    M2MBase( const M2MBase& /*other*/ );
+
+    /**
+     * \brief Constructor
+     * \param name Name of the object created.
+     * \param mode Type of the resource.
+     * \param resource_type Textual information of resource.
+     * \param path Path of the object like 3/0/1
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     */
+    M2MBase(const String &name,
+            M2MBase::Mode mode,
+#ifndef DISABLE_RESOURCE_TYPE
+            const String &resource_type,
+#endif
+            char *path,
+            bool external_blockwise_store,
+            bool multiple_instance,
+            M2MBase::DataType type = M2MBase::OBJLINK);
+
+    M2MBase(const lwm2m_parameters_s* s);
+
+public:
+
+    /**
+     * Destructor
+     */
+    virtual ~M2MBase();
+
+    /**
+     * \brief Sets the operation type for an object.
+     * \param operation The operation to be set.
+     */
+    void set_operation(M2MBase::Operation operation);
+
+#if !defined(MEMORY_OPTIMIZED_API) || defined(RESOURCE_ATTRIBUTES_LIST)
+    /**
+     * \brief Sets the interface description of the object.
+     * \param description The description to be set.
+     */
+#if !defined(DISABLE_INTERFACE_DESCRIPTION) || defined(RESOURCE_ATTRIBUTES_LIST)
+    void set_interface_description(const String &description);
+
+    /**
+     * \brief Sets the interface description of the object.
+     * \param description The description to be set.
+     */
+    void set_interface_description(const char *description);
+
+    /**
+     * \brief Returns the interface description of the object.
+     * \return The interface description of the object.
+     */
+    const char* interface_description() const;
+#endif
+#if !defined(DISABLE_RESOURCE_TYPE) || defined(RESOURCE_ATTRIBUTES_LIST)
+    /**
+     * \brief Sets the resource type of the object.
+     * \param resource_type The resource type to be set.
+     */
+    virtual void set_resource_type(const String &resource_type);
+
+    /**
+     * \brief Sets the resource type of the object.
+     * \param resource_type The resource type to be set.
+     */
+    virtual void set_resource_type(const char *resource_type);
+
+    /**
+     * \brief Returns the resource type of the object.
+     * \return The resource type of the object.
+     */
+    const char* resource_type() const;
+#endif
+#endif
+
+    /**
+     * \brief Sets the CoAP content type of the object.
+     * \param content_type The content type to be set based on
+     * CoAP specifications.
+     */
+    void set_coap_content_type(const uint16_t content_type);
+
+    /**
+     * \brief Sets the observable mode for the object.
+     * \param observable A value for the observation.
+     */
+    void set_observable(bool observable);
+
+    /**
+     * \brief Sets the object to be auto-observable.
+     *
+     * \note This is not a standard CoAP or LWM2M feature and it only works in mbed Cloud.
+     * \note This must be called before registration process, since this info must be in a registration message.
+     * \note Auto-observable will take higher precedence if both observable methods are set.
+     *
+     * \param auto_observable Is auto-obs feature enabled or not.
+     */
+    void set_auto_observable(bool auto_observable);
+
+    /**
+     * \brief Adds the observation level for the object.
+     * \param observation_level The level of observation.
+     */
+    virtual void add_observation_level(M2MBase::Observation observation_level);
+
+    /**
+     * \brief Removes the observation level for the object.
+     * \param observation_level The level of observation.
+     */
+    virtual void remove_observation_level(M2MBase::Observation observation_level);
+
+    /**
+     * \brief Sets the object under observation.
+     * \param observed The value for observation. When true, starts observing. When false, the ongoing observation is cancelled.
+     * \param handler A handler object for sending
+     * observation callbacks.
+     */
+    void set_under_observation(bool observed,
+                               M2MObservationHandler *handler);
+    /**
+     * \brief Returns the Observation Handler object.
+     * \return M2MObservationHandler object.
+    */
+    virtual M2MObservationHandler* observation_handler() const = 0;
+
+    /**
+     * \brief Sets the observation handler
+     * \param handler Observation handler
+    */
+    virtual void set_observation_handler(M2MObservationHandler *handler) = 0;
+
+    /**
+     * \brief Sets the instance ID of the object.
+     * \param instance_id The instance ID of the object.
+     */
+    void set_instance_id(const uint16_t instance_id);
+
+    /**
+     * \brief Sets the max age for the resource value to be cached.
+     * \param max_age The max age in seconds.
+     */
+    void set_max_age(const uint32_t max_age);
+
+    /**
+     * \brief Returns the object type.
+     * \return The base type of the object.
+     */
+    M2MBase::BaseType base_type() const;
+
+    /**
+     * \brief Returns the operation type of the object.
+     * \return The supported operation on the object.
+     */
+    M2MBase::Operation operation() const;
+
+    /**
+     * \brief Returns the object name.
+     * \return The name of the object.
+     */
+    const char* name() const;
+
+    /**
+     * \brief Returns the object name in integer.
+     * \return The name of the object in integer.
+     */
+    int32_t name_id() const;
+
+    /**
+     * \brief Returns the object's instance ID.
+     * \returns The instance ID of the object.
+     */
+    uint16_t instance_id() const;
+
+    /**
+     * \brief Returns the path of the object.
+     * \return The path of the object (eg. 3/0/1).
+     */
+    const char* uri_path() const;
+
+    /**
+     * \brief Returns the CoAP content type of the object.
+     * \return The CoAP content type of the object.
+     */
+    uint16_t coap_content_type() const;
+
+    /**
+     * \brief Returns the observation status of the object.
+     * \return True if observable, else false.
+     */
+    bool is_observable() const;
+
+    /**
+     * \brief Returns the observation level of the object.
+     * \return The observation level of the object.
+     */
+    M2MBase::Observation observation_level() const;
+
+    /**
+     * \brief Returns the mode of the resource.
+     * \return The mode of the resource.
+     */
+     Mode mode() const;
+
+    /**
+     * \brief Returns the observation number.
+     * \return The observation number of the object.
+     */
+    uint16_t observation_number() const;
+
+    /**
+     * \brief Returns the max age for the resource value to be cached.
+     * \return The maax age in seconds.
+     */
+    uint32_t max_age() const;
+
+    /**
+     * \brief Parses the received query for the notification
+     * attribute.
+     * \param query The query that needs to be parsed.
+     * \return True if required attributes are present, else false.
+     */
+    virtual bool handle_observation_attribute(const char *query);
+
+    /**
+     * \brief Handles GET request for the registered objects.
+     * \param nsdl An NSDL handler for the CoAP library.
+     * \param received_coap_header The received CoAP message from the server.
+     * \param observation_handler A handler object for sending
+     * observation callbacks.
+     * \return sn_coap_hdr_s The message that needs to be sent to server.
+     */
+    virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler = NULL);
+    /**
+     * \brief Handles PUT request for the registered objects.
+     * \param nsdl An NSDL handler for the CoAP library.
+     * \param received_coap_header The received CoAP message from the server.
+     * \param observation_handler A handler object for sending
+     * observation callbacks.
+     * \param execute_value_updated True executes the "value_updated" callback.
+     * \return sn_coap_hdr_s The message that needs to be sent to server.
+     */
+    virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler,
+                                              bool &execute_value_updated);
+
+    /**
+     * \brief Handles GET request for the registered objects.
+     * \param nsdl An NSDL handler for the CoAP library.
+     * \param received_coap_header The received CoAP message from the server.
+     * \param observation_handler A handler object for sending
+     * observation callbacks.
+     * \param execute_value_updated True executes the "value_updated" callback.
+     * \return sn_coap_hdr_s  The message that needs to be sent to server.
+     */
+    virtual sn_coap_hdr_s* handle_post_request(nsdl_s *nsdl,
+                                               sn_coap_hdr_s *received_coap_header,
+                                               M2MObservationHandler *observation_handler,
+                                               bool &execute_value_updated,
+                                               sn_nsdl_addr_s *address = NULL);
+
+    /**
+     * \brief Executes the function that is set in "set_notification_delivery_status_cb".
+     */
+    void send_notification_delivery_status(const M2MBase& object, const NotificationDeliveryStatus status);
+
+    /**
+     * \brief Sets whether this resource is published to server or not.
+     * \param register_uri True sets the resource as part of registration message.
+     */
+    void set_register_uri(bool register_uri);
+
+    /**
+     * \brief Returns whether this resource is published to server or not.
+     * \return True if the resource is a part of the registration message, else false.
+     */
+    bool register_uri();
+
+    /**
+     * @brief Returns whether this resource is under observation or not.
+     * @return True if the resource is under observation, else false,
+     */
+    bool is_under_observation() const;
+
+    /**
+     * @brief Sets the function that is executed when this
+     * object receives a PUT or POST command.
+     * @param callback The function pointer that is called.
+     * @return True, if callback could be set, false otherwise.
+     */
+    bool set_value_updated_function(value_updated_callback callback);
+
+    /**
+     * @brief Sets the function that is executed when this
+     * object receives a PUT or POST command.
+     * @param callback The function pointer that is called.
+     * @return True, if callback could be set, false otherwise.
+     */
+    bool set_value_updated_function(value_updated_callback2 callback);
+
+    /**
+     * @brief Returns whether a callback function is set or not.
+     * @return True if the callback function is set, else false.
+     */
+    bool is_value_updated_function_set() const;
+
+    /**
+     * @brief Calls the function that is set in the "set_value_updated_function".
+     * @param name The name of the object.
+     */
+    void execute_value_updated(const String& name);
+
+    /**
+     * @brief Returns length of the object name.
+     * @return Length of the object name.
+     */
+    size_t resource_name_length() const;
+
+    /**
+     * @brief Returns the resource information.
+     * @return Resource information.
+     */
+    sn_nsdl_dynamic_resource_parameters_s* get_nsdl_resource() const;
+
+    /**
+     * @brief Returns the resource structure.
+     * @return Resource structure.
+     */
+    M2MBase::lwm2m_parameters_s* get_lwm2m_parameters() const;
+
+    /**
+     * @brief Returns the notification message id.
+     * @return Message id.
+     */
+    uint16_t get_notification_msgid() const;
+
+    /**
+     * @brief Sets the notification message id.
+     * This is used to map RESET and EMPTY ACK messages.
+     * @param msgid The message id.
+     */
+    void set_notification_msgid(uint16_t msgid);
+
+    /**
+     * @brief Sets the function that is executed when notification message state changes.
+     * @param callback The function pointer that is called.
+     * @param client_args The argument which is passed to the callback function.
+     */
+    bool set_notification_delivery_status_cb(notification_delivery_status_cb callback, void *client_args);
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+    static char* create_path(const M2MEndpoint &parent, const char *name);
+#endif
+    static char* create_path(const M2MObject &parent, const char *name);
+    static char* create_path(const M2MObject &parent, uint16_t object_instance);
+    static char* create_path(const M2MResource &parent, uint16_t resource_instance);
+    static char* create_path(const M2MResource &parent, const char *name);
+    static char* create_path(const M2MObjectInstance &parent, const char *name);
+
+protected : // from M2MReportObserver
+
+    virtual bool observation_to_be_sent(const m2m::Vector<uint16_t> &changed_instance_ids,
+                                        uint16_t obs_number,
+                                        bool send_object = false);
+
+protected:
+
+    /**
+     * \brief Sets the base type for an object.
+     * \param type The base type of the object.
+     */
+    void set_base_type(M2MBase::BaseType type);
+
+    /**
+     * \brief Memory allocation required for libCoap.
+     * \param size The size of memory to be reserved.
+    */
+    static void* memory_alloc(uint32_t size);
+
+    /**
+     * \brief Memory free functions required for libCoap.
+     * \param ptr The object whose memory needs to be freed.
+    */
+    static void memory_free(void *ptr);
+
+    /**
+     * \brief Allocate and make a copy of given zero terminated string. This
+     * is functionally equivalent with strdup().
+     * \param source The source string to copy, may not be NULL.
+    */
+    static char* alloc_string_copy(const char* source);
+
+    /**
+     * \brief Allocate (size + 1) amount of memory, copy size bytes into
+     * it and add zero termination.
+     * \param source The source string to copy, may not be NULL.
+     * \param size The size of memory to be reserved.
+    */
+    static uint8_t* alloc_string_copy(const uint8_t* source, uint32_t size);
+
+    /**
+     * \brief Allocate (size) amount of memory, copy size bytes into it.
+     * \param source The source buffer to copy, may not be NULL.
+     * \param size The size of memory to be reserved.
+    */
+    static uint8_t* alloc_copy(const uint8_t* source, uint32_t size);
+
+    // validate string length to be [min_length..max_length]
+    static bool validate_string_length(const String &string, size_t min_length, size_t max_length);
+    static bool validate_string_length(const char* string, size_t min_length, size_t max_length);
+
+    /**
+     * \brief Create Report Handler object.
+     * \return M2MReportHandler object.
+    */
+    M2MReportHandler* create_report_handler();
+
+    /**
+     * \brief Returns the Report Handler object.
+     * \return M2MReportHandler object.
+    */
+    M2MReportHandler* report_handler() const;
+
+    static bool build_path(StringBuffer<MAX_PATH_SIZE> &buffer, const char *s1, uint16_t i1, const char *s2, uint16_t i2);
+
+    static bool build_path(StringBuffer<MAX_PATH_SIZE_2> &buffer, const char *s1, uint16_t i1, const char *s2);
+
+    static bool build_path(StringBuffer<MAX_PATH_SIZE_3> &buffer, const char *s1, uint16_t i1, uint16_t i2);
+
+    static bool build_path(StringBuffer<MAX_PATH_SIZE_4> &buffer, const char *s1, uint16_t i1);
+
+    static char* stringdup(const char* s);
+
+    /**
+     * \brief Delete the resource structures owned by this object. Note: this needs
+     * to be called separately from each subclass' destructor as this method uses a
+     * virtual method and the call needs to be done at same class which has the
+     * implementation of the pure virtual method.
+     */
+    void free_resources();
+
+    /**
+     * \brief Returns notification send status.
+     * \return Notification status.
+     */
+    NotificationDeliveryStatus get_notification_delivery_status() const;
+
+    /**
+     * \brief Clears the notification send status to initial state.
+     */
+    void clear_notification_delivery_status();
+
+    /**
+     * \brief Provides the observation token of the object.
+     * \param value[OUT] A pointer to the value of the token.
+     * \param value_length[OUT] The length of the token pointer.
+     */
+    void get_observation_token(uint8_t *token, uint8_t &token_length) const;
+
+    /**
+     * \brief Sets the observation token value.
+     * \param token A pointer to the token of the resource.
+     * \param length The length of the token pointer.
+     */
+    void set_observation_token(const uint8_t *token,
+                               const uint8_t length);
+
+    /*
+     * \brief The data has changed and it needs to be updated into Mbed Cloud.
+     *        Current implementation maintains the changed state only in M2MEndpoint. If any of the changes in an
+     *        object changes the M2M registration structure, the information is propagated to M2MEndpoint using
+     *        this interface.
+     */
+    virtual void set_changed();
+
+    /*
+     * \brief Returns the owner object. Can return NULL if the object has no parent.
+     */
+    virtual M2MBase *get_parent() const;
+
+  private:
+    static bool is_integer(const String &value);
+
+    static bool is_integer(const char *value);
+
+    static char* create_path_base(const M2MBase &parent, const char *name);
+
+private:
+    lwm2m_parameters_s          *_sn_resource;
+    M2MReportHandler            *_report_handler; // TODO: can be broken down to smaller classes with inheritance.
+
+friend class Test_M2MBase;
+friend class Test_M2MObject;
+friend class M2MNsdlInterface;
+friend class M2MInterfaceFactory;
+friend class M2MObject;
+};
+
+#endif // M2M_BASE_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mblockmessage.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2MBLOCKMESSAGE_H
+#define M2MBLOCKMESSAGE_H
+
+#include "ns_types.h"
+#include "sn_coap_header.h"
+
+/*! \file m2mblockmessage.h
+ *  \brief M2MBlockMessage.
+ *  This class contains the data of an incoming block message.
+ */
+class M2MBlockMessage {
+
+public:
+
+    /**
+     * \brief An enum defining different kinds of errors
+     * that can occur during the block-wise operation.
+     */
+    typedef enum {
+        ErrorNone = 0,
+        EntityTooLarge
+    }Error;
+
+    /**
+    * Constructor.
+    */
+    M2MBlockMessage();
+
+    /**
+    * Destructor.
+    */
+    virtual ~M2MBlockMessage();
+
+    /**
+     * \brief Store the data from a CoAP message.
+     * \param coap_header The message to parse.
+     */
+    void set_message_info(sn_coap_hdr_s *coap_header);
+
+    /**
+     * \brief Clear values.
+     */
+    void clear_values();
+
+    /**
+     * \brief Check if the message is a block message.
+     * \param coap_header The message to check.
+     * \return True if block message, else false.
+     */
+    bool is_block_message() const;
+
+    /**
+     * \brief Returns the number of an incoming block.
+     * \return Block number, starting from 0.
+     */
+    uint16_t block_number() const;
+
+    /**
+     * \brief Returns the total size of the message.
+     * \return The total size in bytes.
+     */
+    uint32_t total_message_size() const;
+
+    /**
+     * \brief Check if last block.
+     * \return True if last block, else false.
+     */
+    bool is_last_block() const;
+
+    /**
+     * \brief Returns the payload of the message.
+     * \return The message payload.
+     */
+    uint8_t* block_data() const;
+
+    /**
+     * \brief Returns the length of the payload.
+     * \return The payload length.
+     */
+    uint32_t block_data_len() const;
+
+    /**
+     * \brief Returns an error code.
+     * \return Error code.
+     */
+    Error error_code() const;
+
+private:
+    uint8_t     *_block_data_ptr;
+    uint32_t    _total_message_size;
+    uint16_t    _block_data_len;
+    uint16_t    _block_number;
+    Error       _error_code;
+    bool        _is_last_block;
+    bool        _is_block_message;
+};
+
+#endif // M2MBLOCKMESSAGE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mconfig.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2MCONFIG_H
+#define M2MCONFIG_H
+
+/*! \file m2mconfig.h
+* \brief File defining all system build time configuration used by mbed-client.
+*/
+
+#include "mbed-client/m2mstring.h"
+
+#include <stddef.h>
+
+using namespace m2m;
+
+/**
+ * \def MBED_CLIENT_RECONNECTION_COUNT
+ *
+ * \brief Sets Reconnection count for mbed Client
+ * to attempt a reconnection re-tries until
+ * reaches the defined value either by the application
+ * or the default value set in Client.
+ * By default, the value is 3.
+ */
+#undef MBED_CLIENT_RECONNECTION_COUNT  /* 3 */
+
+/**
+ * \def MBED_CLIENT_RECONNECTION_INTERVAL
+ *
+ * \brief Sets Reconnection interval (in seconds) for
+ * mbed Client to attempt a reconnection re-tries.
+ * By default, the value is 5 seconds.
+ */
+#undef MBED_CLIENT_RECONNECTION_INTERVAL  /* 5 */
+
+/**
+ * \def MBED_CLIENT_TCP_KEEPALIVE_INTERVAL
+ *
+ * \brief The number of seconds between CoAP ping messages.
+ * By default, the value is 90 seconds.
+ */
+#undef MBED_CLIENT_TCP_KEEPALIVE_INTERVAL   /* 90 */
+
+/**
+ * \def MBED_CLIENT_EVENT_LOOP_SIZE
+ *
+ * \brief Defines the size of memory allocated for
+ * event loop (in bytes) for timer and network event
+ * handling of mbed Client.
+ * By default, this value is 1024 bytes.This memory is
+ * allocated from heap
+ */
+#undef MBED_CLIENT_EVENT_LOOP_SIZE      /* 1024 */
+
+#ifdef YOTTA_CFG_RECONNECTION_COUNT
+#define MBED_CLIENT_RECONNECTION_COUNT YOTTA_CFG_RECONNECTION_COUNT
+#elif defined MBED_CONF_MBED_CLIENT_RECONNECTION_COUNT
+#define MBED_CLIENT_RECONNECTION_COUNT MBED_CONF_MBED_CLIENT_RECONNECTION_COUNT
+#endif
+
+#ifdef YOTTA_CFG_RECONNECTION_INTERVAL
+#define MBED_CLIENT_RECONNECTION_INTERVAL YOTTA_CFG_RECONNECTION_INTERVAL
+#elif defined MBED_CONF_MBED_CLIENT_RECONNECTION_INTERVAL
+#define MBED_CLIENT_RECONNECTION_INTERVAL MBED_CONF_MBED_CLIENT_RECONNECTION_INTERVAL
+#endif
+
+#ifdef YOTTA_CFG_TCP_KEEPALIVE_INTERVAL
+#define MBED_CLIENT_TCP_KEEPALIVE_INTERVAL YOTTA_CFG_TCP_KEEPALIVE_INTERVAL
+#elif defined MBED_CONF_MBED_CLIENT_TCP_KEEPALIVE_INTERVAL
+#define MBED_CLIENT_TCP_KEEPALIVE_INTERVAL MBED_CONF_MBED_CLIENT_TCP_KEEPALIVE_INTERVAL
+#endif
+
+#ifdef YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE
+#define MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE YOTTA_CFG_DISABLE_BOOTSTRAP_FEATURE
+#elif defined MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+#define MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE MBED_CONF_MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+#endif
+
+#ifdef YOTTA_CFG_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE
+#define SN_COAP_MAX_INCOMING_MESSAGE_SIZE YOTTA_CFG_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE
+#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_MAX_INCOMING_MESSAGE_SIZE
+#define SN_COAP_MAX_INCOMING_MESSAGE_SIZE MBED_CONF_MBED_CLIENT_SN_COAP_MAX_INCOMING_MESSAGE_SIZE
+#endif
+
+#ifdef MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
+#define MBED_CLIENT_EVENT_LOOP_SIZE MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
+#endif
+
+#ifdef YOTTA_CFG_DISABLE_INTERFACE_DESCRIPTION
+#define DISABLE_INTERFACE_DESCRIPTION YOTTA_CFG_DISABLE_INTERFACE_DESCRIPTION
+#elif defined MBED_CONF_MBED_CLIENT_DISABLE_INTERFACE_DESCRIPTION
+#define DISABLE_INTERFACE_DESCRIPTION MBED_CONF_MBED_CLIENT_DISABLE_INTERFACE_DESCRIPTION
+#endif
+
+#ifdef YOTTA_CFG_DISABLE_RESOURCE_TYPE
+#define DISABLE_RESOURCE_TYPE YOTTA_CFG_DISABLE_RESOURCE_TYPE
+#elif defined MBED_CONF_MBED_CLIENT_DISABLE_RESOURCE_TYPE
+#define DISABLE_RESOURCE_TYPE MBED_CONF_MBED_CLIENT_DISABLE_RESOURCE_TYPE
+#endif
+
+#ifdef YOTTA_CFG_DISABLE_DELAYED_RESPONSE
+#define DISABLE_DELAYED_RESPONSE YOTTA_CFG_DISABLE_DELAYED_RESPONSE
+#elif defined MBED_CONF_MBED_CLIENT_DISABLE_DELAYED_RESPONSE
+#define DISABLE_DELAYED_RESPONSE MBED_CONF_MBED_CLIENT_DISABLE_DELAYED_RESPONSE
+#endif
+
+#ifdef YOTTA_CFG_DISABLE_BLOCK_MESSAGE
+#define DISABLE_BLOCK_MESSAGE YOTTA_CFG_DISABLE_BLOCK_MESSAGE
+#elif defined MBED_CONF_MBED_CLIENT_DISABLE_BLOCK_MESSAGE
+#define DISABLE_BLOCK_MESSAGE MBED_CONF_MBED_CLIENT_DISABLE_BLOCK_MESSAGE
+#endif
+
+#ifdef MBED_CONF_MBED_CLIENT_DTLS_PEER_MAX_TIMEOUT
+#define MBED_CLIENT_DTLS_PEER_MAX_TIMEOUT MBED_CONF_MBED_CLIENT_DTLS_PEER_MAX_TIMEOUT
+#endif
+
+
+#if defined (__ICCARM__)
+#define m2m_deprecated
+#else
+#define m2m_deprecated __attribute__ ((deprecated))
+#endif
+
+// This is valid for mbed-client-mbedtls
+// For other SSL implementation there
+// can be other
+
+/*
+*\brief A callback function for a random number
+* required by the mbed-client-mbedtls module.
+*/
+typedef uint32_t (*random_number_cb)(void) ;
+
+/*
+*\brief An entropy structure for an mbedtls entropy source.
+* \param entropy_source_ptr The entropy function.
+* \param p_source  The function data.
+* \param threshold A minimum required from the source before entropy is released
+*                  (with mbedtls_entropy_func()) (in bytes).
+* \param strong    MBEDTLS_ENTROPY_SOURCE_STRONG = 1 or
+*                  MBEDTSL_ENTROPY_SOURCE_WEAK = 0.
+*                  At least one strong source needs to be added.
+*                  Weaker sources (such as the cycle counter) can be used as
+*                  a complement.
+*/
+typedef struct mbedtls_entropy {
+    int     (*entropy_source_ptr)(void *, unsigned char *,size_t , size_t *);
+    void    *p_source;
+    size_t  threshold;
+    int     strong;
+}entropy_cb;
+
+#ifdef MBED_CLIENT_USER_CONFIG_FILE
+#include MBED_CLIENT_USER_CONFIG_FILE
+#endif
+
+#ifndef MBED_CLIENT_RECONNECTION_COUNT
+#define MBED_CLIENT_RECONNECTION_COUNT 3
+#endif
+
+#ifndef MBED_CLIENT_RECONNECTION_INTERVAL
+#define MBED_CLIENT_RECONNECTION_INTERVAL 5
+#endif
+
+#ifndef MBED_CLIENT_TCP_KEEPALIVE_INTERVAL
+#define MBED_CLIENT_TCP_KEEPALIVE_INTERVAL 90
+#endif
+
+#ifndef MBED_CLIENT_EVENT_LOOP_SIZE
+#define MBED_CLIENT_EVENT_LOOP_SIZE 1024
+#endif
+
+#ifndef SN_COAP_MAX_INCOMING_MESSAGE_SIZE
+#define SN_COAP_MAX_INCOMING_MESSAGE_SIZE UINT16_MAX
+#endif
+
+#ifndef MBED_CLIENT_DTLS_PEER_MAX_TIMEOUT
+#define MBED_CLIENT_DTLS_PEER_MAX_TIMEOUT 80000
+#endif
+
+#endif // M2MCONFIG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mconnectionhandler.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_CONNECTION_HANDLER_H__
+#define M2M_CONNECTION_HANDLER_H__
+
+#include "mbed-client/m2mconnectionobserver.h"
+#include "mbed-client/m2mconfig.h"
+#include "mbed-client/m2minterface.h"
+#include "nsdl-c/sn_nsdl.h"
+
+class M2MConnectionSecurity;
+class M2MConnectionHandlerPimpl;
+
+/*! \file m2mconnectionhandler.h
+ * \brief M2MConnectionHandler.
+ * This class handles the socket connection for the LWM2M Client.
+ */
+
+class M2MConnectionHandler {
+public:
+
+    /**
+     * @enum ConnectionError
+     * This enum defines an error that can come from the
+     * socket read and write operation.
+     */
+    typedef enum {
+        CONNECTION_ERROR_WANTS_READ = -1000,
+        CONNECTION_ERROR_WANTS_WRITE = -1001,
+        SSL_PEER_CLOSE_NOTIFY = -1002,
+        ERROR_NONE = 0,
+        SSL_CONNECTION_ERROR,
+        SOCKET_READ_ERROR,
+        SOCKET_SEND_ERROR,
+        SOCKET_ABORT,
+        DNS_RESOLVING_ERROR,
+        SSL_HANDSHAKE_ERROR,
+        SSL_PEER_CLOSED
+    }ConnectionError;
+
+
+public:
+
+    /**
+    * \brief Constructor
+    */
+    M2MConnectionHandler(M2MConnectionObserver &observer,
+                         M2MConnectionSecurity* sec,
+                         M2MInterface::BindingMode mode,
+                         M2MInterface::NetworkStack stack);
+
+    /**
+    * \brief Destructor
+    */
+    ~M2MConnectionHandler();
+
+    /**
+    * \brief This binds the socket connection.
+    * \param listen_port The port to be listened to for an incoming connection.
+    * \return True if successful, else false.
+    */
+    bool bind_connection(const uint16_t listen_port);
+
+    /**
+    * \brief This resolves the server address. The output is
+    * returned through a callback.
+    * \param String The server address.
+    * \param uint16_t The server port.
+    * \param ServerType The server type to be resolved.
+    * \param security The M2MSecurity object that determines which
+    * type of secure connection is used by the socket.
+    * \return True if the address is valid, else false.
+    */
+    bool resolve_server_address(const String& server_address,
+                                const uint16_t server_port,
+                                M2MConnectionObserver::ServerType server_type,
+                                const M2MSecurity* security);
+
+    /**
+    * \brief Sends data to the connected server.
+    * \param data_ptr The data to be sent.
+    * \param data_len The length of data to be sent.
+    * \param address_ptr The address structure to which the data needs to be sent.
+    * \return True if data is sent successfully, else false.
+    */
+    bool send_data(uint8_t *data_ptr,
+                           uint16_t data_len,
+                           sn_nsdl_addr_s *address_ptr);
+
+    /**
+    * \brief Listens to the incoming data from a remote server.
+    * \return True if successful, else false.
+    */
+    bool start_listening_for_data();
+
+    /**
+    * \brief Stops listening to the incoming data.
+    */
+    void stop_listening();
+
+    /**
+    * \brief Closes the open connection.
+    * \note This must be called from the same event loop context!
+    */
+    void force_close();
+
+    /**
+    * \brief Error handling for DTLS connectivity.
+    * \param error An error code from the TLS library.
+    */
+    void handle_connection_error(int error);
+
+    /**
+     * \brief Sets the network interface handler that is used by the client to connect
+     * to a network over IP.
+     * \param handler A network interface handler that is used by the client to connect.
+     *  This API is optional but it provides a mechanism for different platforms to
+     * manage the usage of underlying network interface by client.
+     */
+    void set_platform_network_handler(void *handler = NULL);
+
+    /**
+    * \brief Claims mutex to prevent thread clashes
+    * in multithreaded environment.
+    */
+    void claim_mutex();
+
+    /**
+    * \brief Releases mutex to prevent thread clashes
+    * in multithreaded environment.
+    */
+    void release_mutex();
+
+private:
+
+    M2MConnectionObserver                       &_observer;
+    M2MConnectionHandlerPimpl                   *_private_impl;
+
+friend class Test_M2MConnectionHandler;
+friend class Test_M2MConnectionHandler_mbed;
+friend class Test_M2MConnectionHandler_linux;
+friend class M2MConnection_TestObserver;
+};
+
+#endif //M2M_CONNECTION_HANDLER_H__
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mconnectionobserver.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_CONNECTION_OBSERVER_H__
+#define M2M_CONNECTION_OBSERVER_H__
+
+#include "mbed-client/m2minterface.h"
+
+/*! \file m2mconnectionobserver.h
+ * \brief M2MConnectionObserver.
+ * The observer class for passing the socket activity to the state machine.
+ */
+
+class M2MConnectionObserver
+{
+
+public :
+
+    /**
+      * \enum ServerType, Defines the type of the
+      * server that the client wants to use.
+      */
+    typedef enum {
+        Bootstrap,
+        LWM2MServer
+    }ServerType;
+
+    /**
+     * \brief The M2MSocketAddress struct.
+     * A unified container for holding socket address data
+     * across different platforms.
+     */
+    struct SocketAddress{
+        M2MInterface::NetworkStack  _stack;
+        void                        *_address;
+        uint8_t                     _length;
+        uint16_t                    _port;
+    };
+
+    /**
+    * \brief Indicates that data is available from socket.
+    * \param data The data read from the socket.
+    * \param data_size The length of the data read from the socket.
+    * \param address The address of the server where the data is coming from.
+    */
+    virtual void data_available(uint8_t* data,
+                                uint16_t data_size,
+                                const M2MConnectionObserver::SocketAddress &address) = 0;
+
+    /**
+    * \brief Indicates an error occured in socket.
+    * \param error_code The error code from socket, it cannot be used any further.
+    * \param retry Indicates whether to re-establish the connection.
+    */
+    virtual void socket_error(uint8_t error_code, bool retry = true) = 0;
+
+    /**
+    * \brief Indicates that the server address resolving is ready.
+    * \param address The resolved socket address.
+    * \param server_type The type of the server.
+    * \param server_port The port of the resolved server address.
+    */
+    virtual void address_ready(const M2MConnectionObserver::SocketAddress &address,
+                               M2MConnectionObserver::ServerType server_type,
+                               const uint16_t server_port) = 0;
+
+    /**
+    * \brief Indicates that data has been sent successfully.
+    */
+    virtual void data_sent() = 0;
+};
+
+#endif // M2M_CONNECTION_OBSERVER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mconnectionsecurity.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef __M2M_CONNECTION_SECURITY_H__
+#define __M2M_CONNECTION_SECURITY_H__
+
+#include "mbed-client/m2mconfig.h"
+
+#include <stdint.h>
+
+class M2MConnectionHandler;
+class M2MSecurity;
+class M2MConnectionSecurityPimpl;
+class M2MConnectionHandler;
+
+/*! \file m2mconnectionsecurity.h
+ * \brief M2MConnectionSecurity.
+ * This class provides a method to create a secure socket connection
+ * to handle connectivity for the mbed Client. It handles sending, receiving
+ * and establishing a secure connection for mbed Client on top of the
+ * normal socket connection.
+ */
+
+class M2MConnectionSecurity {
+public:
+    typedef enum {
+        NO_SECURITY = 0,
+        TLS,
+        DTLS
+    } SecurityMode;
+
+private:
+    // Prevents the use of assignment operator by accident.
+    M2MConnectionSecurity& operator=( const M2MConnectionSecurity& /*other*/ );
+    // Prevents the use of copy constructor by accident.
+    M2MConnectionSecurity( const M2MConnectionSecurity& /*other*/ );
+
+public:
+    /**
+     * \brief Default Constructor.
+     */
+    M2MConnectionSecurity(SecurityMode mode);
+
+    /**
+     * \brief Default Destructor.
+     */
+    ~M2MConnectionSecurity();
+
+    /**
+     * \brief Resets the socket connection states.
+     */
+    void reset();
+
+    /**
+     * \brief Initiatlizes the socket connection states.
+     */
+    int init(const M2MSecurity *security, uint16_t security_instance_id);
+
+    /**
+     * \brief Starts the connection in non-blocking mode.
+     * \param connHandler The ConnectionHandler object that maintains the socket.
+     * \return Returns the state of the connection. Successful or not.
+     */
+    int start_connecting_non_blocking(M2MConnectionHandler* connHandler);
+
+    /**
+     * \brief Continues connectivity logic for a secure connection.
+     * \return Returns an error code if any while continuing the connection sequence.
+     */
+    int continue_connecting();
+
+    /**
+     * \brief Connects the client to the server.
+     * \param connHandler The ConnectionHandler object that maintains the socket.
+     * \return Returns the state of the connection. Successful or not.
+     */
+    int connect(M2MConnectionHandler* connHandler);
+
+    /**
+     * \brief Sends data to the server.
+     * \param message The data to be sent.
+     * \param len The length of the data.
+     * \return Indicates whether the data is sent successfully or not.
+     */
+    int send_message(unsigned char *message, int len);
+
+    /**
+     * \brief Reads the data received from the server.
+     * \param message The data to be read.
+     * \param len The length of the data.
+     * \return Indicates whether the data is read successfully or not.
+     */
+    int read(unsigned char* buffer, uint16_t len);
+
+    /**
+     * \brief Sets the function callback that is called by mbed Client to
+     * fetch a random number from an application to ensure strong entropy.
+     * \param random_callback A function pointer that is called by mbed Client
+     * while performing a secure handshake.
+     * The function signature should be uint32_t (*random_number_callback)(void);
+     */
+    void set_random_number_callback(random_number_cb callback);
+
+    /**
+     * \brief Sets the function callback that is called by mbed Client to
+     * provide an entropy source from an application to ensure strong entropy.
+     * \param entropy_callback A function pointer that is called by mbed-client
+     * while performing a secure handshake.
+     * Function signature, if using mbed-client-mbedtls, should be
+     * int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output,
+     *                                     size_t len, size_t *olen);
+     */
+    void set_entropy_callback(entropy_cb callback);
+
+    /**
+     * \brief Set socket information for this secure connection.
+     * \param socket Socket used with this TLS session.
+     * \param address Pointer to the address of the server.
+     * \return Indicates whether the data is read successfully or not.
+     */
+    void set_socket(void *socket, void *address);
+
+private:
+
+    M2MConnectionSecurityPimpl* _private_impl;
+
+    friend class Test_M2MConnectionSecurity;
+    //friend class Test_M2MConnectionSecurityImpl;
+};
+
+#endif //__M2M_CONNECTION_SECURITY_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mconstants.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2MCONSTANTS_H
+#define M2MCONSTANTS_H
+
+/*! \file m2mconstants.h
+* \brief File defining all the constants used across mbed-client.
+*/
+
+#include <stdint.h>
+#include "m2mconfig.h"
+
+const int MAX_VALUE_LENGTH = 256;
+const int BUFFER_LENGTH = 1152;
+
+const uint8_t MINIMUM_REGISTRATION_TIME = 60; //in seconds
+const uint8_t ONE_SECOND_TIMER = 1;
+const uint8_t MAX_ALLOWED_STRING_LENGTH = 64;
+const uint8_t MAX_ALLOWED_ERROR_STRING_LENGTH = 64;
+const uint16_t OPTIMUM_LIFETIME = 3600;
+const uint16_t REDUCE_LIFETIME = 900;
+const float REDUCTION_FACTOR = 0.75f;
+const uint16_t MAX_CERTIFICATE_SIZE = 1024;
+const uint16_t CONFIG_BOOLEAN_ITEM_SIZE = 4;
+
+// XXX:
+//                               <name></><inst-id></><res-name>
+//#define MAX_OBJECT_INSTANCE_NAME (255 + 1 + 5 + 1 + 255 + 1 + 5)
+//                           <name></><inst-id></><inst-id><zero-terminator>
+#define MAX_OBJECT_PATH_NAME (255 + 1 + 5 + 1 + 5 + 1)
+
+// values per: draft-ietf-core-observe-16
+// OMA LWM2M CR ref.
+#define START_OBSERVATION 0
+#define STOP_OBSERVATION 1
+
+#define COAP "coap://"
+#define COAPS  "coaps://"
+#define BOOTSTRAP_URI "bs"
+// PUT attributes to be checked from server
+#define EQUAL  "="
+#define AMP  "&"
+#define PMIN  "pmin"
+#define PMAX  "pmax"
+#define GT  "gt"
+#define LT  "lt"
+#define ST_SIZE  "st"
+#define STP  "stp"
+#define CANCEL  "cancel"
+
+// Different query parameters
+#define QUERY_PARAM_IEP "iep"
+#define QUERY_PARAM_EST "est"
+#define QUERY_PARAM_AID "aid"
+
+// Different query parameter values
+#define QUERY_VALUE_TRUE "true"
+
+// just a helper for "String default_value = "";" pattern
+extern const String EMPTY;
+
+//LWM2MOBJECT NAME/ID
+#define M2M_SECURITY_ID  "0"
+#define M2M_SERVER_ID  "1"
+#define M2M_ACCESS_CONTROL_ID  "2"
+#define M2M_DEVICE_ID  "3"
+#define M2M_CONNECTIVITY_MONITOR_ID  "4"
+#define M2M_FIRMWARE_ID  "5"
+#define M2M_LOCATION_ID  "6"
+#define M2M_CONNECTIVITY_STATISTICS_ID  "7"
+#define RESERVED_ID  "8"
+
+//OMA RESOURCE TYPE
+#define OMA_RESOURCE_TYPE  "" //oma.lwm2m
+
+//DEVICE RESOURCES
+#define DEVICE_MANUFACTURER  "0"
+#define DEVICE_DEVICE_TYPE  "17"
+#define DEVICE_MODEL_NUMBER  "1"
+#define DEVICE_SERIAL_NUMBER  "2"
+#define DEVICE_HARDWARE_VERSION  "18"
+#define DEVICE_FIRMWARE_VERSION  "3"
+#define DEVICE_SOFTWARE_VERSION  "19"
+#define DEVICE_REBOOT  "4"
+#define DEVICE_FACTORY_RESET  "5"
+#define DEVICE_AVAILABLE_POWER_SOURCES  "6"
+#define DEVICE_POWER_SOURCE_VOLTAGE  "7"
+#define DEVICE_POWER_SOURCE_CURRENT  "8"
+#define DEVICE_BATTERY_LEVEL  "9"
+#define DEVICE_BATTERY_STATUS  "20"
+#define DEVICE_MEMORY_FREE  "10"
+#define DEVICE_MEMORY_TOTAL  "21"
+#define DEVICE_ERROR_CODE  "11"
+#define DEVICE_RESET_ERROR_CODE  "12"
+#define DEVICE_CURRENT_TIME  "13"
+#define DEVICE_UTC_OFFSET  "14"
+#define DEVICE_TIMEZONE  "15"
+#define DEVICE_SUPPORTED_BINDING_MODE  "16"
+#define BINDING_MODE_UDP  "U"
+#define BINDING_MODE_UDP_QUEUE  "UQ"
+#define BINDING_MODE_SMS  "S"
+#define BINDING_MODE_SMS_QUEUE  "SQ"
+#define ERROR_CODE_VALUE  "0"
+
+//SECURITY RESOURCES
+#define SECURITY_M2M_SERVER_URI  "0"
+#define SECURITY_BOOTSTRAP_SERVER  "1"
+#define SECURITY_SECURITY_MODE  "2"
+#define SECURITY_PUBLIC_KEY  "3"
+#define SECURITY_SERVER_PUBLIC_KEY  "4"
+#define SECURITY_SECRET_KEY  "5"
+#define SECURITY_SMS_SECURITY_MODE  "6"
+#define SECURITY_SMS_BINDING_KEY  "7"
+#define SECURITY_SMS_BINDING_SECRET_KEY  "8"
+#define SECURITY_M2M_SERVER_SMS_NUMBER  "9"
+#define SECURITY_SHORT_SERVER_ID  "10"
+#define SECURITY_CLIENT_HOLD_OFF_TIME  "11"
+
+#define SECURITY_OPEN_CERTIFICATE_CHAIN  "12"
+#define SECURITY_CLOSE_CERTIFICATE_CHAIN  "13"
+#define SECURITY_READ_CERTIFICATE_CHAIN  "14"
+
+//SERVER RESOURCES
+#define SERVER_PATH_PREFIX "1/0/"
+#define SERVER_SHORT_SERVER_ID  "0"
+#define SERVER_LIFETIME  "1"
+#define SERVER_DEFAULT_MIN_PERIOD  "2"
+#define SERVER_DEFAULT_MAX_PERIOD  "3"
+#define SERVER_DISABLE  "4"
+#define SERVER_DISABLE_TIMEOUT  "5"
+#define SERVER_NOTIFICATION_STORAGE  "6"
+#define SERVER_BINDING  "7"
+#define SERVER_REGISTRATION_UPDATE  "8"
+#define SERVER_LIFETIME_PATH SERVER_PATH_PREFIX SERVER_LIFETIME
+
+//FIRMWARE RESOURCES
+#define FIRMWARE_PATH_PREFIX "5/0/"
+#define FIRMWARE_PACKAGE  "0"
+#define FIRMWARE_PACKAGE_URI  "1"
+#define FIRMWARE_UPDATE  "2"
+#define FIRMWARE_STATE  "3"
+#define FIRMWARE_UPDATE_SUPPORTED_OBJECTS  "4"
+#define FIRMWARE_UPDATE_RESULT  "5"
+#define FIRMWARE_PACKAGE_NAME  "6"
+#define FIRMWARE_PACKAGE_VERSION  "7"
+#define FIRMAWARE_PACKAGE_URI_PATH FIRMWARE_PATH_PREFIX FIRMWARE_PACKAGE_URI
+
+// Error Strings
+
+#define ERROR_REASON_1 "No security object found for Bootstrap"
+#define ERROR_REASON_2 "Bootstrap not allowed for now, try later"
+#define ERROR_REASON_3 "Bootstrap feature is disabled"
+#define ERROR_REASON_4 "No security object found for Registration"
+#define ERROR_REASON_5 "Registration not allowed for now, try later"
+#define ERROR_REASON_6 "Unregistration not allowed for now, try later"
+#define ERROR_REASON_7 "Client is not connected, cannot send data now"
+#define ERROR_REASON_8 "LWM2M server rejected client registration"
+#define ERROR_REASON_9 "Client in reconnection mode %s"
+#define ERROR_REASON_10 "Client cannot connect anymore %s"
+#define ERROR_REASON_11 "Bootstrap server URL is not correctly formed"
+#define ERROR_REASON_12 "Bootstrap resource is not correctly formed"
+#define ERROR_REASON_13 "LWM2M server URL is not correctly formed"
+#define ERROR_REASON_14 "LWM2M server address is not set correctly in client"
+#define ERROR_REASON_15 "Failed to do full registration because of missing parameters in registration"
+#define ERROR_REASON_16 "Cannot unregister as client is not registered"
+#define ERROR_REASON_17 "Incoming CoAP message parsing failed"
+#define ERROR_REASON_18 "Sending reg-update failed as lifetime is less than 60 sec"
+#define ERROR_REASON_19 "LWM2M server URL is not correctly formed"
+#define ERROR_REASON_20 "BS PUT fails :%s"
+#define ERROR_REASON_21 "BS DEL fails :%s"
+#define ERROR_REASON_22 "BS FIN fails :%s"
+#define ERROR_REASON_23 "Bootstrap SecureConnection failed"
+#define ERROR_REASON_24 "LWM2M server rejected client unregistration (not-found)"
+#define ERROR_REASON_25 "Failed to allocate registration message"
+#define ERROR_REASON_26 "BS FIN fails: missing EST iep param"
+#define ERROR_REASON_27 "Call already in progress"
+
+#define COAP_ERROR_REASON_1 "bad-request"
+#define COAP_ERROR_REASON_2 "bad-option"
+#define COAP_ERROR_REASON_3 "request-entity-incomplete"
+#define COAP_ERROR_REASON_4 "precondition-failed"
+#define COAP_ERROR_REASON_5 "request-entity-too-large"
+#define COAP_ERROR_REASON_6 "unsupported-content-format"
+#define COAP_ERROR_REASON_7 "response-unauthorized"
+#define COAP_ERROR_REASON_8 "response-forbidden"
+#define COAP_ERROR_REASON_9 "not-acceptable"
+#define COAP_ERROR_REASON_10 "not-found"
+#define COAP_ERROR_REASON_11 "method-not-allowed"
+#define COAP_ERROR_REASON_12 "message-sending-failed"
+#define COAP_ERROR_REASON_13 "service-unavailable"
+#define COAP_ERROR_REASON_14 "internal-server-error"
+#define COAP_ERROR_REASON_15 "bad-gateway"
+#define COAP_ERROR_REASON_16 "gateway-timeout"
+#define COAP_ERROR_REASON_17 "proxying-not-supported"
+#define COAP_NO_ERROR        "no-error"
+
+#define ERROR_SECURE_CONNECTION "SecureConnectionFailed"
+#define ERROR_DNS               "DnsResolvingFailed"
+#define ERROR_NETWORK           "NetworkError"
+#define ERROR_NO                "No error"
+
+#define MAX_RECONNECT_TIMEOUT        604800
+#define RECONNECT_INCREMENT_FACTOR   2
+
+#define AUTO_OBS_TOKEN_MIN 1
+#define AUTO_OBS_TOKEN_MAX 1023
+
+#define RESPONSE_RANDOM_FACTOR  1.5   /**< Resending random factor, value is specified in IETF CoAP specification */
+
+// TLV serializer / deserializer
+const uint8_t TYPE_RESOURCE = 0xC0;
+const uint8_t TYPE_MULTIPLE_RESOURCE = 0x80;
+const uint8_t TYPE_RESOURCE_INSTANCE = 0x40;
+const uint8_t TYPE_OBJECT_INSTANCE = 0x0;
+
+const uint8_t ID8 = 0x0;
+const uint8_t ID16 = 0x20;
+
+const uint8_t LENGTH8 = 0x08;
+const uint8_t LENGTH16 = 0x10;
+const uint8_t LENGTH24 = 0x18;
+
+const uint8_t COAP_CONTENT_OMA_PLAIN_TEXT_TYPE = 0;
+const uint8_t COAP_CONTENT_OMA_TLV_TYPE_OLD = 99;
+const uint16_t COAP_CONTENT_OMA_TLV_TYPE = 11542;
+const uint16_t COAP_CONTENT_OMA_JSON_TYPE = 11543;
+const uint8_t COAP_CONTENT_OMA_OPAQUE_TYPE = 42;
+
+const uint16_t MAX_UNINT_16_COUNT = 65535;
+
+#endif // M2MCONSTANTS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mdevice.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_DEVICE_H
+#define M2M_DEVICE_H
+
+#include "mbed-client/m2mobject.h"
+
+// FORWARD DECLARATION
+class M2MResource;
+class M2MResourceInstance;
+
+/*! \file m2mdevice.h
+ *  \brief M2MDevice.
+ *  This class represents the Device Object model of the LWM2M framework.
+ *  It provides an interface for handling the device object
+ *  and all its corresponding resources. There can be only one instance
+ *  of a Device Object.
+ */
+class  M2MDevice : public M2MObject {
+
+friend class M2MInterfaceFactory;
+
+public:
+
+     /**
+      * \brief An enum defining all the resources associated with the
+      * Device Object in the LWM2M framework.
+      */
+    typedef enum {
+        Manufacturer,
+        DeviceType,
+        ModelNumber,
+        SerialNumber,
+        HardwareVersion,
+        FirmwareVersion,
+        SoftwareVersion,
+        Reboot,
+        FactoryReset,
+        AvailablePowerSources,
+        PowerSourceVoltage,
+        PowerSourceCurrent,
+        BatteryLevel,
+        BatteryStatus,
+        MemoryFree,
+        MemoryTotal,
+        ErrorCode,
+        ResetErrorCode,
+        CurrentTime,
+        UTCOffset,
+        Timezone,
+        SupportedBindingMode
+    }DeviceResource;
+
+private:
+
+    /**
+     * Constructor
+     */
+    M2MDevice(char *path);
+
+    // Prevents the use of assignment operator.
+    M2MDevice& operator=( const M2MDevice& /*other*/ );
+
+    // Prevents the use of copy constructor
+    M2MDevice( const M2MDevice& /*other*/ );
+
+    /**
+     * Destructor
+     */
+    virtual ~M2MDevice();
+
+    static M2MDevice* get_instance();
+
+public:
+
+    /**
+     * \brief Deletes an M2MDevice instance.
+     */
+    static void delete_instance();
+
+    /**
+     * \brief Creates a new resource for the given resource enum.
+     * \param resource With this function, the following resources can be created:
+     * 'Manufacturer', 'DeviceType','ModelNumber','SerialNumber',
+     * 'HardwareVersion', 'FirmwareVersion', 'SoftwareVersion',
+     *  'UTCOffset', 'Timezone', 'SupportedBindingMode'.
+     * \param value The value to be set on the resource, in string format.
+     * \return M2MResource if created successfully, else NULL.
+     */
+    M2MResource* create_resource(DeviceResource resource, const String &value);
+
+    /**
+     * \brief Creates a new resource for given resource enum.
+     * \param resource With this function, the following resources can be created:
+     * 'AvailablePowerSources','PowerSourceVoltage','PowerSourceCurrent',
+     * 'BatteryLevel', 'BatteryStatus', 'MemoryFree', 'MemoryTotal',
+     * 'ErrorCode', 'CurrentTime'. For 'CurrentTime', pass the time value in EPOCH format, for example
+     * 1438944683.
+     * \param value The value to be set on the resource, in integer format.
+     * \return M2MResource if created successfully, else NULL.
+     */
+    M2MResource* create_resource(DeviceResource resource, int64_t value);
+
+    /**
+     * \brief Creates a new resource instance for given resource enum.
+     * \param resource With this function, the following resources can be created:
+     * 'AvailablePowerSources','PowerSourceVoltage','PowerSourceCurrent',
+     * 'ErrorCode'.
+     * \param value The value to be set on the resource, in integer format.
+     * \return M2MResourceInstance if created successfully, else NULL.
+     */
+    M2MResourceInstance* create_resource_instance(DeviceResource resource, int64_t value,
+                                                  uint16_t instance_id);
+
+    /**
+     * \brief Creates a new resource for given resource name.
+     * \param resource With this function, the following resources can be created:
+     * 'ResetErrorCode','FactoryReset'.
+     * \return M2MResource if created successfully, else NULL.
+     */
+    M2MResource* create_resource(DeviceResource resource);
+
+    /**
+     * \brief Deletes the resource with the given resource enum.
+     * Mandatory resources cannot be deleted.
+     * \param resource The name of the resource to be deleted.
+     * \return True if deleted, else false.
+     */
+    bool delete_resource(DeviceResource resource);
+
+    /**
+     * \brief Deletes the resource with the given resource enum.
+     * Mandatory resources cannot be deleted.
+     * \param resource The name of the resource to be deleted.
+     * \param instance_id The instance ID of the resource.
+     * \return True if deleted, else false.
+     */
+    bool delete_resource_instance(DeviceResource resource,
+                                  uint16_t instance_id);
+
+    /**
+     * \brief Sets the value of the given resource enum.
+     * \param resource With this function, a value can be set for the following resources:
+     * 'Manufacturer', 'DeviceType','ModelNumber','SerialNumber',
+     * 'HardwareVersion', 'FirmwareVersion', 'SoftwareVersion',
+     *  'UTCOffset', 'Timezone', 'SupportedBindingMode'.
+     * \param value The value to be set on the resource, in string format.
+     * \param instance_id The instance ID of the resource, default is 0.
+     * \return True if successfully set, else false.
+     */
+    bool set_resource_value(DeviceResource resource,
+                            const String &value,
+                            uint16_t instance_id = 0);
+
+    /**
+     * \brief Sets the value of the given resource enum.
+     * \param resource With this function, a value can be set for the following resources:
+     * 'AvailablePowerSources','PowerSourceVoltage','PowerSourceCurrent',
+     * 'BatteryLevel', 'BatteryStatus', 'MemoryFree', 'MemoryTotal',
+     * 'ErrorCode', 'CurrentTime'.
+     * \param value The value to be set on the resource, in integer format.
+     * \param instance_id The instance ID of the resource, default is 0.
+     * \return True if successfully set, else false.
+     */
+    bool set_resource_value(DeviceResource resource,
+                            int64_t value,
+                            uint16_t instance_id = 0);
+
+    /**
+     * \brief Returns the value of the given resource enum, in string format.
+     * \param resource With this function, the following resources can return a value:
+     * 'Manufacturer', 'DeviceType','ModelNumber','SerialNumber',
+     * 'HardwareVersion', 'FirmwareVersion', 'SoftwareVersion',
+     *  'UTCOffset', 'Timezone', 'SupportedBindingMode'.
+     * \param instance_id The instance ID of the resource, default is 0.
+     * \return The value associated with that resource. If the resource is not valid NULL is returned.
+     */
+    String resource_value_string(DeviceResource resource,
+                                 uint16_t instance_id = 0) const;
+
+    /**
+     * \brief Returns the value of the given resource key name, in integer format.
+     * \param resource With this function, the following resources can return a value:
+     * 'AvailablePowerSources','PowerSourceVoltage','PowerSourceCurrent',
+     * 'BatteryLevel', 'BatteryStatus', 'MemoryFree', 'MemoryTotal',
+     * 'ErrorCode', 'CurrentTime'.
+     * \param instance_id The instance ID of the resource, default is 0
+     * \return The value associated with that resource. If the resource is not valid -1 is returned.
+     */
+    int64_t resource_value_int(DeviceResource resource,
+                               uint16_t instance_id = 0) const;
+
+    /**
+     * \brief Indicates whether the resource instance with the given resource enum exists or not.
+     * \param resource The resource enum.
+     * \return True if at least one instance exists, else false.
+     */
+    bool is_resource_present(DeviceResource resource)const;
+
+    /**
+     * \brief Returns the number of resources for the whole device object.
+     * \return Total number of resources belonging to the device object.
+     */
+    uint16_t total_resource_count()const;
+
+    /**
+     * \brief Returns the number of resources for a given resource enum.
+     * \param resource The resource enum.
+     * \return The number of resources for a given resource enum. Returns 1 for the
+     * mandatory resources. Can be 0 as well if no instances exist for an
+     * optional resource.
+     */
+    uint16_t per_resource_count(DeviceResource resource)const;
+
+private:
+
+    M2MResourceBase* get_resource_instance(DeviceResource dev_res,
+                                               uint16_t instance_id) const;
+
+    static const char* resource_name(DeviceResource resource);
+
+    static bool check_value_range(DeviceResource resource, const int64_t value);
+
+private :
+
+    M2MObjectInstance*    _device_instance;     //Not owned
+
+protected:
+
+    static M2MDevice*     _instance;
+
+    friend class Test_M2MDevice;
+    friend class Test_M2MInterfaceFactory;
+};
+
+#endif // M2M_DEVICE_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mendpoint.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_ENDPOINT_H
+#define M2M_ENDPOINT_H
+
+#include "mbed-client/m2mvector.h"
+#include "mbed-client/m2mbase.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mstring.h"
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+
+//FORWARD DECLARATION
+typedef Vector<M2MObject *> M2MObjectList;
+
+/*! \file M2MEndpoint.h
+ *  \brief M2MEndpoint.
+ *  This class can be used to represent an LwM2M Device endpoint, it contains a list of LwM2M objects.
+ *  It implements the M2MBase interface so it can be passed to the m2minterface for registering to server.
+ */
+
+class M2MEndpoint : public M2MBase
+{
+
+friend class M2MInterfaceFactory;
+friend class M2MNsdlInterface;
+friend class TestFactory;
+friend class Test_M2MObject;
+
+protected :
+
+    /**
+     * \brief Constructor
+     * \param name The name of the object.
+     * \param path Path of the object like 3/0/1
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     */
+    M2MEndpoint(const String &object_name,
+              char *path);
+
+    // Prevents the use of default constructor.
+    M2MEndpoint();
+
+    // Prevents the use of assignment operator.
+    M2MEndpoint& operator=( const M2MEndpoint& /*other*/ );
+
+    // Prevents the use of copy constructor.
+    M2MEndpoint( const M2MEndpoint& /*other*/ );
+
+    /*
+     * \brief Data has been changed and it needs to be updated to Mbed Cloud.
+     */
+    virtual void set_changed();
+
+    /*
+     * \brief Clears the changed flag. This can be done when the data has been updated into Mbed Cloud.
+     */
+    void clear_changed();
+
+    /*
+     * \brief Returns current changed status.
+     */
+    bool get_changed() const;
+
+
+public:
+
+    /**
+     * \brief Destructor
+     */
+    virtual ~M2MEndpoint();
+
+    /**
+     * \brief Creates a new object for a given mbed Client endpoint instance. With this,
+     * the client can respond to server's GET methods with the provided value.
+     * \return M2MObject. An object for managing object instances and resources.
+     */
+    M2MObject* create_object(const String &name);
+
+    /**
+     * \brief Removes the object with the given id.
+     * \param object_id The ID of the object to be removed, default is 0.
+     * \return True if removed, else false.
+     */
+    bool remove_object(const String &name);
+
+    /**
+     * \brief Returns the object with the the given ID.
+     * \param instance_id The ID of the requested object ID, default is 0.
+     * \return Object reference if found, else NULL.
+     */
+    M2MObject* object(const String &name) const;
+
+    /**
+     * \brief Returns a list of objects.
+     * \return A list of objects.
+     */
+    const M2MObjectList& objects() const;
+
+    /**
+     * \brief Returns the total number of objects-
+     * \return The total number of the objects.
+     */
+    uint16_t object_count() const;
+
+    /**
+     * \brief Returns the Observation Handler object.
+     * \return M2MObservationHandler object.
+    */
+    virtual M2MObservationHandler* observation_handler() const;
+
+    /**
+     * \brief Sets the observation handler
+     * \param handler Observation handler
+    */
+    virtual void set_observation_handler(M2MObservationHandler *handler);
+
+    /**
+     * \brief Adds the observation level for the object.
+     * \param observation_level The level of observation.
+     */
+    virtual void add_observation_level(M2MBase::Observation observation_level);
+
+    /**
+     * \brief Removes the observation level from the object.
+     * \param observation_level The level of observation.
+     */
+    virtual void remove_observation_level(M2MBase::Observation observation_level);
+
+    /**
+     * \brief Handles GET request for the registered objects.
+     * \param nsdl The NSDL handler for the CoAP library.
+     * \param received_coap_header The CoAP message received from the server.
+     * \param observation_handler The handler object for sending
+     * observation callbacks.
+     * \return sn_coap_hdr_s  The message that needs to be sent to server.
+     */
+    virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler = NULL);
+
+    /**
+     * \brief Handles PUT request for the registered objects.
+     * \param nsdl The NSDL handler for the CoAP library.
+     * \param received_coap_header The received CoAP message from the server.
+     * \param observation_handler The handler object for sending
+     * observation callbacks.
+     * \param execute_value_updated True will execute the "value_updated" callback.
+     * \return sn_coap_hdr_s The message that needs to be sent to server.
+     */
+    virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler,
+                                              bool &execute_value_updated);
+
+    /**
+     * \brief Handles GET request for the registered objects.
+     * \param nsdl The NSDL handler for the CoAP library.
+     * \param received_coap_header The received CoAP message from the server.
+     * \param observation_handler The handler object for sending
+     * observation callbacks.
+     * \param execute_value_updated True will execute the "value_updated" callback.
+     * \return sn_coap_hdr_s The message that needs to be sent to server.
+     */
+    virtual sn_coap_hdr_s* handle_post_request(nsdl_s *nsdl,
+                                               sn_coap_hdr_s *received_coap_header,
+                                               M2MObservationHandler *observation_handler,
+                                               bool &execute_value_updated,
+                                               sn_nsdl_addr_s *address = NULL);
+
+    /**
+     * \brief Set the user defined context for this M2MEndpoint.
+     * \param ctx pointer to allocated context, lifecycle must be handled outside of M2MEndpoint.
+     */
+    void set_context(void *ctx);
+
+    /**
+     * \brief Get the user defined context set for this M2MEndpoint.
+     * \return The user defined context or NULL if not set. The lifecycle of the user defined context
+     * is handled outside of M2MEndpoint.
+     */
+    void* get_context() const;
+
+protected :
+
+
+private:
+
+    M2MObjectList     _object_list; // owned
+    M2MObservationHandler    *_observation_handler; // Not owned
+    void             *_ctx; // user defined context
+    bool             _changed; // True if modifications have been done to this endpoint since last registration update.
+                               // False otherwise.
+
+friend class Test_M2MEndpoint;
+friend class Test_M2MInterfaceImpl;
+friend class Test_M2MNsdlInterface;
+friend class Test_M2MTLVSerializer;
+friend class Test_M2MTLVDeserializer;
+friend class Test_M2MDevice;
+friend class Test_M2MFirmware;
+friend class Test_M2MBase;
+friend class Test_M2MResource;
+friend class Test_M2MSecurity;
+friend class Test_M2MServer;
+friend class Test_M2MResourceInstance;
+};
+
+#endif // MBED_CLOUD_CLIENT_EDGE_EXTENSION
+
+#endif // M2M_ENDPOINT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mfirmware.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2MFIRMWARE_H
+#define M2MFIRMWARE_H
+
+#include "mbed-client/m2mobject.h"
+
+// FORWARD DECLARATION
+class M2MResource;
+class M2MResourceInstance;
+
+/*! \file m2mfirmware.h
+ *  \brief M2MFirmware.
+ *  This class represents the Firmware Object model of the LWM2M framework.
+ *  It provides an interface for handling the Firmware Object
+ *  and all its corresponding resources. There can be only one instance
+ *  of a Firmware Object.
+ */
+class  M2MFirmware : public M2MObject {
+
+friend class M2MInterfaceFactory;
+
+public:
+
+     /**
+      * \brief An enum defining all the resources associated with a
+      * Firmware Object in the LWM2M framework.
+      */
+    typedef enum {
+        Package,
+        PackageUri,
+        Update,
+        State,
+        UpdateSupportedObjects,
+        UpdateResult,
+        PackageName,
+        PackageVersion
+    } FirmwareResource;
+
+    /**
+     * \brief An enum defining the state of the firmware update.
+     */
+    typedef enum {
+       Idle = 0,
+       Downloading,
+       Downloaded,
+       Updating
+    } UpdateState;
+
+    /**
+     * \brief An enum defining the result of the firmware update.
+     */
+    typedef enum {
+       Default = 0,
+       SuccessfullyUpdated,
+       NotEnoughSpace,
+       OutOfMemory,
+       ConnectionLost,
+       CRCCheckFailure,
+       UnsupportedPackageType,
+       InvalidURI
+    } ResultOfUpdate;
+
+private:
+
+    /**
+     * Constructor
+     */
+    M2MFirmware();
+
+    // Prevents the use of assignment operator.
+    M2MFirmware& operator=( const M2MFirmware& /*other*/ );
+
+    // Prevents the use of copy constructor.
+    M2MFirmware( const M2MFirmware& /*other*/ );
+
+    /**
+     * Destructor
+     */
+    virtual ~M2MFirmware();
+
+    static M2MFirmware* get_instance();
+
+public:
+
+    /**
+     * \brief Deletes a M2MFirmware instance.
+     */
+    static void delete_instance();
+
+    /**
+     * \brief Creates a new resource for a given resource enum.
+     * \param resource With this function, the following resources can be created:
+     * 'PackageUri', 'PackageName','PackageVersion'.
+     * \param value The value to be set on the resource, in string format.
+     * \return M2MResource if created successfully, else NULL.
+     */
+    M2MResource* create_resource(FirmwareResource resource, const String &value);
+
+    /**
+     * \brief Creates a new resource for a given resource enum.
+     * \param resource With this function, the following resources can be created:
+     * 'State','UpdateSupportedObjects','UpdateResult'.
+     * \param value The value to be set on the resource, in integer format.
+     * \return M2MResource if created successfully, else NULL.
+     */
+    M2MResource* create_resource(FirmwareResource resource, int64_t value);
+
+    /**
+     * \brief Deletes a resource with a given resource enum.
+     * Mandatory resources cannot be deleted.
+     * \param resource The name of the resource to be deleted.
+     * \return True if deleted, else false.
+     */
+    bool delete_resource(FirmwareResource resource);
+
+    /**
+     * \brief Sets a value of a given resource enum.
+     * \param resource With this function, a value can be set on the following resources:
+     * 'Package', 'PackageUri', 'PackageName','PackageVersion'.
+     * \param value The value to be set on the resource, in string format.
+     * \return True if successfully set, else false.
+     */
+    bool set_resource_value(FirmwareResource resource,
+                            const String &value);
+
+    /**
+     * \brief Sets a value of a given resource enum.
+     * \param resource With this function, a value can be set for the following resources:
+     * 'State','UpdateSupportedObjects','UpdateResult'.
+     * \param value The value to be set on the resource, in integer format.
+     * \return True if successfully set, else false.
+     */
+    bool set_resource_value(FirmwareResource resource,
+                            int64_t value);
+
+    /**
+     * \brief Sets a value of a given resource enum.
+     * \param resource With this function, a value can be set for the following resources:
+     * 'Package'.
+     * \param value The value to be set on the resource, in uint8_t format.
+     * \param size The size of the buffer value to be set on the resource.
+     * \return True if successfully set, else false.
+     */
+    bool set_resource_value(FirmwareResource resource,
+                            const uint8_t *value,
+                            const uint32_t length);
+
+    /**
+     * \brief Returns a value of a given resource enum, in string format.
+     * \param resource With this function, the following resources can return a value:
+     * 'PackageUri', 'PackageName','PackageVersion'.
+     * \return The value associated with that resource, if the key is not valid it returns NULL.
+     */
+    String resource_value_string(FirmwareResource resource) const;
+
+    /**
+     * \brief Returns a value of a given resource key name, in integer format.
+     * \param resource With this function, the following resources can return a value:
+     * 'State','UpdateSupportedObjects','UpdateResult'.
+     * \return The value associated with that resource. If the resource is not valid -1 is returned.
+     */
+    int64_t resource_value_int(FirmwareResource resource) const;
+
+    /**
+     * \brief Populates the data buffer and returns the size of the buffer.
+     * \param resource With this function, the following resources can return a value:
+     * 'Package'.
+     * \param [OUT]data The data buffer containing the value.
+     * Tha value of the pointer MUST be set as NULL before calling this function unless it has been
+     * allocated using malloc. In that case the data is freed when calling this function.
+     * The buffer is allocated using malloc when this function is called and MUST be passed to function free after use.
+     * \return The size of the buffer populated.
+     */
+    uint32_t resource_value_buffer(FirmwareResource resource,
+                                   uint8_t *&data) const;
+
+    /**
+     * \brief Returns whether a resource instance with a given resource enum exists or not.
+     * \param resource The resource enum.
+     * \return True if at least one instance exists, else false.
+     */
+    bool is_resource_present(FirmwareResource resource) const;
+
+    /**
+     * \brief Returns the number of resources for a whole firmware object.
+     * \return Total number of resources belonging to the firmware object.
+     */
+    uint16_t total_resource_count() const;
+
+    /**
+     * \brief Returns the number of resources for a given resource enum.
+     * \param resource The resource enum.
+     * \return The number of resources for a given resource enum. Returns 1 for the
+     * mandatory resources. Can be 0 as well if no instances exist for an
+     * optional resource.
+     */
+    uint16_t per_resource_count(FirmwareResource resource) const;
+
+    /**
+     * \brief Set update resource execute callback function. This is called when update resource
+     *        receives POST command
+     * \param callback The function pointer that is called.
+     * \return True if successfully set, else false.
+     */
+    bool set_update_execute_callback(execute_callback callback);
+
+    /**
+     * \brief Set resource value update callback function. This is called when resource value
+     *        is updated.
+     * \param resource The resource enum.
+     * \param callback The function pointer that is called.
+     * \return True if successfully set, else false.
+     */
+    bool set_resource_value_update_callback(FirmwareResource resource,
+                                            value_updated_callback callback);
+
+    /**
+     * \brief Sets the callback function that is executed when this object receives
+     *        response(Empty ACK) for notification message
+     * \param resource The resource enum.
+     * \param callback The function pointer that is called.
+     * \return True if successfully set, else false.
+     * \deprecated
+     */
+    bool set_resource_notification_sent_callback(FirmwareResource resource,
+                                                 notification_sent_callback_2 callback) m2m_deprecated;
+
+
+    /**
+     * \brief Sets the callback function that is executed when notification message state changes.
+     * \param resource The resource enum.
+     * \param callback The function pointer that is called.
+     * \return True if successfully set, else false.
+     */
+    bool set_resource_notification_sent_callback(FirmwareResource resource,
+                                                 notification_delivery_status_cb callback);
+
+#ifndef DISABLE_BLOCK_MESSAGE
+    /**
+     * \brief Set incoming_block_message_callback for the package resource.
+     *        The callback will be called when a block of the package has been received.
+     * \param callback The function pointer to be called.
+     * \return true if successfully set, else false.
+     */
+    bool set_package_block_message_callback(incoming_block_message_callback callback);
+#endif
+
+private:
+
+    M2MResource* get_resource(FirmwareResource resource) const;
+
+    static const char* resource_name(FirmwareResource resource);
+
+    void create_mandatory_resources();
+
+    bool check_value_range(FirmwareResource resource, const int64_t value) const;
+
+private :
+
+    M2MObjectInstance*    _firmware_instance;     //Not owned
+
+protected:
+
+    static M2MFirmware*     _instance;
+
+    friend class Test_M2MFirmware;
+    friend class Test_M2MInterfaceFactory;
+};
+
+
+#endif // M2MFIRMWARE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2minterface.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_INTERFACE_H
+#define M2M_INTERFACE_H
+
+#include <stdint.h>
+#include "mbed-client/m2mvector.h"
+#include "mbed-client/m2mconfig.h"
+#include "mbed-client/functionpointer.h"
+
+//FORWARD DECLARATION
+class M2MSecurity;
+class M2MObject;
+class M2MBase;
+class M2MInterfaceObserver;
+
+typedef Vector<M2MObject*> M2MObjectList;
+typedef Vector<M2MBase*> M2MBaseList;
+typedef FP callback_handler;
+
+// TODO! Add more errors
+typedef enum request_error_e {
+    FAILED_TO_SEND_MSG = 0,
+    FAILED_TO_ALLOCATE_MEMORY = 1
+} request_error_t;
+
+typedef request_error_e get_data_req_error_e;
+typedef request_error_t get_data_req_error_t;
+
+/*!
+ * @brief A callback function to receive data from GET request.
+ *        Transfer is completed once total size equals to received size.
+ *        Caller needs to take care of counting how many bytes it has received.
+ * @param buffer Buffer containing the payload.
+ * @param buffer_size Size of the payload.
+ * @param total_size Total size of the package. This information is available only in first package.
+ *                   Caller must store this information to detect when the download has completed.
+ * @param context Application context
+*/
+typedef void (*request_data_cb)(const uint8_t *buffer,
+                                size_t buffer_size,
+                                size_t total_size,
+                                void *context);
+typedef request_data_cb get_data_cb; // For backward compatibility
+
+/*!
+ * @brief A callback function to receive errors from GET transfer.
+ * @param error_code
+ * @param context Application context
+*/
+typedef void (*request_error_cb)(request_error_t error_code, void *context);
+typedef request_error_cb get_data_error_cb; // For backward compatibility
+
+
+/*! \file m2minterface.h
+ *  \brief M2MInterface.
+ *  This class provides an interface for handling all mbed Client interface operations
+ *  defined in the OMA LWM2M specifications.
+ *  This includes Bootstrapping, Client Registration, Device Management &
+ *  Service Enablement and Information Reporting.
+ */
+
+class M2MInterface {
+
+public:
+
+    /**
+     * \brief An enum defining different kinds of errors
+     * that can occur during various client operations.
+     */
+    typedef enum {
+        ErrorNone = 0,
+        AlreadyExists,
+        BootstrapFailed,
+        InvalidParameters,
+        NotRegistered,
+        Timeout,
+        NetworkError,
+        ResponseParseFailed,
+        UnknownError,
+        MemoryFail,
+        NotAllowed,
+        SecureConnectionFailed,
+        DnsResolvingFailed,
+        UnregistrationFailed,
+        ESTEnrollmentFailed
+    }Error;
+
+    /**
+     * \brief An enum defining different kinds of binding
+     * modes handled for client operations.
+     */
+    typedef enum {
+        NOT_SET = 0,
+        UDP = 0x01,
+        UDP_QUEUE = 0x03,
+        SMS = 0x04,
+        SMS_QUEUE =0x06,
+        UDP_SMS_QUEUE = 0x07,
+        TCP = 0x09, //not real value, spec does not have one!
+                    //this has nsdl binding mode bit UDP set
+        TCP_QUEUE = 0x0b //not real value, spec does not have one!
+                         //this has nsdl binding mode bits, UDP and UDP_QUEUE set
+    }BindingMode;
+
+    /**
+     * \brief An enum defining different kinds of network
+     * stacks that can be used by mbed Client.
+     */
+    typedef enum {
+        Uninitialized = 0,
+        LwIP_IPv4,
+        LwIP_IPv6,
+        Reserved,
+        Nanostack_IPv6,
+        ATWINC_IPv4,
+        Unknown
+    }NetworkStack;
+
+public:
+
+    virtual ~M2MInterface(){}
+
+    /**
+     * \brief Initiates bootstrapping of the client with the provided Bootstrap
+     * Server information.
+     * NOTE: This API is not supported for developers!!
+     * \param security_object A security object that contains information
+     * required for successful bootstrapping of the client.
+     */
+    virtual void bootstrap(M2MSecurity *security_object) = 0;
+
+    /**
+     * \brief Cancels an ongoing bootstrapping operation of the client. If the client has
+     * already successfully bootstrapped, this function deletes the existing
+     * bootstrap information from the client.
+     * NOTE: This API is not supported for developers!!
+     */
+    virtual void cancel_bootstrap() = 0;
+
+    /**
+     * \brief Finishes bootstrap in cases where client will be the one to finish it.
+     */
+    virtual void finish_bootstrap() = 0;
+
+    /**
+     * \brief Initiates the registration of a provided security object to the
+     * corresponding LWM2M server.
+     * \param security_object The security object that contains information
+     * required for registering to the LWM2M server.
+     * If the client wants to register to multiple LWM2M servers, it must call
+     * this function once for each of the LWM2M server objects separately.
+     * \param object_list Objects that contain information about the
+     * client attempting to register to the LWM2M server.
+     */
+    virtual void register_object(M2MSecurity *security_object, const M2MBaseList &list) = 0;
+
+    /**
+     * \brief Initiates the registration of a provided security object to the
+     * corresponding LWM2M server.
+     * \param security_object The security object that contains information
+     * required for registering to the LWM2M server.
+     * If the client wants to register to multiple LWM2M servers, it must call
+     * this function once for each of the LWM2M server objects separately.
+     * \param object_list Objects that contain information about the
+     * client attempting to register to the LWM2M server.
+     */
+    virtual void register_object(M2MSecurity *security_object, const M2MObjectList &object_list) = 0;
+
+
+    /**
+      * \brief Removes an object from M2MInterface.
+      * Does not call delete on the object though.
+      * \return true if the object was found and false if the object was not found.
+      */
+    virtual bool remove_object(M2MBase *base) = 0;
+
+    /**
+     * \brief Updates or refreshes the client's registration on the LWM2M
+     * server.
+     * \param security_object A security object from which the device object
+     * needs to update the registration. If there is only one LWM2M server registered,
+     * this parameter can be NULL.
+     * \param lifetime The lifetime of the endpoint client in seconds. If the same value
+     * has to be passed, set the default value to 0.
+     */
+    virtual void update_registration(M2MSecurity *security_object, const uint32_t lifetime = 0) = 0;
+
+    /**
+     * \brief Updates or refreshes the client's registration on the LWM2M
+     * server. Use this function to publish new objects to LWM2M server.
+     * \param security_object The security object from which the device object
+     * needs to update the registration. If there is only one LWM2M server registered,
+     * this parameter can be NULL.
+     * \param object_list Objects that contain information about the
+     * client attempting to register to the LWM2M server.
+     * \param lifetime The lifetime of the endpoint client in seconds. If the same value
+     * has to be passed, set the default value to 0.
+     */
+    virtual void update_registration(M2MSecurity *security_object, const M2MBaseList &list,
+                                     const uint32_t lifetime = 0) = 0;
+
+    /**
+     * \brief Updates or refreshes the client's registration on the LWM2M
+     * server. Use this function to publish new objects to LWM2M server.
+     * \param security_object The security object from which the device object
+     * needs to update the registration. If there is only one LWM2M server registered,
+     * this parameter can be NULL.
+     * \param object_list Objects that contain information about the
+     * client attempting to register to the LWM2M server.
+     * \param lifetime The lifetime of the endpoint client in seconds. If the same value
+     * has to be passed, set the default value to 0.
+     */
+    virtual void update_registration(M2MSecurity *security_object, const M2MObjectList &object_list,
+                                     const uint32_t lifetime = 0) = 0;
+
+    /**
+     * \brief Unregisters the registered object from the LWM2M server.
+     * \param security_object The security object from which the device object
+     * needs to be unregistered. If there is only one LWM2M server registered,
+     * this parameter can be NULL.
+     */
+    virtual void unregister_object(M2MSecurity* security_object = NULL) = 0;
+
+    /**
+     * \brief Sets the function that is called for indicating that the client
+     * is going to sleep when the binding mode is selected with queue mode.
+     * \param callback A function pointer that is called when the client
+     * goes to sleep.
+     */
+    virtual void set_queue_sleep_handler(callback_handler handler) = 0;
+
+    /**
+     * \brief Sets the function callback that is called by mbed Client to
+     * fetch a random number from an application to ensure strong entropy.
+     * \param random_callback A function pointer that is called by mbed Client
+     * while performing a secure handshake.
+     * The function signature should be uint32_t (*random_number_callback)(void);
+     */
+    virtual void set_random_number_callback(random_number_cb callback) = 0;
+
+    /**
+     * \brief Sets the function callback that is called by mbed Client to
+     * provide an entropy source from an application to ensure strong entropy.
+     * \param entropy_callback A function pointer that is called by mbed Client
+     * while performing a secure handshake.
+     * Function signature, if using mbed-client-mbedtls, should be
+     * int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output,
+     *                                     size_t len, size_t *olen);
+     */
+    virtual void set_entropy_callback(entropy_cb callback) = 0;
+
+    /**
+     * \brief Sets the network interface handler that is used by mbed Client to connect
+     * to a network over IP.
+     * \param handler A network interface handler that is used by mbed Client to connect.
+     *  This API is optional but it provides a mechanism for different platforms to
+     * manage the usage of underlying network interface by the client.
+     */
+    virtual void set_platform_network_handler(void *handler = NULL) = 0;
+
+    /**
+     * @brief Updates the endpoint name.
+     * @param name New endpoint name
+     */
+    virtual void update_endpoint(String &name) = 0;
+
+    /**
+     * @brief Updates the domain name.
+     * @param domain New domain name
+     */
+    virtual void update_domain(String &domain) = 0;
+
+
+    /**
+     * @brief Return internal endpoint name
+     * @return internal endpoint name
+     */
+    virtual const String internal_endpoint_name() const = 0;
+
+    /**
+     * @brief Return error description for the latest error code
+     * @return Error description string
+     */
+    virtual const char *error_description() const = 0;
+
+    /**
+     * @brief Sends the CoAP GET request to the server.
+     * @uri Uri path to the data.
+     * @offset Data offset.
+     * @async In async mode application must call this API again with the updated offset.
+     *        If set to false then client will automatically download the whole package.
+     * @get_data_cb Callback which is triggered once there is data available.
+     * @get_data_error_cb Callback which is trigged in case of any error.
+    */
+    virtual void get_data_request(const char *uri,
+                                  const size_t offset,
+                                  const bool async,
+                                  get_data_cb,
+                                  get_data_error_cb,
+                                  void *context) = 0;
+
+    /**
+     * @brief Sends the CoAP POST request to the server.
+     * @uri Uri path to the data.
+     * @async In async mode application must call this API again with the updated offset.
+     *        If set to false then client will automatically download the whole package.
+     * @payload_len Length of payload.
+     * @payload_ptr, Pointer to payload buffer.
+     * @get_data_cb Callback which is triggered once there is data available.
+     * @get_data_error_cb Callback which is trigged in case of any error.
+     */
+    virtual void post_data_request(const char *uri,
+                                   const bool async,
+                                   const uint16_t payload_len,
+                                   uint8_t *payload_ptr,
+                                   get_data_cb data_cb,
+                                   get_data_error_cb error_cb,
+                                   void *context) = 0;
+
+    /**
+     * @brief Set custom uri query paramaters used in LWM2M registration.
+     * @uri_query_params Uri query params. Parameters must be in key-value format:
+     * "a=100&b=200". Maximum length can be up to 64 bytes.
+     * @return False if maximum length exceeded otherwise True.
+    */
+    virtual bool set_uri_query_parameters(const char *uri_query_params) = 0;
+};
+
+#endif // M2M_INTERFACE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2minterfacefactory.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_INTERFACE_FACTORY_H
+#define M2M_INTERFACE_FACTORY_H
+
+#include <stdlib.h>
+#include "mbed-client/m2msecurity.h"
+#include "mbed-client/m2mresource.h"
+#include "mbed-client/m2minterfaceobserver.h"
+
+//FORWARD DECLARATION
+class M2MDevice;
+class M2MServer;
+class M2MInterfaceImpl;
+class M2MFirmware;
+
+/*! \file m2minterfacefactory.h
+ *  \brief M2MInterfaceFactory.
+ *  This is a factory class that provides an interface for creating an mbed Client Interface
+ *  object for an application to utilize the LWM2M features provided by the client.
+ */
+
+class  M2MInterfaceFactory {
+private:
+    // Prevents the use of an assignment operator by accident.
+    M2MInterfaceFactory& operator=( const M2MInterfaceFactory& /*other*/ );
+
+    // Prevents the use of a copy constructor by accident.
+    M2MInterfaceFactory( const M2MInterfaceFactory& /*other*/ );
+
+public:
+
+    /**
+     * \brief Creates an interface object for the mbed Client Inteface. With this, the
+     * client can handle client operations like Bootstrapping, Client
+     * Registration, Device Management and Information Reporting.
+     * \param endpoint_name The endpoint name of mbed Client.
+     * \param endpoint_type The endpoint type of mbed Client, default is empty.
+     * \param life_time The lifetime of the endpoint in seconds,
+     *        if -1 it is optional.
+     * \param listen_port The listening port for the endpoint, default is 5683.
+     * \param domain The domain of the endpoint, default is empty.
+     * \param mode The binding mode of the endpoint, default is NOT_SET.
+     * \param stack The underlying network stack to be used for the connection,
+     * default is LwIP_IPv4.
+     * \param context_address The context address for M2M-HTTP, not used currently.
+     * \return M2MInterfaceImpl An object for managing other client operations.
+     */
+    static M2MInterface *create_interface(M2MInterfaceObserver &observer,
+                                              const String &endpoint_name,
+                                              const String &endpoint_type = "",
+                                              const int32_t life_time = -1,
+                                              const uint16_t listen_port = 5683,
+                                              const String &domain = "",
+                                              M2MInterface::BindingMode mode = M2MInterface::NOT_SET,
+                                              M2MInterface::NetworkStack stack = M2MInterface::LwIP_IPv4,
+                                              const String &context_address = "");
+
+    /**
+     * \brief Creates a security object for the mbed Client Inteface. With this, the
+     * client can manage Bootstrapping and Client Registration.
+     * \param ServerType The type of the Security Object, bootstrap or LWM2M server.
+     * \return M2MSecurity An object for managing other client operations.
+     */
+    static M2MSecurity *create_security(M2MSecurity::ServerType server_type);
+
+    /**
+     * \brief Creates a server object for the mbed Client Inteface. With this, the 
+     * client can manage the server resources used for client operations
+     * such as Client Registration, server lifetime.
+     * \return M2MServer An object for managing server client operations.
+     */
+    static M2MServer *create_server();
+
+    /**
+     * \brief Creates a device object for the mbed Client Inteface. With this, the
+     * client can manage the device resources used for client operations
+     * such as Client Registration, Device Management and Information Reporting.
+     * \param name The name of the device object.
+     * \return M2MDevice An object for managing other client operations.
+     */
+    static M2MDevice *create_device();
+
+    /**
+     * \brief Creates a firmware object for the mbed Client Inteface. With this, the
+     * client can manage the firmware resources used for the client operations
+     * such as Client Registration, Device Management and Information Reporting.
+     * \return M2MFirmware An object for managing other client operations.
+     */
+    static M2MFirmware *create_firmware();
+
+    /**
+     * \brief Creates a generic object for the mbed Client Inteface. With this, the
+     * client can manage its own customized resources used for registering
+     * Device Management and Information Reporting for those resources.
+     * \param name The name of the object.
+     * \return M2MObject An object for managing other mbed Client operations.
+     */
+    static M2MObject *create_object(const String &name);
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+    /**
+     * \brief Creates a endpoint object for the mbed Client Inteface. With this, the
+     * client can manage multiple endpoints and their resources. Common directory path "d/"
+     * will be prepended to the endpoint path, resulting in the endpoint having final path of
+     * "d/name".
+     * \param name The name of the object.
+     * \return M2MObject An object for managing other mbed Client operations.
+     */
+    static M2MEndpoint* create_endpoint(const String &name);
+#endif
+
+    friend class Test_M2MInterfaceFactory;
+};
+
+#endif // M2M_INTERFACE_FACTORY_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2minterfaceobserver.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_INTERFACE_OBSERVER_H
+#define M2M_INTERFACE_OBSERVER_H
+
+#include "mbed-client/m2mbase.h"
+#include "mbed-client/m2minterface.h"
+
+//FORWARD DECLARATION
+class M2MServer;
+
+/*! \file m2minterfaceobserver.h
+ * \brief M2MInterfaceObserver
+ * This is an observer class that updates the calling application about
+ * various events associated with various Interface operations.
+ * Also, it informs about various errors that can occur during any of the above
+ * operations.
+ */
+class M2MInterfaceObserver {
+
+public:
+
+    /**
+     * \brief A callback indicating that the bootstap has been performed successfully.
+     * \param server_object The server object that contains information fetched
+     * about the LWM2M server from the bootstrap server. This object can be used
+     * to register to the LWM2M server. The object ownership is passed.
+     */
+    virtual void bootstrap_done(M2MSecurity *server_object) = 0;
+
+    /**
+     * \brief A callback indicating that the device object has been registered
+     * successfully to the LWM2M server.
+     * \param security_object The server object on which the device object is
+     * registered. The object ownership is passed.
+     * \param server_object An object containing information about the LWM2M server.
+     * The client maintains the object.
+     */
+    virtual void object_registered(M2MSecurity *security_object, const M2MServer &server_object) = 0;
+
+    /**
+     * \brief A callback indicating that the device object has been successfully unregistered
+     * from the LWM2M server.
+     * \param server_object The server object from which the device object is
+     * unregistered. The object ownership is passed.
+     */
+    virtual void object_unregistered(M2MSecurity *server_object) = 0;
+
+    /**
+     * \brief A callback indicating that the device object registration has been successfully
+     * updated on the LWM2M server.
+     * \param security_object The server object on which the device object registration
+     * updated. The object ownership is passed.
+     * \param server_object An object containing information about the LWM2M server.
+     * The client maintains the object.
+     */
+    virtual void registration_updated(M2MSecurity *security_object, const M2MServer & server_object) = 0;
+
+    /**
+     * \brief A callback indicating that there was an error during the operation.
+     * \param error An error code for the occurred error.
+     */
+    virtual void error(M2MInterface::Error error) = 0;
+
+    /**
+     * \brief A callback indicating that the value of the resource object is updated by the server.
+     * \param base The object whose value is updated.
+     * \param type The type of the object.
+     */
+    virtual void value_updated(M2MBase *base, M2MBase::BaseType type) = 0;
+
+    /**
+     * \brief A callback indicating when all bootstrap data has been received.
+     * \param security_object, The security object that contains the security information.
+     */
+    virtual void bootstrap_data_ready(M2MSecurity *security_object) { };
+
+};
+
+#endif // M2M_INTERFACE_OBSERVER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mobject.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_OBJECT_H
+#define M2M_OBJECT_H
+
+#include "mbed-client/m2mvector.h"
+#include "mbed-client/m2mbase.h"
+#include "mbed-client/m2mobjectinstance.h"
+
+//FORWARD DECLARATION
+typedef Vector<M2MObjectInstance *> M2MObjectInstanceList;
+
+class M2MEndpoint;
+
+/*! \file m2mobject.h
+ *  \brief M2MObject.
+ *  This class is the base class for the mbed Client Objects. All defined
+ *  LWM2M object models can be created based on it. This class also holds all object
+ *  instances associated with the given object.
+ */
+
+class M2MObject : public M2MBase
+{
+
+friend class M2MInterfaceFactory;
+friend class M2MEndpoint;
+friend class TestFactory;
+
+protected :
+
+    /**
+     * \brief Constructor
+     * \param name The name of the object.
+     * \param path Path of the object like 3/0/1
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     */
+    M2MObject(const String &object_name,
+              char *path,
+              bool external_blockwise_store = false);
+
+    // Prevents the use of default constructor.
+    M2MObject();
+
+    // Prevents the use of assignment operator.
+    M2MObject& operator=( const M2MObject& /*other*/ );
+
+    // Prevents the use of copy constructor.
+    M2MObject( const M2MObject& /*other*/ );
+
+    /**
+     * \brief Constructor
+     * \param name The name of the object.
+     */
+    M2MObject(const M2MBase::lwm2m_parameters_s* static_res);
+
+public:
+
+    /**
+     * \brief Destructor
+     */
+    virtual ~M2MObject();
+
+    /**
+     * \brief Creates a new object instance for a given mbed Client Interface object. With this,
+     * the client can respond to server's GET methods with the provided value.
+     * \return M2MObjectInstance. An object instance for managing other client operations.
+     */
+    M2MObjectInstance* create_object_instance(uint16_t instance_id = 0);
+
+    /**
+     * TODO!!
+     */
+    M2MObjectInstance* create_object_instance(const lwm2m_parameters_s* s);
+
+    /**
+     * \brief Removes the object instance resource with the given instance id.
+     * \param instance_id The instance ID of the object instance to be removed, default is 0.
+     * \return True if removed, else false.
+     */
+    bool remove_object_instance(uint16_t instance_id = 0);
+
+    /**
+     * \brief Returns the object instance with the the given instance ID.
+     * \param instance_id The instance ID of the requested object instance ID, default is 0.
+     * \return Object instance reference if found, else NULL.
+     */
+    M2MObjectInstance* object_instance(uint16_t instance_id = 0) const;
+
+    /**
+     * \brief Returns a list of object instances.
+     * \return A list of object instances.
+     */
+    const M2MObjectInstanceList& instances() const;
+
+    /**
+     * \brief Returns the total number of object instances-
+     * \return The total number of the object instances.
+     */
+    uint16_t instance_count() const;
+
+    /**
+     * \brief Returns the Observation Handler object.
+     * \return M2MObservationHandler object.
+    */
+    virtual M2MObservationHandler* observation_handler() const;
+
+    /**
+     * \brief Sets the observation handler
+     * \param handler Observation handler
+    */
+    virtual void set_observation_handler(M2MObservationHandler *handler);
+
+    /**
+     * \brief Adds the observation level for the object.
+     * \param observation_level The level of observation.
+     */
+    virtual void add_observation_level(M2MBase::Observation observation_level);
+
+    /**
+     * \brief Removes the observation level from the object.
+     * \param observation_level The level of observation.
+     */
+    virtual void remove_observation_level(M2MBase::Observation observation_level);
+
+    /**
+     * \brief Handles GET request for the registered objects.
+     * \param nsdl The NSDL handler for the CoAP library.
+     * \param received_coap_header The CoAP message received from the server.
+     * \param observation_handler The handler object for sending
+     * observation callbacks.
+     * \return sn_coap_hdr_s  The message that needs to be sent to server.
+     */
+    virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler = NULL);
+
+    /**
+     * \brief Handles PUT request for the registered objects.
+     * \param nsdl The NSDL handler for the CoAP library.
+     * \param received_coap_header The received CoAP message from the server.
+     * \param observation_handler The handler object for sending
+     * observation callbacks.
+     * \param execute_value_updated True will execute the "value_updated" callback.
+     * \return sn_coap_hdr_s The message that needs to be sent to server.
+     */
+    virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler,
+                                              bool &execute_value_updated);
+
+    /**
+     * \brief Handles GET request for the registered objects.
+     * \param nsdl The NSDL handler for the CoAP library.
+     * \param received_coap_header The received CoAP message from the server.
+     * \param observation_handler The handler object for sending
+     * observation callbacks.
+     * \param execute_value_updated True will execute the "value_updated" callback.
+     * \return sn_coap_hdr_s The message that needs to be sent to server.
+     */
+    virtual sn_coap_hdr_s* handle_post_request(nsdl_s *nsdl,
+                                               sn_coap_hdr_s *received_coap_header,
+                                               M2MObservationHandler *observation_handler,
+                                               bool &execute_value_updated,
+                                               sn_nsdl_addr_s *address = NULL);
+
+    void notification_update(uint16_t obj_instance_id);
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+    void set_endpoint(M2MEndpoint *endpoint);
+
+    M2MEndpoint* get_endpoint() const;
+#endif
+
+protected :
+    /**
+     * \brief Returns the owner object. Can return NULL if the object has no parent.
+     */
+    virtual M2MBase *get_parent() const;
+
+private:
+
+    M2MObjectInstanceList     _instance_list; // owned
+
+    M2MObservationHandler    *_observation_handler; // Not owned
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+    M2MEndpoint              *_endpoint; // Parent endpoint
+#endif
+
+friend class Test_M2MObject;
+friend class Test_M2MEndpoint;
+friend class Test_M2MInterfaceImpl;
+friend class Test_M2MNsdlInterface;
+friend class Test_M2MTLVSerializer;
+friend class Test_M2MTLVDeserializer;
+friend class Test_M2MDevice;
+friend class Test_M2MFirmware;
+friend class Test_M2MBase;
+friend class Test_M2MObjectInstance;
+friend class Test_M2MResource;
+friend class Test_M2MSecurity;
+friend class Test_M2MServer;
+friend class Test_M2MResourceInstance;
+};
+
+#endif // M2M_OBJECT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mobjectinstance.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,337 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_OBJECT_INSTANCE_H
+#define M2M_OBJECT_INSTANCE_H
+
+#include "mbed-client/m2mvector.h"
+#include "mbed-client/m2mresource.h"
+
+//FORWARD DECLARATION
+typedef Vector<M2MResource *> M2MResourceList;
+typedef Vector<M2MResourceInstance *> M2MResourceInstanceList;
+
+
+class M2MObject;
+
+/*! \file m2mobjectinstance.h
+ *  \brief M2MObjectInstance.
+ *  This class is the instance class for mbed Client Objects. All defined
+ *  LWM2M object models can be created based on it. This class also holds all resource
+ *  instances associated with the given object.
+ */
+
+class M2MObjectInstance : public M2MBase
+{
+
+friend class M2MObject;
+
+private: // Constructor and destructor are private which means
+         // that these objects can be created or
+         // deleted only through function provided by M2MObject.
+
+    /**
+     * \brief Constructor
+     * \param name Name of the object
+     */
+    M2MObjectInstance(M2MObject& parent,
+                      const String &resource_type,
+                      char *path,
+                      bool external_blockwise_store = false);
+
+    M2MObjectInstance(M2MObject& parent, const lwm2m_parameters_s* static_res);
+
+    // Prevents the use of default constructor.
+    M2MObjectInstance();
+
+    // Prevents the use of assignment operator.
+    M2MObjectInstance& operator=( const M2MObjectInstance& /*other*/ );
+
+    // Prevents the use of copy constructor.
+    M2MObjectInstance( const M2MObjectInstance& /*other*/ );
+
+    /**
+     * Destructor
+     */
+    virtual ~M2MObjectInstance();
+
+public:
+
+    /**
+     * \brief TODO!
+     * \return M2MResource The resource for managing other client operations.
+     */
+    M2MResource* create_static_resource(const lwm2m_parameters_s* static_res,
+                                        M2MResourceInstance::ResourceType type);
+
+    /**
+     * \brief Creates a static resource for a given mbed Client Inteface object. With this, the
+     * client can respond to server's GET methods with the provided value.
+     * \param resource_name The name of the resource.
+     * \param resource_type The type of the resource.
+     * \param value A pointer to the value of the resource.
+     * \param value_length The length of the value in the pointer.
+     * \param multiple_instance A resource can have
+     *        multiple instances, default is false.
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     * \return M2MResource The resource for managing other client operations.
+     */
+    M2MResource* create_static_resource(const String &resource_name,
+                                        const String &resource_type,
+                                        M2MResourceInstance::ResourceType type,
+                                        const uint8_t *value,
+                                        const uint8_t value_length,
+                                        bool multiple_instance = false,
+                                        bool external_blockwise_store = false);
+
+    /**
+     * \brief Creates a dynamic resource for a given mbed Client Inteface object. With this,
+     * the client can respond to different queries from the server (GET,PUT etc).
+     * This type of resource is also observable and carries callbacks.
+     * \param resource_name The name of the resource.
+     * \param resource_type The type of the resource.
+     * \param observable Indicates whether the resource is observable or not.
+     * \param multiple_instance The resource can have
+     *        multiple instances, default is false.
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     * \return M2MResource The resource for managing other client operations.
+     */
+    M2MResource* create_dynamic_resource(const String &resource_name,
+                                         const String &resource_type,
+                                         M2MResourceInstance::ResourceType type,
+                                         bool observable,
+                                         bool multiple_instance = false,
+                                         bool external_blockwise_store = false);
+
+    /**
+     * \brief TODO!
+     * \return M2MResource The resource for managing other client operations.
+     */
+    M2MResource* create_dynamic_resource(const lwm2m_parameters_s* static_res,
+                                        M2MResourceInstance::ResourceType type,
+                                        bool observable);
+
+    /**
+     * \brief Creates a static resource instance for a given mbed Client Inteface object. With this,
+     * the client can respond to server's GET methods with the provided value.
+     * \param resource_name The name of the resource.
+     * \param resource_type The type of the resource.
+     * \param value A pointer to the value of the resource.
+     * \param value_length The length of the value in pointer.
+     * \param instance_id The instance ID of the resource.
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     * \return M2MResourceInstance The resource instance for managing other client operations.
+     */
+    M2MResourceInstance* create_static_resource_instance(const String &resource_name,
+                                                         const String &resource_type,
+                                                         M2MResourceInstance::ResourceType type,
+                                                         const uint8_t *value,
+                                                         const uint8_t value_length,
+                                                         uint16_t instance_id,
+                                                         bool external_blockwise_store = false);
+
+    /**
+     * \brief Creates a dynamic resource instance for a given mbed Client Inteface object. With this,
+     * the client can respond to different queries from the server (GET,PUT etc).
+     * This type of resource is also observable and carries callbacks.
+     * \param resource_name The name of the resource.
+     * \param resource_type The type of the resource.
+     * \param observable Indicates whether the resource is observable or not.
+     * \param instance_id The instance ID of the resource.
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     * \return M2MResourceInstance The resource instance for managing other client operations.
+     */
+    M2MResourceInstance* create_dynamic_resource_instance(const String &resource_name,
+                                                          const String &resource_type,
+                                                          M2MResourceInstance::ResourceType type,
+                                                          bool observable,
+                                                          uint16_t instance_id,
+                                                          bool external_blockwise_store = false);
+
+    /**
+     * \brief Removes the resource with the given name.
+     * \param name The name of the resource to be removed.
+     * Note: this will be removed in next version, please use the
+     * remove_resource(const char*) version instead.
+     * \return True if removed, else false.
+     */
+    bool remove_resource(const String &name);
+
+    /**
+     * \brief Removes the resource with the given name.
+     * \param name The name of the resource to be removed.
+     * \return True if removed, else false.
+     */
+    bool remove_resource(const char *name);
+
+    /**
+     * \brief Removes the resource instance with the given name.
+     * \param resource_name The name of the resource instance to be removed.
+     * \param instance_id The instance ID of the instance.
+     * \return True if removed, else false.
+     */
+    bool remove_resource_instance(const String &resource_name,
+                                          uint16_t instance_id);
+
+    /**
+     * \brief Returns the resource with the given name.
+     * \param name The name of the requested resource.
+     * \return Resource reference if found, else NULL.
+     */
+    M2MResource* resource(const String &name) const;
+
+    M2MResource* resource(const char *resource) const;
+
+    /**
+     * \brief Returns a list of M2MResourceBase objects.
+     * \return A list of M2MResourceBase objects.
+     */
+    const M2MResourceList& resources() const;
+
+    /**
+     * \brief Returns the total number of resources with the object.
+     * \return Total number of the resources.
+     */
+    uint16_t resource_count() const;
+
+    /**
+     * \brief Returns the total number of single resource instances.
+     * Note: this will be removed in next version, please use the
+     * resource_count(const char*) version instead.
+     * \param resource The name of the resource.
+     * \return Total number of the resources.
+     */
+    uint16_t resource_count(const String& resource) const;
+
+    /**
+     * \brief Returns the total number of single resource instances.
+     * \param resource The name of the resource.
+     * \return Total number of the resources.
+     */
+    uint16_t resource_count(const char *resource) const;
+
+    /**
+     * \brief Adds the observation level for the object.
+     * \param observation_level The level of observation.
+     */
+    virtual void add_observation_level(M2MBase::Observation observation_level);
+
+    /**
+     * \brief Removes the observation level from the object.
+     * \param observation_level The level of observation.
+     */
+    virtual void remove_observation_level(M2MBase::Observation observation_level);
+
+    /**
+     * \brief Returns the Observation Handler object.
+     * \return M2MObservationHandler object.
+    */
+    virtual M2MObservationHandler* observation_handler() const;
+
+    /**
+     * \brief Sets the observation handler
+     * \param handler Observation handler
+    */
+    virtual void set_observation_handler(M2MObservationHandler *handler);
+
+    /**
+     * \brief Handles GET request for the registered objects.
+     * \param nsdl The NSDL handler for the CoAP library.
+     * \param received_coap_header The CoAP message received from the server.
+     * \param observation_handler The handler object for sending
+     * observation callbacks.
+     * return sn_coap_hdr_s The message that needs to be sent to the server.
+     */
+    virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler = NULL);
+    /**
+     * \brief Handles PUT request for the registered objects.
+     * \param nsdl The NSDL handler for the CoAP library.
+     * \param received_coap_header The CoAP message received from the server.
+     * \param observation_handler The handler object for sending
+     * observation callbacks.
+     * \param execute_value_updated True will execute the "value_updated" callback.
+     * \return sn_coap_hdr_s The message that needs to be sent to server.
+     */
+    virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler,
+                                              bool &execute_value_updated);
+
+    /**
+     * \brief Handles POST request for the registered objects.
+     * \param nsdl The NSDL handler for the CoAP library.
+     * \param received_coap_header The CoAP message received from the server.
+     * \param observation_handler The handler object for sending
+     * observation callbacks.
+     * \param execute_value_updated True will execute the "value_updated" callback.
+     * \return sn_coap_hdr_s The message that needs to be sent to server.
+     */
+    virtual sn_coap_hdr_s* handle_post_request(nsdl_s *nsdl,
+                                               sn_coap_hdr_s *received_coap_header,
+                                               M2MObservationHandler *observation_handler,
+                                               bool &execute_value_updated,
+                                               sn_nsdl_addr_s *address = NULL);
+
+    inline M2MObject& get_parent_object() const;
+
+    // callback used from M2MResource/M2MResourceInstance
+    void notification_update(M2MBase::Observation observation_level);
+
+protected:
+    virtual M2MBase *get_parent() const;
+
+private:
+
+    /**
+     * \brief Utility function to map M2MResourceInstance ResourceType
+     * to M2MBase::DataType.
+     * \param resource_type M2MResourceInstance::ResourceType.
+     * \return M2MBase::DataType.
+     */
+    M2MBase::DataType convert_resource_type(M2MResourceInstance::ResourceType);
+
+private:
+
+    M2MObject      &_parent;
+
+    M2MResourceList     _resource_list; // owned
+
+    friend class Test_M2MObjectInstance;
+    friend class Test_M2MObject;
+    friend class Test_M2MDevice;
+    friend class Test_M2MSecurity;
+    friend class Test_M2MServer;
+    friend class Test_M2MNsdlInterface;
+    friend class Test_M2MFirmware;
+    friend class Test_M2MTLVSerializer;
+    friend class Test_M2MTLVDeserializer;
+    friend class Test_M2MBase;
+    friend class Test_M2MResource;
+    friend class Test_M2MResourceInstance;
+    friend class TestFactory;
+};
+
+inline M2MObject& M2MObjectInstance::get_parent_object() const
+{
+    return _parent;
+}
+
+#endif // M2M_OBJECT_INSTANCE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mobservationhandler.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_OBSERVATION_HANDLER_H
+#define M2M_OBSERVATION_HANDLER_H
+
+//FORWARD DECLARATION
+class M2MBase;
+class M2MResourceInstance;
+
+/*! \file m2mobservationhandler.h
+ * \brief M2MObservationHandler.
+ * An interface for handling observation
+ * callbacks from different objects.
+ *
+ */
+class M2MObservationHandler
+{
+  public:
+
+    /**
+     * \brief The observation callback to be sent to the
+     * server due to a change in a parameter under observation.
+     * \param object The observed object whose information needs to be sent.
+     * \param obs_number The observation number.
+     * \param changed_instance_ids A list of changed object instance IDs.
+     * \param send_object Indicates whether the whole object will be sent or not.
+     *
+     * \return True if the message was send, False if there is already ongoing notification.
+     */
+    virtual bool observation_to_be_sent(M2MBase *object,
+                                        uint16_t obs_number,
+                                        const m2m::Vector<uint16_t> &changed_instance_ids,
+                                        bool send_object = false) = 0;
+
+    /**
+     * \brief A callback for removing an NSDL resource from the data structures.
+     * \param The M2MBase derived observed object whose information
+     * needs to be removed.
+     */
+    virtual void resource_to_be_deleted(M2MBase *base) = 0;
+
+    /**
+     * \brief A callback indicating that the value of the resource object is updated by server.
+     * \param base The object whose value is updated.
+     * \param object_name The name of the updated resource, default is empty.
+     */
+    virtual void value_updated(M2MBase *base) = 0;
+
+    /**
+     * \brief A callback for removing an object from the list.
+     * \param object The M2MObject to be removed.
+     */
+    virtual void remove_object(M2MBase *object) = 0;
+
+#ifndef DISABLE_DELAYED_RESPONSE
+    /**
+     * \brief A delayed response callback to be sent to the
+     * server due to a changed response.
+     * \param base The resource sending the response.
+     */
+    virtual void send_delayed_response(M2MBase *base) = 0;
+#endif
+};
+
+
+#endif // M2M_OBSERVATION_HANDLER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mreportobserver.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2MREPORTOBSERVER_H
+#define M2MREPORTOBSERVER_H
+
+#include <inttypes.h>
+#include <mbed-client/m2mvector.h>
+
+/*! \file m2mreportobserver.h
+ * \brief M2MReportObserver.
+ * An interface for inviting the base class
+ * to send a report to the server.
+ *
+ */
+class M2MReportObserver
+{
+  public:
+
+    /**
+     * \brief An observation callback to be sent to the
+     * server due to a change in the observed parameter.
+     * \param changed_instance_ids A list of changed object instance IDs.
+     * \param obs_number The observation number.
+     * \param send_object Indicates whether the whole object will be sent or not.
+     *
+     * \return True if the message was send, False if there is already ongoing notification.
+     */
+    virtual bool observation_to_be_sent(const m2m::Vector<uint16_t> &changed_instance_ids,
+                                        uint16_t obs_number,
+                                        bool send_object = false) = 0;
+
+};
+
+#endif // M2MREPORTOBSERVER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mresource.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_RESOURCE_H
+#define M2M_RESOURCE_H
+
+#include "mbed-client/m2mvector.h"
+#include "mbed-client/m2mresourcebase.h"
+#include "mbed-client/m2mresourceinstance.h"
+
+//FORWARD DECLARATION
+class M2MObjectInstance;
+typedef Vector<M2MResourceInstance *> M2MResourceInstanceList;
+
+/*! \file m2mresource.h
+ *  \brief M2MResource.
+ *  This class is the base class for mbed Client Resources. All defined
+ *  LWM2M object models can be created using it. This class will also hold all resources
+ *  instances associated with the given object.
+ */
+
+class M2MResource : public M2MResourceBase {
+
+    friend class M2MObjectInstance;
+
+public:
+    class M2MExecuteParameter;
+
+private: // Constructor and destructor are private,
+         // which means that these objects can be created or
+         // deleted only through a function provided by the M2MObjectInstance.
+
+    M2MResource(M2MObjectInstance &_parent,
+                 const lwm2m_parameters_s* s,
+                 M2MBase::DataType type);
+    /**
+     * \brief Constructor
+     * \param resource_name The resource name of the object.
+     * \param resource_type The resource type of the object.
+     * \param type The resource data type of the object.
+     * \param value The value pointer of the object.
+     * \param value_length The length of the value pointer.
+     * \param path Full path of the resource, eg. 1/2/3. Ownership of the memory is transferred.
+     * \param object_name The name of the object where the resource exists.
+     * \param multiple_instance True if the resource supports instances.
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     */
+    M2MResource(M2MObjectInstance &_parent,
+                const String &resource_name,
+                M2MBase::Mode mode,
+                const String &resource_type,
+                M2MBase::DataType type,
+                const uint8_t *value,
+                const uint8_t value_length,
+                char *path,
+                bool multiple_instance = false,
+                bool external_blockwise_store = false);
+
+    /**
+     * \brief Constructor
+     * \param resource_name The resource name of the object.
+     * \param resource_type The resource type of the object.
+     * \param type The resource data type of the object.
+     * \param observable Indicates whether the resource is observable or not.
+     * \param path Full path of the resource, eg. 1/2/3. Ownership of the memory is transferred.
+     * \param object_name The name of the object where the resource exists.
+     * \param multiple_instance True if the resource supports instances.
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     */
+    M2MResource(M2MObjectInstance &_parent,
+                const String &resource_name,
+                M2MBase::Mode mode,
+                const String &resource_type,
+                M2MBase::DataType type,
+                bool observable,
+                char *path,
+                bool multiple_instance = false,
+                bool external_blockwise_store = false);
+
+    // Prevents the use of a default constructor.
+    M2MResource();
+
+    // Prevents the use of an assignment operator.
+    M2MResource& operator=( const M2MResource& /*other*/ );
+
+    // Prevents the use of a copy constructor
+    M2MResource( const M2MResource& /*other*/ );
+
+    /**
+     * \brief Returns the owner object. Can return NULL if the object has no parent.
+     */
+    virtual M2MBase *get_parent() const;
+
+    /**
+     * Destructor
+     */
+    virtual ~M2MResource();
+
+public:
+
+    /**
+     * \brief Adds resource instances to a M2MResource.
+     * \param resource_instance The resource instance to be added.
+     */
+    void add_resource_instance(M2MResourceInstance *resource_instance);
+
+    /**
+     * \brief Returns whether the resource has multiple
+     * resource instances or not.
+     * \return True if the resource base has multiple instances,
+     * else false.
+     */
+    bool supports_multiple_instances() const;
+
+#ifndef DISABLE_DELAYED_RESPONSE
+    /**
+     * \brief Sets whether the resource should send a delayed response for a POST request.
+     * \param delayed_response A boolean value to set the delayed response.
+     */
+    void set_delayed_response(bool delayed_response);
+
+    /**
+     * \brief A trigger to send the delayed response for the POST request.
+     * The delayed_response flag must be set before receiving the POST request
+     * and the value of the resource must be updated before calling this function.
+     * \return True if a response is sent, else false.
+     */
+    bool send_delayed_post_response();
+
+    /**
+     * \brief Provides the value of the given token.
+     * \param value[OUT] A pointer to the token value.
+     * \param value_length[OUT] The length of the token pointer.
+     */
+    void get_delayed_token(uint8_t *&token, uint8_t &token_length);
+#endif
+
+    /**
+     * \brief Removes a resource with a given name.
+     * \param name The name of the resource to be removed.
+     * \param instance_id The instance ID of the resource to be removed, default is 0.
+     * \return True if removed, else false.
+     */
+    bool remove_resource_instance(uint16_t instance_id = 0);
+
+    /**
+     * \brief Returns a resource instance with a given name.
+     * \param instance_id The instance ID of the requested resource, default is 0
+     * \return M2MResourceInstance object if found, else NULL.
+     */
+    M2MResourceInstance* resource_instance(uint16_t instance_id = 0) const;
+
+    /**
+     * \brief Returns a list of resources.
+     * \return A list of resources.
+     */
+    const M2MResourceInstanceList& resource_instances() const;
+
+    /**
+     * \brief Returns the total number of resources.
+     * \return The total number of resources.
+     */
+    uint16_t resource_instance_count() const;
+
+    /**
+     * \brief Returns the value set for delayed response.
+     * \return The value for delayed response.
+     */
+    bool delayed_response() const;
+
+    /**
+     * \brief Returns the Observation Handler object.
+     * \return M2MObservationHandler object.
+    */
+    virtual M2MObservationHandler* observation_handler() const;
+
+    /**
+     * \brief Sets the observation handler
+     * \param handler Observation handler
+    */
+    virtual void set_observation_handler(M2MObservationHandler *handler);
+
+    /**
+     * \brief Parses the received query for a notification
+     * attribute.
+     * \return True if required attributes are present, else false.
+     */
+    virtual bool handle_observation_attribute(const char *query);
+
+    /**
+     * \brief Adds the observation level for the object.
+     * \param observation_level The level of observation.
+     */
+    virtual void add_observation_level(M2MBase::Observation observation_level);
+
+    /**
+     * \brief Removes the observation level from an object.
+     * \param observation_level The level of observation.
+     */
+    virtual void remove_observation_level(M2MBase::Observation observation_level);
+
+    /**
+     * \brief Handles the GET request for registered objects.
+     * \param nsdl An NSDL handler for the CoAP library.
+     * \param received_coap_header The CoAP message received from the server.
+     * \param observation_handler A handler object for sending
+     * observation callbacks.
+     * \return sn_coap_hdr_s The message that needs to be sent to the server.
+     */
+    virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler = NULL);
+    /**
+     * \brief Handles the PUT request for registered objects.
+     * \param nsdl An NSDL handler for the CoAP library.
+     * \param received_coap_header The CoAP message received from the server.
+     * \param observation_handler A handler object for sending
+     * observation callbacks.
+     * \param execute_value_updated True executes the "value_updated" callback.
+     * \return sn_coap_hdr_s The message that needs to be sent to the server.
+     */
+    virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler,
+                                              bool &execute_value_updated);
+    /**
+     * \brief Handles the POST request for registered objects.
+     * \param nsdl An NSDL handler for the CoAP library.
+     * \param received_coap_header The CoAP message received from the server.
+     * \param observation_handler A handler object for sending
+     * observation callbacks.
+     * \param execute_value_updated True executes the "value_updated" callback.
+     * \return sn_coap_hdr_s The message that needs to be sent to the server.
+     */
+    virtual sn_coap_hdr_s* handle_post_request(nsdl_s *nsdl,
+                                               sn_coap_hdr_s *received_coap_header,
+                                               M2MObservationHandler *observation_handler,
+                                               bool &execute_value_updated,
+                                               sn_nsdl_addr_s *address = NULL);
+
+    M2MObjectInstance& get_parent_object_instance() const;
+
+    /**
+     * \brief Returns the instance ID of the object where the resource exists.
+     * \return Object instance ID.
+    */
+    virtual uint16_t object_instance_id() const;
+
+    /**
+     * \brief Returns the name of the object where the resource exists.
+     * \return Object name.
+    */
+    virtual const char* object_name() const;
+
+    virtual M2MResource& get_parent_resource() const;
+private:
+    M2MObjectInstance &_parent;
+
+    M2MResourceInstanceList     _resource_instance_list; // owned
+#ifndef DISABLE_DELAYED_RESPONSE
+    uint8_t                     *_delayed_token;
+    uint8_t                     _delayed_token_len;
+    bool                        _delayed_response;
+#endif
+
+friend class Test_M2MResource;
+friend class Test_M2MObjectInstance;
+friend class Test_M2MObject;
+friend class Test_M2MDevice;
+friend class Test_M2MSecurity;
+friend class Test_M2MServer;
+friend class Test_M2MNsdlInterface;
+friend class Test_M2MFirmware;
+friend class Test_M2MTLVSerializer;
+friend class Test_M2MTLVDeserializer;
+friend class Test_M2MBase;
+friend class Test_M2MResourceInstance;
+friend class TestFactory;
+};
+
+/**
+ *  \brief M2MResource::M2MExecuteParameter.
+ *  This class handles the "Execute" operation arguments.
+ */
+class M2MResource::M2MExecuteParameter {
+
+private:
+
+    /**
+     * \brief Constructor, since there is no implementation, it prevents invalid use of it
+     */
+    M2MExecuteParameter();
+
+#ifdef MEMORY_OPTIMIZED_API
+    M2MExecuteParameter(const char *object_name, const char *resource_name, uint16_t object_instance_id);
+#else
+    // This is a deprecated constructor, to be removed on next release.
+    M2MExecuteParameter(const String &object_name, const String &resource_name, uint16_t object_instance_id);
+#endif
+
+public:
+
+    /**
+     * \brief Returns the value of an argument.
+     * \return uint8_t * The argument value.
+     */
+    const uint8_t *get_argument_value() const;
+
+    /**
+     * \brief Returns the length of the value argument.
+     * \return uint8_t The argument value length.
+     */
+    uint16_t get_argument_value_length() const;
+
+    /**
+     * \brief Returns the name of the object where the resource exists.
+     * \return Object name.
+    */
+#ifdef MEMORY_OPTIMIZED_API
+    const char* get_argument_object_name() const;
+#else
+    const String& get_argument_object_name() const;
+#endif
+
+    /**
+     * \brief Returns the resource name.
+     * \return Resource name.
+    */
+#ifdef MEMORY_OPTIMIZED_API
+    const char* get_argument_resource_name() const;
+#else
+    const String& get_argument_resource_name() const;
+#endif
+
+    /**
+     * \brief Returns the instance ID of the object where the resource exists.
+     * \return Object instance ID.
+    */
+    uint16_t get_argument_object_instance_id() const;
+
+private:
+    // pointers to const data, not owned by this instance
+
+#ifdef MEMORY_OPTIMIZED_API
+    const char      *_object_name;
+    const char      *_resource_name;
+#else
+    const String    &_object_name;
+    const String    &_resource_name;
+#endif
+
+    const uint8_t   *_value;
+    uint16_t        _value_length;
+    uint16_t        _object_instance_id;
+
+friend class Test_M2MResource;
+friend class M2MResource;
+};
+
+#endif // M2M_RESOURCE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mresourcebase.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_RESOURCE_BASE_H
+#define M2M_RESOURCE_BASE_H
+
+#include "mbed-client/m2mbase.h"
+#include "mbed-client/functionpointer.h"
+
+
+/*! \file m2mresourceinstance.h
+ *  \brief M2MResourceInstance.
+ *  This class is the base class for mbed Client Resources. All defined
+ *  LWM2M resource models can be created based on it.
+ */
+class M2MBlockMessage;
+
+typedef FP1<void,void*> execute_callback;
+typedef void(*execute_callback_2) (void *arguments);
+
+typedef FP0<void> notification_sent_callback;
+typedef void(*notification_sent_callback_2) (void);
+
+#ifndef DISABLE_BLOCK_MESSAGE
+typedef FP1<void, M2MBlockMessage *> incoming_block_message_callback;
+typedef FP3<void, const String &, uint8_t *&, uint32_t &> outgoing_block_message_callback;
+#endif
+
+class M2MResource;
+
+class M2MResourceBase : public M2MBase {
+
+friend class M2MObjectInstance;
+friend class M2MResource;
+friend class M2MResourceInstance;
+
+public:
+
+    typedef enum {
+        INIT = 0,   // Initial state.
+        SENT,       // Notification created/sent but not received ACK yet.
+        DELIVERED   // Received ACK from server.
+    } NotificationStatus;
+
+    typedef FP2<void, const uint16_t, const M2MResourceBase::NotificationStatus> notification_status_callback;
+
+    typedef void(*notification_status_callback_2) (const uint16_t msg_id,
+                                                   const M2MResourceBase::NotificationStatus status);
+
+    /**
+     * An enum defining a resource type that can be
+     * supported by a given resource.
+    */
+    typedef enum {
+        STRING,
+        INTEGER,
+        FLOAT,
+        BOOLEAN,
+        OPAQUE,
+        TIME,
+        OBJLINK
+    } ResourceType;
+
+    /*
+     * \brief Value set callback function.
+     * \param resource Pointer to resource whose value should be updated
+     * \param value Pointer to value buffer containing new value, ownership is transferred to callback function
+     * \param value_length Length of value buffer
+     */
+    typedef void(*value_set_callback) (const M2MResourceBase *resource, uint8_t *value, const uint32_t value_length);
+
+    /*
+     * \brief Read resource value callback function.
+     * \param resource Pointer to resource whose value should will be read
+     * \param buffer[OUT] Buffer containing the resource value
+     * \param buffer_size[IN/OUT] Buffer length
+     * \param client_args Client arguments
+     * \return Error code, 0 on success otherwise < 0
+     */
+    typedef int(*read_resource_value_callback) (const M2MResourceBase& resource,
+                                                void *buffer,
+                                                size_t *buffer_size,
+                                                void *client_args);
+
+    /*
+     * \brief Set resource value callback function.
+     * \param resource Pointer to resource whose value will be updated
+     * \param buffer Buffer containing the new value
+     * \param buffer_size Size of the data
+     * \param client_args Client arguments
+     * \return error code, True if value storing completed otherwise False
+     */
+    typedef bool(*write_resource_value_callback) (const M2MResourceBase& resource,
+                                                  const uint8_t *buffer,
+                                                  const size_t buffer_size,
+                                                  void *client_args);
+
+protected: // Constructor and destructor are private
+           // which means that these objects can be created or
+           // deleted only through a function provided by the M2MObjectInstance.
+
+    M2MResourceBase(
+                        const lwm2m_parameters_s* s,
+                        M2MBase::DataType type);
+    /**
+     * \brief A constructor for creating a resource.
+     * \param resource_name The name of the resource.
+     * \param resource_type The type of the resource.
+     * \param type The resource data type of the object.
+     * \param object_name Object name where resource exists.
+     * \param path Path of the object like 3/0/1
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     */
+    M2MResourceBase(
+                        const String &resource_name,
+                        M2MBase::Mode mode,
+                        const String &resource_type,
+                        M2MBase::DataType type,
+                        char* path,
+                        bool external_blockwise_store,
+                        bool multiple_instance);
+
+    /**
+     * \brief A Constructor for creating a resource.
+     * \param resource_name The name of the resource.
+     * \param resource_type The type of the resource.
+     * \param type The resource data type of the object.
+     * \param value The value pointer of the object.
+     * \param value_length The length of the value pointer.
+     * \param value_length The length of the value pointer.
+     * \param object_name Object name where resource exists.
+     * \param path Path of the object like 3/0/1
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     */
+    M2MResourceBase(
+                        const String &resource_name,
+                        M2MBase::Mode mode,
+                        const String &resource_type,
+                        M2MBase::DataType type,
+                        const uint8_t *value,
+                        const uint8_t value_length,
+                        char* path,
+                        bool external_blockwise_store,
+                        bool multiple_instance);
+
+    // Prevents the use of default constructor.
+    M2MResourceBase();
+
+    // Prevents the use of assignment operator.
+    M2MResourceBase& operator=( const M2MResourceBase& /*other*/ );
+
+    // Prevents the use of copy constructor
+    M2MResourceBase( const M2MResourceBase& /*other*/ );
+
+    /**
+     * Destructor
+     */
+    virtual ~M2MResourceBase();
+
+public:
+
+    /**
+     * \brief Returns the resource data type.
+     * \return ResourceType.
+     */
+    M2MResourceBase::ResourceType resource_instance_type() const;
+
+    /**
+     * \brief Sets the function that should be executed when this
+     * resource receives a POST command.
+     * \param callback The function pointer that needs to be executed.
+     * \return True, if callback could be set, false otherwise.
+     */
+    bool set_execute_function(execute_callback callback);
+
+    /**
+     * \brief Sets the function that should be executed when this
+     * resource receives a POST command.
+     * \param callback The function pointer that needs to be executed.
+     * \return True, if callback could be set, false otherwise.
+     */
+    bool set_execute_function(execute_callback_2 callback);
+
+    /**
+     * \brief Sets the function that is executed when the resource value change.
+     * \param callback The function pointer that needs to be executed.
+     * \param client_args Client arguments.
+     * \return True, if callback could be set, false otherwise.
+     */
+    bool set_resource_read_callback(read_resource_value_callback callback, void *client_args);
+
+    /**
+     * \brief Sets the function that is executed when reading the resource value.
+     * \param callback The function pointer that needs to be executed.
+     * \param client_args Client arguments.
+     * \return True, if callback could be set, false otherwise.
+     */
+    bool set_resource_write_callback(write_resource_value_callback callback, void *client_args);
+
+    /**
+     * \brief Executes the function that is set in "set_resource_read_callback".
+     * \note If "read_resource_value_callback" is not set this is internally calling value() and value_length() API's.
+     * \param resource Pointer to resource whose value will be read.
+     * \param buffer[OUT] Buffer where the value is stored.
+     * \param buffer_len[IN/OUT] Buffer length
+     * \return Error code, 0 on success otherwise < 0
+     */
+    int read_resource_value(const M2MResourceBase& resource, void *buffer, size_t *buffer_len);
+
+    /**
+     * \brief Executes the function that is set in "set_resource_write_callback".
+     * \param resource Pointer to resource where value will be stored.
+     * \param buffer Buffer containing the new value.
+     * \param buffer_size Size of the data.
+     * \return True if storing succeeded otherwise False.
+     */
+    bool write_resource_value(const M2MResourceBase& resource, const uint8_t *buffer, const size_t buffer_size);
+
+    /**
+     * \brief Sets a value of a given resource.
+     * \param value A pointer to the value to be set on the resource.
+     * \param value_length The length of the value pointer.
+     * \return True if successfully set, else false.
+     * \note If resource is observable, calling this API rapidly (< 1s) can fill up the CoAP resending queue
+     * and notification sending fails. CoAP resending queue size can be modified through:
+     * "sn-coap-resending-queue-size-msgs" and "sn-coap-resending-queue-size-bytes" parameters.
+     * Increasing these parameters will increase the memory consumption.
+     */
+    bool set_value(const uint8_t *value, const uint32_t value_length);
+
+    /**
+     * \brief Sets a value of a given resource.
+     * \param value A pointer to the value to be set on the resource, ownerhip transfered.
+     * \param value_length The length of the value pointer.
+     * \return True if successfully set, else false.
+     * \note If resource is observable, calling this API rapidly (< 1s) can fill up the CoAP resending queue
+     * and notification sending fails. CoAP resending queue size can be modified through:
+     * "sn-coap-resending-queue-size-msgs" and "sn-coap-resending-queue-size-bytes" parameters.
+     * Increasing these parameters will increase the memory consumption.
+     */
+    bool set_value_raw(uint8_t *value, const uint32_t value_length);
+
+    /**
+     * \brief Sets a value of a given resource.
+     * \param value, A new value formatted as a string
+     * and set on the resource.
+     * \return True if successfully set, else false.
+     * \note If resource is observable, calling this API rapidly (< 1s) can fill up the CoAP resending queue
+     * and notification sending fails. CoAP resending queue size can be modified through:
+     * "sn-coap-resending-queue-size-msgs" and "sn-coap-resending-queue-size-bytes" parameters.
+     * Increasing these parameters will increase the memory consumption.
+     */
+    bool set_value(int64_t value);
+
+    /**
+     * \brief Sets a value of a given resource.
+     * \param value, A new value formatted as a string
+     * and set on the resource.
+     * \return True if successfully set, else false.
+     * \note If resource is observable, calling this API rapidly (< 1s) can fill up the CoAP resending queue
+     * and notification sending fails. CoAP resending queue size can be modified through:
+     * "sn-coap-resending-queue-size-msgs" and "sn-coap-resending-queue-size-bytes" parameters.
+     * Increasing these parameters will increase the memory consumption.
+     */
+    bool set_value_float(float value);
+
+    /**
+     * \brief Clears the value of a given resource.
+     */
+    void clear_value();
+
+    /**
+     * \brief Executes the function that is set in "set_execute_function".
+     * \param arguments The arguments that are passed to be executed.
+     */
+    void execute(void *arguments);
+
+    /**
+     * \brief Provides the value of the given resource.
+     * \param value[OUT] A pointer to the resource value.
+     * \param value_length[OUT] The length of the value pointer.
+     * \note If value argument is not NULL, it will be freed.
+     */
+    void get_value(uint8_t *&value, uint32_t &value_length);
+
+    /**
+     * \brief Converts a value to integer and returns it. Note: Conversion
+     * errors are not detected.
+     */
+    int64_t get_value_int() const;
+
+    /**
+     * Get the value as a string object. No encoding/charset conversions
+     * are done for the value, just a raw copy.
+     */
+    String get_value_string() const;
+
+    /**
+     * \brief Converts a value to float and returns it. Note: Conversion
+     * errors are not detected.
+     */
+    float get_value_float() const;
+
+    /**
+     * \brief Returns the value pointer of the object.
+     * \return The value pointer of the object.
+     */
+    uint8_t* value() const;
+
+    /**
+     * \brief Returns the length of the value pointer.
+     * \return The length of the value pointer.
+     */
+    uint32_t value_length() const;
+
+    /**
+     * \brief Set the value set callback. The set callback will be called instead of setting
+     * the value in set_value methods. When this function is set actual value change is done
+     * using the update_value function.
+     * \param callback Callback function that will handle new value
+     */
+    void set_value_set_callback(value_set_callback callback);
+
+    /**
+     * \brief Default value update function. This function frees old value, stores the new value
+     * and informs report handler in case it changed.
+     * \param value Pointer to new value, ownership is transferred to client
+     * \param value_length Length of new value buffer
+     */
+    void update_value(uint8_t *value, const uint32_t value_length);
+
+    /**
+     * \brief Handles the GET request for the registered objects.
+     * \param nsdl An NSDL handler for the CoAP library.
+     * \param received_coap_header The CoAP message received from the server.
+     * \param observation_handler A handler object for sending
+     * observation callbacks.
+     * \return sn_coap_hdr_s The message that needs to be sent to the server.
+     */
+    virtual sn_coap_hdr_s* handle_get_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler = NULL);
+    /**
+     * \brief Handles the PUT request for the registered objects.
+     * \param nsdl An NSDL handler for the CoAP library.
+     * \param received_coap_header The CoAP message received from the server.
+     * \param observation_handler A handler object for sending
+     * observation callbacks.
+     * \param execute_value_updated True will execute the "value_updated" callback.
+     * \return sn_coap_hdr_s The message that needs to be sent to the server.
+     */
+    virtual sn_coap_hdr_s* handle_put_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler,
+                                              bool &execute_value_updated);
+
+    /**
+     * \brief Returns the instance ID of the object where the resource exists.
+     * \return Object instance ID.
+    */
+    virtual uint16_t object_instance_id() const = 0;
+
+    /**
+     * \brief Returns the name of the object where the resource exists.
+     * \return Object name.
+    */
+    virtual const char* object_name() const = 0;
+
+    virtual M2MResource& get_parent_resource() const = 0;
+
+#ifndef DISABLE_BLOCK_MESSAGE
+    /**
+     * @brief Sets the function that is executed when this
+     * object receives a block-wise message.
+     * @param callback The function pointer that is called.
+     */
+    bool set_incoming_block_message_callback(incoming_block_message_callback callback);
+
+    /**
+     * @brief Sets the function that is executed when this
+     * object receives a GET request.
+     * This is called if resource values are stored on the application side.
+     * NOTE! Due to a limitation in the mbed-client-c library, a GET request can only contain data size up to 65KB.
+     * @param callback The function pointer that is called.
+     */
+    bool set_outgoing_block_message_callback(outgoing_block_message_callback callback);
+
+    /**
+     * \brief Returns the block message object.
+     * \return Block message.
+    */
+    M2MBlockMessage* block_message() const;
+
+#endif
+
+    /**
+     * @brief Sets the function that is executed when this object receives
+     * response(Empty ACK) for notification message.
+     * @param callback The function pointer that is called.
+     */
+    bool set_notification_sent_callback(notification_sent_callback callback) m2m_deprecated;
+
+    /**
+     * @brief Sets the function that is executed when this object receives
+     * response(Empty ACK) for notification message.
+     * @param callback The function pointer that is called.
+     */
+    bool set_notification_sent_callback(notification_sent_callback_2 callback) m2m_deprecated;
+
+    /**
+     * @brief Sets the function that is executed when this object receives
+     * response(Empty ACK) for notification message.
+     * @param callback The function pointer that is called.
+     */
+    bool set_notification_status_callback(notification_status_callback callback) m2m_deprecated;
+
+    /**
+     * @brief Sets the function that is executed when this object receives
+     * response(Empty ACK) for notification message.
+     * @param callback The function pointer that is called.
+     */
+    bool set_notification_status_callback(notification_status_callback_2 callback);
+
+    /**
+     * \brief Executes the function that is set in "set_notification_sent_callback".
+     */
+    void notification_sent();
+
+    /**
+     * \brief Executes the function that is set in "set_notification_status_callback".
+     */
+    void notification_status(const uint16_t msg_id, NotificationStatus status);
+
+    /**
+     * \brief Returns notification send status.
+     * \return Notification status.
+     */
+    M2MResourceBase::NotificationStatus notification_status() const;
+
+    /**
+     * \brief Clears the notification send status to initial state.
+     */
+    void clear_notification_status();
+
+    /**
+     * @brief Set the status whether resource value will be part of registration message.     *
+     * This only allowed for following resource types:
+     * STRING,
+     * INTEGER,
+     * FLOAT,
+     * BOOLEAN
+     * OPAQUE
+     *
+     * @param publish_value If true then resource value will be part of registration message.
+     */
+    void publish_value_in_registration_msg(bool publish_value);
+
+private:
+
+    void report();
+
+    void report_value_change();
+
+    bool has_value_changed(const uint8_t* value, const uint32_t value_len);
+
+    M2MResourceBase::ResourceType convert_data_type(M2MBase::DataType type) const;
+
+private:
+
+#ifndef DISABLE_BLOCK_MESSAGE
+    M2MBlockMessage     *_block_message_data;
+#endif
+
+    NotificationStatus    _notification_status : 2;
+
+    friend class Test_M2MResourceInstance;
+    friend class Test_M2MResource;
+    friend class Test_M2MObjectInstance;
+    friend class Test_M2MObject;
+    friend class Test_M2MDevice;
+    friend class Test_M2MSecurity;
+    friend class Test_M2MServer;
+    friend class Test_M2MNsdlInterface;
+    friend class Test_M2MFirmware;
+    friend class Test_M2MTLVSerializer;
+    friend class Test_M2MTLVDeserializer;
+};
+
+#endif // M2M_RESOURCE_BASE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mresourceinstance.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_RESOURCE_INSTANCE_H
+#define M2M_RESOURCE_INSTANCE_H
+
+#include "mbed-client/m2mresourcebase.h"
+
+
+/*! \file m2mresourceinstance.h
+ *  \brief M2MResourceInstance.
+ *  This class is the base class for mbed Client Resources. All defined
+ *  LWM2M resource models can be created based on it.
+ */
+class M2MBlockMessage;
+
+
+class M2MResource;
+
+class M2MResourceInstance : public M2MResourceBase {
+
+friend class M2MObjectInstance;
+friend class M2MResource;
+
+private: // Constructor and destructor are private
+         // which means that these objects can be created or
+         // deleted only through a function provided by the M2MObjectInstance.
+
+    M2MResourceInstance(M2MResource &parent,
+                        const lwm2m_parameters_s* s,
+                        M2MBase::DataType type);
+    /**
+     * \brief A constructor for creating a resource.
+     * \param resource_name The name of the resource.
+     * \param resource_type The type of the resource.
+     * \param type The resource data type of the object.
+     * \param object_name Object name where resource exists.
+     * \param path Path of the object like 3/0/1
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     */
+    M2MResourceInstance(M2MResource &parent,
+                        const String &resource_name,
+                        M2MBase::Mode mode,
+                        const String &resource_type,
+                        M2MBase::DataType type,
+                        char* path,
+                        bool external_blockwise_store,
+                        bool multiple_instance);
+
+    /**
+     * \brief A Constructor for creating a resource.
+     * \param resource_name The name of the resource.
+     * \param resource_type The type of the resource.
+     * \param type The resource data type of the object.
+     * \param value The value pointer of the object.
+     * \param value_length The length of the value pointer.
+     * \param value_length The length of the value pointer.
+     * \param object_name Object name where resource exists.
+     * \param path Path of the object like 3/0/1
+     * \param external_blockwise_store If true CoAP blocks are passed to application through callbacks
+     *        otherwise handled in mbed-client-c.
+     */
+    M2MResourceInstance(M2MResource &parent,
+                        const String &resource_name,
+                        M2MBase::Mode mode,
+                        const String &resource_type,
+                        M2MBase::DataType type,
+                        const uint8_t *value,
+                        const uint8_t value_length,
+                        char* path,
+                        bool external_blockwise_store,
+                        bool multiple_instance);
+
+    // Prevents the use of default constructor.
+    M2MResourceInstance();
+
+    // Prevents the use of assignment operator.
+    M2MResourceInstance& operator=( const M2MResourceInstance& /*other*/ );
+
+    // Prevents the use of copy constructor
+    M2MResourceInstance( const M2MResourceInstance& /*other*/ );
+
+    /**
+     * Destructor
+     */
+    virtual ~M2MResourceInstance();
+
+protected:
+    /**
+     * \brief Returns the owner object. Can return NULL if the object has no parent.
+     */
+    virtual M2MBase *get_parent() const;
+
+public:
+
+    /**
+     * \brief Returns the Observation Handler object.
+     * \return M2MObservationHandler object.
+    */
+    virtual M2MObservationHandler* observation_handler() const;
+
+    /**
+     * \brief Sets the observation handler
+     * \param handler Observation handler
+    */
+    virtual void set_observation_handler(M2MObservationHandler *handler);
+
+    /**
+     * \brief Parses the received query for a notification
+     * attribute.
+     * \return True if required attributes are present, else false.
+     */
+    virtual bool handle_observation_attribute(const char *query);
+
+
+    /**
+     * \brief Returns the instance ID of the object where the resource exists.
+     * \return Object instance ID.
+    */
+    virtual uint16_t object_instance_id() const;
+
+    /**
+     * \brief Returns the name of the object where the resource exists.
+     * \return Object name.
+    */
+    virtual const char* object_name() const;
+
+    /**
+     * \brief Get reference to the resource owning this resource instance.
+     * \return parent resource
+     */
+    virtual M2MResource& get_parent_resource() const;
+
+private:
+
+    // Parent resource which owns this resource instance
+    M2MResource &_parent_resource;
+
+    friend class Test_M2MResourceInstance;
+    friend class Test_M2MResource;
+    friend class Test_M2MObjectInstance;
+    friend class Test_M2MObject;
+    friend class Test_M2MDevice;
+    friend class Test_M2MSecurity;
+    friend class Test_M2MServer;
+    friend class Test_M2MNsdlInterface;
+    friend class Test_M2MFirmware;
+    friend class Test_M2MTLVSerializer;
+    friend class Test_M2MTLVDeserializer;
+};
+
+#endif // M2M_RESOURCE_INSTANCE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2msecurity.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_SECURITY_H
+#define M2M_SECURITY_H
+
+#include "mbed-client/m2mobject.h"
+
+// FORWARD DECLARATION
+class M2MResource;
+
+/*! \file m2msecurity.h
+ *  \brief M2MSecurity.
+ *  This class represents an interface for the Security Object model of the LWM2M framework.
+ *  It handles the security object instances and all corresponding
+ *  resources.
+ */
+
+class  M2MSecurity : public M2MObject {
+
+friend class M2MInterfaceFactory;
+friend class M2MNsdlInterface;
+
+public:
+
+    /**
+     * \brief An enum defining all resources associated with a
+     * Security Object in the LWM2M framework.
+     */
+    typedef enum {
+        M2MServerUri,
+        BootstrapServer,
+        SecurityMode,
+        PublicKey,
+        ServerPublicKey,
+        Secretkey,
+        SMSSecurityMode,
+        SMSBindingKey,
+        SMSBindingSecretKey,
+        M2MServerSMSNumber,
+        ShortServerID,
+        ClientHoldOffTime,
+        OpenCertificateChain,
+        CloseCertificateChain,
+        ReadDeviceCertificateChain
+    } SecurityResource;
+
+    /**
+     * \brief An enum defining the type of the security attribute
+     * used by the Security Object.
+     */
+    typedef enum {
+        SecurityNotSet = -1,
+        Psk = 0,
+        Certificate = 2,
+        NoSecurity = 3,
+        EST = 4
+    } SecurityModeType;
+
+    /**
+     * \brief An enum defining an interface operation that can be
+     * handled by the Security Object.
+     */
+    typedef enum {
+        M2MServer = 0x0,
+        Bootstrap = 0x1
+    } ServerType;
+
+private:
+
+    /**
+     * \brief Constructor
+     * \param server_type The type of the security object created. Either bootstrap or LWM2M server.
+     */
+    M2MSecurity(ServerType server_type);
+
+
+    /**
+     * \brief Destructor
+     */
+    virtual ~M2MSecurity();
+
+    // Prevents the use of default constructor.
+    M2MSecurity();
+
+    // Prevents the use of assignment operator.
+    M2MSecurity& operator=( const M2MSecurity& /*other*/ );
+
+    // Prevents the use of copy constructor
+    M2MSecurity( const M2MSecurity& /*other*/ );
+
+public:
+
+    /**
+     * \brief Get the singleton instance of M2MSecurity
+     */
+    static M2MSecurity* get_instance();
+
+    /**
+     * \brief Delete the singleton instance of M2MSecurity
+     */
+    static void delete_instance();
+
+    /**
+     * \brief Creates a new object instance.
+     * \param server_type Server type for new object instance.
+     * \return M2MObjectInstance if created successfully, else NULL.
+     */
+    M2MObjectInstance* create_object_instance(ServerType server_type);
+
+    /**
+     * \brief Remove all security object instances.
+     */
+    void remove_security_instances();
+
+    /**
+     * \brief Creates a new resource for a given resource enum.
+     * \param rescource With this function, the following resources can be created:
+     * ' BootstrapServer', 'SecurityMode', 'SMSSecurityMode',
+     * 'M2MServerSMSNumber', 'ShortServerID', 'ClientHoldOffTime'.
+     * \param value The value to be set on the resource, in integer format.
+     * \param instance_id Instance id of the security instance where resource should be created.
+     * \return M2MResource if created successfully, else NULL.
+     */
+    M2MResource* create_resource(SecurityResource rescource, uint32_t value, uint16_t instance_id);
+
+    /**
+     * \brief Deletes a resource with a given resource enum.
+     * Mandatory resources cannot be deleted.
+     * \param resource The resource to be deleted.
+     * \param instance_id Instance id of the security instance where resource should be deleted.
+     * \return True if deleted, else false.
+     */
+    bool delete_resource(SecurityResource rescource, uint16_t instance_id);
+
+    /**
+     * \brief Sets the value of a given resource enum.
+     * \param resource With this function, a value can be set for the following resources:
+     * 'M2MServerUri', 'SMSBindingKey', 'SMSBindingSecretKey'.
+     * \param value The value to be set on the resource, in string format.
+     * \param instance_id Instance id of the security instance where resource value should be set.
+     * \return True if successfully set, else false.
+     */
+    bool set_resource_value(SecurityResource resource,
+                            const String &value,
+                            uint16_t instance_id);
+
+    /**
+     * \brief Sets the value of a given resource enum.
+     * \param resource With this function, a value can be set for the following resourecs:
+     * 'BootstrapServer', 'SecurityMode', 'SMSSecurityMode',
+     * 'M2MServerSMSNumber', 'ShortServerID', 'ClientHoldOffTime'.
+     * \param value The value to be set on the resource, in integer format.
+     * \param instance_id Instance id of the security instance where resource value should be set.
+     * \return True if successfully set, else false.
+     */
+    bool set_resource_value(SecurityResource resource,
+                            uint32_t value,
+                            uint16_t instance_id);
+
+    /**
+     * \brief Sets the value of a given resource enum.
+     * \param resource With this function, a value can be set for the follwing resources:
+     * 'PublicKey', 'ServerPublicKey', 'Secretkey'.
+     * \param value The value to be set on the resource, in uint8_t format.
+     * \param length The size of the buffer value to be set on the resource.
+     * \param instance_id Instance id of the security instance where resource value should be set.
+     * \return True if successfully set, else false.
+     */
+    bool set_resource_value(SecurityResource resource,
+                            const uint8_t *value,
+                            const uint16_t length,
+                            uint16_t instance_id);
+
+    /**
+     * \brief Returns the value of a given resource enum, in string format.
+     * \param resource With this function, the following resources can return a value:
+     * 'M2MServerUri','SMSBindingKey', 'SMSBindingSecretKey'.
+     * \param instance_id Instance id of the security instance where resource value should be retrieved.
+     * \return The value associated with the resource. If the resource is not valid an empty string is returned.
+     */
+    String resource_value_string(SecurityResource resource, uint16_t instance_id) const;
+
+    /**
+     * \brief Populates the data buffer and returns the size of the buffer.
+     * \param resource With this function, the following resources can return a value:
+     * 'PublicKey', 'ServerPublicKey', 'Secretkey',
+     * 'OpenCertificateChain', 'CloseCertificateChain' 'ReadDeviceCertificateChain'.
+     * \param [OUT]data A copy of the data buffer that contains the value. The caller
+     * is responsible for freeing this buffer.
+     * \param instance_id Instance id of the security instance where resource value should be retrieve.
+     * \param buffer_len[IN/OUT] Length of the buffer.
+     * \return Error code, 0 on success otherwise < 0
+     */
+    int resource_value_buffer(SecurityResource resource,
+                              uint8_t *&data,
+                              uint16_t instance_id,
+                              size_t *buffer_len) const;
+
+    /**
+     * \brief Returns a pointer to the value and size of the buffer.
+     * \param resource With this function, the following resources can return a value:
+     * 'PublicKey', 'ServerPublicKey', 'Secretkey'.
+     * \param [OUT]data A pointer to the data buffer that contains the value.
+     * \param instance_id Instance id of the security instance where resource value should be retrieved.
+     * \return The size of the populated buffer.
+     */
+    uint32_t resource_value_buffer(SecurityResource resource,
+                                   const uint8_t *&data,
+                                   uint16_t instance_id) const;
+
+    /**
+     * \brief Returns the value of a given resource name, in integer format.
+     * \param resource With this function, the following resources can return a value:
+     * 'BootstrapServer', 'SecurityMode', 'SMSSecurityMode',
+     * 'M2MServerSMSNumber', 'ShortServerID', 'ClientHoldOffTime'.
+     * \param instance_id Instance id of the security instance where resource should be created.
+     * \return The value associated with the resource. If the resource is not valid 0 is returned.
+     */
+    uint32_t resource_value_int(SecurityResource resource,
+                                uint16_t instance_id) const;
+
+    /**
+     * \brief Returns whether a resource instance with a given resource enum exists or not
+     * \param resource Resource enum.
+     * \param instance_id Instance id of the security instance where resource should be checked.
+     * \return True if at least one instance exists, else false.
+     */
+    bool is_resource_present(SecurityResource resource,
+                             uint16_t instance_id) const;
+
+    /**
+     * \brief Returns the total number of resources for a security object.
+     * \param instance_id Instance id of the security instance where resources should be counted.
+     * \return The total number of resources.
+     */
+    uint16_t total_resource_count(uint16_t instance_id) const;
+
+    /**
+     * \brief Returns the type of the Security Object. It can be either
+     * Bootstrap or M2MServer.
+     * \param instance_id Instance id of the security instance where resource should be created.
+     * \return ServerType The type of the Security Object.
+     */
+    ServerType server_type(uint16_t instance_id) const;
+
+    /**
+     * \brief Returns first bootstrap or lwm2m server security object instance id.
+     * \param server_type Which server type security instance to return.
+     * \return Object instance id, or -1 if no such instance exists.
+     */
+    int32_t get_security_instance_id(ServerType server_type) const;
+
+    M2MResource* get_resource(SecurityResource resource, uint16_t instance_id = 0) const;
+private:
+
+
+    void clear_resources(uint16_t instance_id = 0);
+
+protected:
+    static M2MSecurity*          _instance;
+
+    friend class Test_M2MSecurity;
+    friend class Test_M2MInterfaceImpl;
+    friend class Test_M2MConnectionSecurityImpl;
+    friend class Test_M2MConnectionHandlerPimpl_linux;
+    friend class Test_M2MConnectionHandlerPimpl_mbed;
+    friend class Test_M2MConnectionSecurityPimpl;
+    friend class Test_M2MNsdlInterface;
+    friend class Test_M2MConnectionHandlerPimpl_classic;
+};
+
+#endif // M2M_SECURITY_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mserver.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_SERVER_H
+#define M2M_SERVER_H
+
+#include "mbed-client/m2mobject.h"
+
+// FORWARD DECLARATION
+class M2MResource;
+
+/*! \file m2mserver.h
+ *  \brief M2MServer.
+ *  This class represents an interface for the Server Object model of the LWM2M framework.
+ *  It handles the server object and all its corresponding
+ *  resources.
+ */
+
+class M2MServer : public M2MObject
+{
+
+friend class M2MInterfaceFactory;
+friend class M2MNsdlInterface;
+
+public:
+
+    /**
+     * \brief Am enum defining all resources associated with
+     * a Server Object in the LWM2M framework.
+     */
+    typedef enum {
+        ShortServerID,
+        Lifetime,
+        DefaultMinPeriod,
+        DefaultMaxPeriod,
+        Disable,
+        DisableTimeout,
+        NotificationStorage,
+        Binding,
+        RegistrationUpdate
+    }ServerResource;
+
+private:
+
+    /**
+     * \brief Constructor
+     */
+    M2MServer();
+
+
+    // Prevents the use of assignment operator.
+    M2MServer& operator=( const M2MServer& /*other*/ );
+
+    // Prevents the use of copy constructor
+    M2MServer( const M2MServer& /*other*/ );
+
+public:
+
+    /**
+     * \brief Destructor
+     */
+    virtual ~M2MServer();
+
+    /**
+     * \brief Creates a new resource for a given resource enum.
+     * \param resource With this function, a value can be set to the following resources:
+     *  'ShortServerID','Lifetime','DefaultMinPeriod','DefaultMaxPeriod','DisableTimeout',
+     *  'NotificationStorage'.
+     * \param value The value to be set on the resource, in integer format.
+     * \return M2MResource if created successfully, else NULL.
+     */
+    M2MResource* create_resource(ServerResource resource, uint32_t value);
+
+    /**
+     * \brief Creates a new resource for a given resource enum.
+     * \param resource With this function, the following resources can be created:
+     * 'Disable', 'RegistrationUpdate'
+     * \return M2MResource if created successfully, else NULL.
+     */
+    M2MResource* create_resource(ServerResource resource);
+
+    /**
+     * \brief Deletes the resource with the given resource enum.
+     * Mandatory resources cannot be deleted.
+     * \param resource The name of the resource to be deleted.
+     * \return True if deleted, else false.
+     */
+    bool delete_resource(ServerResource rescource);
+
+    /**
+     * \brief Sets the value of a given resource enum.
+     * \param resource With this function, a value can be set on the following resources: 
+     * 'Binding'.
+     * \param value The value to be set on the resource, in string format.
+     * \return True if successfully set, else false.
+     */
+    bool set_resource_value(ServerResource resource,
+                            const String &value);
+
+    /**
+     * \brief Sets the value of a given resource enum.
+     * \param resource With this function, a value can be set to the following resources:
+     *  'ShortServerID','Lifetime','DefaultMinPeriod','DefaultMaxPeriod','DisableTimeout',
+     *  'NotificationStorage'.
+     * \param value The value to be set on the resource, in integer format.
+     * \return True if successfully set, else false.
+     */
+    bool set_resource_value(ServerResource resource,
+                            uint32_t value);
+    /**
+     * \brief Returns the value of the given resource enum, in string format.
+     * \param resource With this function, the following resources can return a value:
+     * 'Binding'.
+     * \return The value associated with the resource. If the resource is not valid an empty string is returned.
+     */
+    String resource_value_string(ServerResource resource) const;
+
+    /**
+     * \brief Returns the value of a given resource name, in integer format.
+     * \param resource With this function, the following resources can return a value:
+     *  'ShortServerID','Lifetime','DefaultMinPeriod','DefaultMaxPeriod','DisableTimeout',
+     *  'NotificationStorage'
+     * \return The value associated with the resource. If the resource is not valid -1 is returned.
+     */
+    uint32_t resource_value_int(ServerResource resource) const;
+
+    /**
+     * \brief Returns whether the resource instance with the given resource enum exists or not.
+     * \param resource Resource enum.
+     * \return True if at least one instance exists, else false.
+     */
+    bool is_resource_present(ServerResource resource)const;
+
+    /**
+     * \brief Returns the total number of resources for the server object.
+     * \return The total number of resources.
+     */
+    uint16_t total_resource_count()const;
+
+private:
+
+    M2MResource* get_resource(ServerResource res) const;
+
+
+private:
+
+    M2MObjectInstance*    _server_instance;
+
+    friend class Test_M2MServer;
+    friend class Test_M2MNsdlInterface;
+};
+
+#endif // M2M_SERVER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mstring.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_STRING_H
+#define M2M_STRING_H
+
+#include <stddef.h> // size_t
+#include <stdint.h>
+
+class Test_M2MString;
+
+namespace m2m
+{
+
+/*! \file m2mstring.h
+* \brief A simple C++ string class, used as replacement for std::string.
+   */
+  class String
+  {
+    char* p;           ///< The data.
+    size_t allocated_;  ///< The allocated memory size (including trailing NULL).
+    size_t size_;       ///< The currently used memory size (excluding trailing NULL).
+
+  public:
+    typedef size_t size_type;
+    static const size_type npos;
+
+    String();
+    ~String();
+    String(const String&);
+    String(const char*);
+    String(const char*, size_t);
+
+    String& operator=(const char*);
+    String& operator=(const String&);
+
+    String& operator+=(const String&);
+    String& operator+=(const char*);
+    String& operator+=(char);
+    void push_back(char);
+
+    bool operator==(const char*) const;
+    bool operator==(const String&) const;
+
+    void clear();       // Set the string to empty (memory remains reserved).
+
+    size_type size()   const   { return size_; }   ///< size without terminating NULL
+    size_type length() const   { return size_; }   ///< as size()
+
+    size_type capacity() const { return allocated_-1; }
+
+    bool empty() const    { return size_ == 0; }
+
+    const char* c_str() const { return p; } ///< raw data
+
+    /** Reserve internal string memory so that n characters can be put into the
+        string (plus 1 for the NULL char). If there is already enough memory,
+        nothing happens, if not, the memory is realloated to exactly this
+        amount.
+        */
+    void reserve( size_type n);
+
+    /** Resize string. If n is less than the current size, the string is truncated.
+        If n is larger, the memory is reallocated to exactly this amount, and
+        the additional characters are NULL characters.
+        */
+    void resize( size_type n);
+
+    /** Resize string. If n is less than the current size, the string is truncated.
+        If n is larger, the memory is reallocated to exactly this amount, and
+        the additional characters are c characters.
+        */
+    void resize( size_type n, char c);
+
+    /// swap contents
+    void swap( String& );
+
+    String substr(const size_type pos, size_type length) const;
+
+    // unchecked access:
+    char& operator[](const size_type i)       { return p[i]; }
+    char operator[](const size_type i) const { return p[i]; }
+    // checked access:
+    char at(const size_type i) const;
+
+    /// erase len characters at position pos
+    String& erase(size_type pos, size_type len);
+    /// Append n characters of a string
+    String& append(const char* str, size_type n);
+
+    // Append n characters of a non-zero-terminated string
+    // (in contrast with other append(), which performs strlen() for the given string).
+    String& append_raw(const char*, size_type);
+
+    // convert int to ascii and append it to end of string
+    void append_int(int);
+
+    int compare( size_type pos, size_type len, const String& str ) const;
+    int compare( size_type pos, size_type len, const char*   str ) const;
+
+    int find_last_of(char c) const;
+
+    static uint8_t* convert_integer_to_array(int64_t value, uint8_t &size, const uint8_t *array = NULL, const uint32_t array_size = 0);
+    static int64_t convert_array_to_integer(const uint8_t *value, const uint32_t size);
+
+  private:
+    // reallocate the internal memory
+    void new_realloc( size_type n);
+    char* strdup(const char* other);
+
+    friend class ::Test_M2MString;
+
+  };
+  // class
+
+  bool operator<(const String&, const String&);
+
+  void reverse(char s[], uint32_t length);
+
+  uint32_t itoa_c (int64_t n, char s[]);
+} // namespace
+
+
+#endif // M2M_STRING_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mstringbuffer.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef __STRING_BUFFER_H__
+#define __STRING_BUFFER_H__
+
+#include "mbed-client/m2mstringbufferbase.h"
+
+#include <assert.h>
+#include <stddef.h>
+
+template <int SIZE>
+class StringBuffer : private StringBufferBase
+{
+public:
+    /**
+     * Initialize a empty buffer with zero length and zero content.
+     */
+    inline StringBuffer();
+
+    //
+    // This is not implemented on purpose, as the given string may conflict with
+    // templated size. Otoh, if we used compile time assert, the overflow
+    // could be prevented at compile time.
+    //
+    // inline StringBuffer(const char *initial_string);
+
+    /**
+     * Verify, if the buffer has still room for given amount of bytes.
+     * Note: the given size value must include the zero terminator as it is not
+     * implicitly taken into account for.
+     */
+    bool ensure_space(size_t required_size) const;
+
+    /**
+     * Append given char to end of string.
+     * Return false if the buffer would overflow, true otherwise.
+     */
+    bool append(char data);
+
+    /**
+     * Append given zero terminated string to end of buffer.
+     *
+     * Return false if the buffer would overflow, true otherwise.
+     *
+     * Note: the whole string, including the zero terminator must fit
+     * to buffer or the append operation is not done and false is returned.
+     */
+    bool append(const char *data);
+
+    /**
+     * Append given block of chars to end of buffer.
+     *
+     * Return false if the buffer would overflow, true otherwise.
+     *
+     * Note: the whole string, including the zero terminator must fit
+     * to buffer or the append operation is not done and false is returned.
+     */
+    bool append(const char *data, size_t data_len);
+
+    /**
+     * Convert given uint16_t into string representation and add it to the
+     * end of buffer.
+     *
+     * Note: the whole string, including the zero terminator must fit
+     * to buffer or the append operation is not done and false is returned.
+     */
+    bool append_int(uint16_t data);
+
+    /**
+     * Get the amount of bytes added to the buffer.
+     *
+     * Note: the size does not include the terminating zero, so this is
+     * functionally equal to strlen().
+     */
+    inline size_t get_size() const;
+
+    // API functionality copied from m2mstring:
+
+    // find the index of last occurance of given char in string, or negative if not found
+    int find_last_of(char search_char) const;
+
+    /**
+     * Get a read only pointer to the data.
+     */
+    inline const char* c_str() const;
+
+    // Add this only if needed
+    //inline char* c_str();
+private:
+    char _buff[SIZE];
+};
+
+template <int SIZE>
+inline StringBuffer<SIZE>::StringBuffer()
+{
+    // actually a assert_compile() would be better as this is completely a code problem
+    assert(SIZE > 0);
+
+    _buff[0] = '\0';
+}
+
+template <int SIZE>
+bool StringBuffer<SIZE>::ensure_space(size_t required_size) const
+{
+    return StringBufferBase::ensure_space(SIZE, required_size);
+}
+
+template <int SIZE>
+bool StringBuffer<SIZE>::append(const char *data)
+{
+    return StringBufferBase::append(_buff, SIZE, data);
+}
+
+template <int SIZE>
+bool StringBuffer<SIZE>::append(const char *data, size_t data_len)
+{
+    return StringBufferBase::append(_buff, SIZE, data, data_len);
+}
+
+template <int SIZE>
+inline bool StringBuffer<SIZE>::append(char data)
+{
+    return StringBufferBase::append(_buff, SIZE, data);
+}
+
+template <int SIZE>
+bool StringBuffer<SIZE>::append_int(uint16_t data)
+{
+    return StringBufferBase::append_int(_buff, SIZE, data);
+}
+
+template <int SIZE>
+int StringBuffer<SIZE>::find_last_of(char search_char) const
+{
+    return StringBufferBase::find_last_of(_buff, search_char);
+}
+
+template <int SIZE>
+inline const char* StringBuffer<SIZE>::c_str() const
+{
+    return _buff;
+}
+
+template <int SIZE>
+inline size_t StringBuffer<SIZE>::get_size() const
+{
+    return _curr_size;
+}
+
+#endif // !__STRING_BUFFER_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mstringbufferbase.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef __STRING_BUFFER_BASE_H__
+#define __STRING_BUFFER_BASE_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+class StringBufferBase
+{
+protected:
+
+    // inline version of this produces smaller code
+    inline StringBufferBase();
+
+    // all the docs are at template level, as it is the only public API
+
+    bool ensure_space(size_t max_size, size_t required_size) const;
+
+    bool append(char *buff, size_t max_size, char data);
+
+    bool append(char *buff, size_t max_size, const char *data);
+
+    bool append(char *buff, size_t max_size, const char *data, size_t data_len);
+
+    bool append_int(char *buff, size_t max_size, uint16_t data);
+
+    int find_last_of(const char *buff, char search_char) const;
+
+protected:
+    //const size_t _max_size;
+    size_t _curr_size;
+};
+
+inline StringBufferBase::StringBufferBase() : _curr_size(0)
+{
+}
+
+#endif // !__STRING_BUFFER_BASE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mtimer.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_TIMER_H
+#define M2M_TIMER_H
+
+#include <stdint.h>
+#include "mbed-client/m2mtimerobserver.h"
+
+class M2MTimerPimpl;
+
+/*! \file m2mtimer.h
+* \brief M2MTimer.
+* Timer class for mbed client.
+*/
+class M2MTimer
+{
+private:
+    // Prevents the use of assignment operator
+    M2MTimer& operator=(const M2MTimer& other);
+
+    // Prevents the use of copy constructor
+    M2MTimer(const M2MTimer& other);
+
+public:
+
+    /**
+    * Constructor.
+    */
+    M2MTimer(M2MTimerObserver& observer);
+
+    /**
+    * Destructor.
+    */
+    ~M2MTimer();
+
+    /**
+    * \brief Starts the timer.
+    * \param interval The timer interval in milliseconds.
+    * \param single_shot Defines whether the timer is ticked once or restarted every time at expiry.
+    */
+    void start_timer(uint64_t interval, M2MTimerObserver::Type type, bool single_shot = true);
+
+    /**
+     * \brief Starts the timer in DTLS manner.
+     * \param intermediate_interval The intermediate interval to use, must be smaller than total (usually 1/4 of total).
+     * \param total_interval The total interval to use; This is the timeout value of a DTLS packet.
+     * \param type The type of the timer.
+     */
+    void start_dtls_timer(uint64_t intermediate_interval, uint64_t total_interval, M2MTimerObserver::Type type = M2MTimerObserver::Dtls);
+
+    /**
+    * \brief Stops the timer.
+    * This cancels the ongoing timer.
+    */
+    void stop_timer();
+
+    /**
+     * \brief Checks if the intermediate interval has passed.
+     * \return True if the interval has passed, else false.
+     */
+    bool is_intermediate_interval_passed();
+
+    /**
+     * \brief Checks if the total interval has passed.
+     * \return True if the interval has passed, else false.
+     */
+    bool is_total_interval_passed();
+
+private:
+
+    M2MTimerObserver&   _observer;
+    M2MTimerPimpl       *_private_impl;
+    friend class Test_M2MTimerImpl_linux;
+};
+
+#endif // M2M_TIMER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mtimerobserver.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_TIMER_OBSERVER_H
+#define M2M_TIMER_OBSERVER_H
+
+/*! \file m2mtimerobserver.h
+ *  \brief M2MTimerObserver.
+ *  Observer class for indicating the timer expiry to the parent class.
+ */
+class M2MTimerObserver
+{
+public:
+    /**
+      * \enum Defines the types of timer
+      * that can be created for mbed Client.
+      */
+    typedef enum {
+        Notdefined,
+        Registration,
+        NsdlExecution,
+        PMinTimer,
+        PMaxTimer,
+        Dtls,
+        QueueSleep,
+        RetryTimer,
+        BootstrapFlowTimer,
+        RegistrationFlowTimer
+    }Type;
+
+    /**
+    * \brief Indicates that the timer has expired.
+    * \param type The type of the timer that has expired.
+    */
+    virtual void timer_expired(M2MTimerObserver::Type type =
+                               M2MTimerObserver::Notdefined) = 0;
+};
+
+#endif // M2M_TIMER_OBSERVER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/m2mvector.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2015-2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifndef M2M_VECTOR_H
+#define M2M_VECTOR_H
+
+/*! \file m2mvector.h
+* \brief A simple C++ Vector class, used as replacement for std::vector.
+*/
+
+
+namespace m2m
+{
+
+template <typename ObjectTemplate>
+
+class Vector
+{
+  public:
+    explicit Vector( int init_size = MIN_CAPACITY)
+            : _size(0),
+              _capacity((init_size >= MIN_CAPACITY) ? init_size : MIN_CAPACITY) {
+        _object_template = new ObjectTemplate[ _capacity ];
+    }
+
+    Vector(const Vector & rhs ): _object_template(0) {
+        operator=(rhs);
+    }
+ 
+    ~Vector() {
+        delete [] _object_template;
+    }
+
+    const Vector & operator=(const Vector & rhs) {
+        if(this != &rhs) {
+            delete[] _object_template;
+            _size = rhs.size();
+            _capacity = rhs._capacity;
+
+            _object_template = new ObjectTemplate[capacity()];
+            for(int k = 0; k < size(); k++) {
+                _object_template[k] = rhs._object_template[k];
+            }
+        }
+        return *this;
+    }
+
+    void resize(int new_size) {
+        if(new_size > _capacity) {
+            reserve(new_size * 2 + 1);
+        }
+        _size = new_size;
+    }
+
+    void reserve(int new_capacity) {
+        if(new_capacity < _size) {
+            return;
+        }
+        ObjectTemplate *old_array = _object_template;
+
+        _object_template = new ObjectTemplate[new_capacity];
+        for(int k = 0; k < _size; k++) {
+            _object_template[k] = old_array[k];
+        }
+        _capacity = new_capacity;
+        delete [] old_array;
+    }
+
+    ObjectTemplate & operator[](int idx) {
+        return _object_template[idx];
+    }
+
+    const ObjectTemplate& operator[](int idx) const {
+        return _object_template[idx];
+    }
+
+    bool empty() const{
+        return size() == 0;
+    }
+
+    int size() const {
+        return _size;
+    }
+
+    int capacity() const {
+        return _capacity;
+    }
+
+    void push_back(const ObjectTemplate& x) {
+        if(_size == _capacity) {
+            reserve(2 * _capacity + 1);
+        }
+        _object_template[_size] = x;
+        _size++;
+    }
+
+    void pop_back() {
+        _size--;
+    }
+
+    void clear() {
+        _size = 0;
+    }
+
+    const ObjectTemplate& back() const {
+        return _object_template[_size - 1];
+    }
+
+    typedef ObjectTemplate* iterator;
+    typedef const ObjectTemplate* const_iterator;
+
+    iterator begin() {
+        return &_object_template[0];
+    }
+
+    const_iterator begin() const {
+        return &_object_template[0];
+    }
+
+    iterator end() {
+        return &_object_template[_size];
+    }
+
+    const_iterator end() const {
+        return &_object_template[_size];
+    }
+
+    void erase(int position) {
+        if(position < _size) {
+            for(int k = position; k + 1 < _size; k++) {
+                _object_template[k] = _object_template[k + 1];
+            }
+            _size--;
+        }
+    }
+
+    enum {
+        MIN_CAPACITY = 1
+    };
+
+  private:
+    int                 _size;
+    int                 _capacity;
+    ObjectTemplate*     _object_template;
+};
+
+} // namespace
+
+#endif // M2M_VECTOR_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed-client/uriqueryparser.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef URIQUERYPARSER_H_
+#define URIQUERYPARSER_H_
+
+
+/**
+ * @brief Parse query parameter from uri and return size of parameter value and pointer to value within
+ *        uri.
+ *
+ * Example usage:
+ * char *value_ptr = NULL;
+ * ssize_t value_len = parse_query_parameter_value_from_uri("http://www.myquery.com?someparameter=value", "someparameter", &value_ptr);
+ * will result in value_len = 5 and value_ptr = "value"
+ *
+ * @param uri uri to parse.
+ * @param parameter_name, parameter name to parse from query.
+ * @param parameter_value[OUT], pointer to parameter value, NULL if parameter does not exist.
+ * @return size of parameter value, -1 if parameter does not exist in uri
+ */
+int parse_query_parameter_value_from_uri(const char *uri, const char *parameter_name, const char **parameter_value);
+
+/**
+ * @brief Parse query parameter from query and return size of parameter value and pointer to value within
+ *        query.
+ *
+ * Example usage:
+ * char *value_ptr = NULL;
+ * ssize_t value_len = parse_query_parameter_value("someparameter=value&param2=second", "param2", &value_ptr);
+ * will result in value_len = 6 and value_ptr = "second"
+ *
+ * @param query query to parse.
+ * @param parameter_name, parameter name to parse from query.
+ * @param parameter_value[OUT], pointer to parameter value, NULL if parameter does not exist.
+ * @return size of parameter value, -1 if parameter does not exist in query
+ */
+int parse_query_parameter_value_from_query(const char *uri, const char *parameter_name, const char **parameter_value);
+
+
+#endif /* URIQUERYPARSER_H_ */
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/mbed_lib.json	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,27 @@
+{
+    "name": "mbed-client",
+    "config": {
+        "event-loop-size": 1024,
+        "reconnection-count": 3,
+        "reconnection-interval": 5,
+        "tcp-keepalive-interval": 90,
+        "disable-bootstrap-feature": null,
+        "coap-disable-obs-feature":null,
+        "reconnection-loop": 1,
+        "dns-use-thread": null,
+        "dtls_peer_max_timeout": null,
+        "sn-coap-max-blockwise-payload-size" : null,
+        "sn-coap-duplication-max-msgs-count": null,
+        "sn-coap-max-incoming-message-size": null,
+        "sn-coap-resending-queue-size-msgs": null,
+        "sn-coap-resending-queue-size-bytes": null,
+        "sn-coap-blockwise-max-time-data-stored": null,
+        "disable-interface-description": null,
+        "disable-resource-type": null,
+        "disable-delayed-response": null,
+        "disable-block-message": null
+    },
+    "macros" : [
+        "MBED_CLIENT_C_NEW_API"
+    ]
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/eventdata.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef EVENT_DATA_H
+#define EVENT_DATA_H
+
+#include "mbed-client/m2mvector.h"
+
+//FORWARD DECLARATION
+class M2MObject;
+
+
+typedef Vector<M2MObject *> M2MObjectList;
+
+class M2MSecurity;
+
+class EventData
+{
+public:
+    virtual ~EventData() {}
+};
+
+class M2MSecurityData : public EventData
+{
+public:
+    M2MSecurityData()
+    :_object(NULL){}
+    virtual ~M2MSecurityData() {}
+    M2MSecurity  *_object;
+};
+
+class ResolvedAddressData : public EventData
+{
+public:
+    ResolvedAddressData()
+    :_address(NULL),
+    _port(0){}
+    virtual ~ResolvedAddressData() {}
+    const M2MConnectionObserver::SocketAddress    *_address;
+    uint16_t                                       _port;
+};
+
+class ReceivedData : public EventData
+{
+public:
+    ReceivedData()
+    :_data(NULL),
+    _size(0),
+    _port(0),
+    _address(NULL){}
+    virtual ~ReceivedData() {}
+    uint8_t                                         *_data;
+    uint16_t                                        _size;
+    uint16_t                                        _port;
+    const M2MConnectionObserver::SocketAddress      *_address;
+};
+
+class M2MRegisterData : public EventData
+{
+public:
+    M2MRegisterData()
+    :_object(NULL){}
+    virtual ~M2MRegisterData() {}
+    M2MSecurity     *_object;
+    M2MBaseList    _base_list;
+};
+
+class M2MUpdateRegisterData : public EventData
+{
+public:
+    M2MUpdateRegisterData()
+    :_object(NULL),
+    _lifetime(0){}
+    virtual ~M2MUpdateRegisterData() {}
+    M2MSecurity     *_object;
+    uint32_t        _lifetime;
+    M2MBaseList    _base_list;
+};
+
+
+#endif //EVENT_DATA_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mcallbackstorage.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2017 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef __M2M_CALLBACK_STORAGE_H__
+#define __M2M_CALLBACK_STORAGE_H__
+
+#include "mbed-client/m2mvector.h"
+
+class M2MBase;
+class M2MCallbackAssociation;
+class M2MCallbackStorage;
+
+typedef m2m::Vector<M2MCallbackAssociation> M2MCallbackAssociationList;
+
+// XXX: this should not be visible for client code
+class M2MCallbackAssociation
+{
+public:
+
+    // Types of callbacks stored as "void*" in the _callback variable.
+    // Note: the FPn<> -types are actually stored as pointers to object instances,
+    // which needs to be handled externally when fetching and deleting the callbacks.
+    enum M2MCallbackType {
+        // typedef FP1<void, const char*> value_updated_callback;
+        M2MBaseValueUpdatedCallback,
+
+        // typedef void(*value_updated_callback2) (const char* object_name);
+        M2MBaseValueUpdatedCallback2,
+
+        // typedef FP1<void,void*> execute_callback;
+        M2MResourceInstanceExecuteCallback,
+
+        //typedef void(*execute_callback_2) (void *arguments);
+        M2MResourceInstanceExecuteCallback2,
+
+        // typedef FP1<void, M2MBlockMessage *> incoming_block_message_callback;
+        M2MResourceInstanceIncomingBlockMessageCallback,
+
+        // typedef FP3<void, const String &, uint8_t *&, uint32_t &> outgoing_block_message_callback;
+        M2MResourceInstanceOutgoingBlockMessageCallback,
+
+        // class M2MResourceCallback
+        M2MResourceInstanceM2MResourceCallback,
+
+        // typedef FP0<void> notification_sent_callback;
+        M2MResourceInstanceNotificationSentCallback,
+
+        // typedef void(*notification_sent_callback_2) (void);
+        M2MResourceInstanceNotificationSentCallback2,
+
+        // typedef FP2<void, const uint16_t, const M2MResourceBase::NotificationStatus> notification_status_callback;
+        M2MResourceInstanceNotificationStatusCallback,
+
+        // typedef void(*notification_status_callback_2) (const uint16_t msg_id, const M2MResourceBase::NotificationStatus status);
+        M2MResourceInstanceNotificationStatusCallback2,
+
+        // typedef void(*notification_delivery_status_cb) (const M2MBase& base,
+        // const M2MBase::NotificationDeliveryStatus status, void *client_args);
+        M2MBaseNotificationDeliveryStatusCallback,
+
+        // typedef void(*value_set_callback) (const M2MResourceBase *resource,
+        // uint8_t *value, const uint32_t value_length);
+        M2MResourceBaseValueSetCallback,
+
+        // typedef size_t(*read_resource_value_callback) (const M2MResourceBase& resource,
+        // void *buffer, void *client_args);
+        M2MResourceBaseValueReadCallback,
+
+        // typedef bool(*write_resource_value_callback) (const M2MResourceBase& resource,
+        // const uint8_t *buffer, const size_t buffer_size, void *client_args);
+        M2MResourceBaseValueWriteCallback
+    };
+
+    /**
+     * Dummy constructor which does not initialize any predictable value to members,
+     * needed for array instantiation. Please use the parameterized constructor for real work.
+     */
+    M2MCallbackAssociation();
+
+    M2MCallbackAssociation(const M2MBase *object, void *callback, M2MCallbackType type, void *client_args);
+
+public:
+    /** Object, where the callback is associated to. This is used as key on searches, must not be null. */
+    const M2MBase *_object;
+
+    /**
+     * Callback pointer, actual data type of the is dependent of _type.
+     *
+     * We could also use eg. a union with specific pointer types to avoid ugly casts, but that would
+     * then require a type-specific get_callback_<type>() to avoid casts on caller side too - unless
+     * the get_callback() would return this object and the caller would access the union._callback_<type>
+     * variable according to the _type.
+     */
+    void *_callback;
+
+    /** Type of the data _callback points to and needed for interpreting the data in it. */
+    M2MCallbackType _type;
+
+    void *_client_args;
+};
+
+
+class M2MCallbackStorage
+{
+public:
+
+    ~M2MCallbackStorage();
+
+    // get the shared instance of the storage.
+    // TODO: tie this' instance to the nsdlinterface or similar class instead, as it would help
+    // to manage the lifecycle of the object. This would also remove the need for these static methods.
+    static M2MCallbackStorage *get_instance();
+
+    // utility for deleting the singleton instance, used on unit test and on application exit
+    static void delete_instance();
+
+    static bool add_callback(const M2MBase &object,
+                             void *callback,
+                             M2MCallbackAssociation::M2MCallbackType type,
+                             void *client_args = 0);
+
+    // remove all callbacks attached for given object
+    static void remove_callbacks(const M2MBase &object);
+
+    // remove callback if one exists, return old value of it
+    static void* remove_callback(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type);
+
+    // XXX: needed for protecting the vector during iteration, but that would add a dependency on PAL here
+    // void lock();
+    // void release();
+
+    // XXX: const_iterator would be nicer
+    //int get_callback(const M2MBase &object, void &*callback, M2MCallbackType type);
+
+    static bool does_callback_exist(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type);
+
+    static void* get_callback(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type);
+
+    static M2MCallbackAssociation* get_association_item(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type);
+    // XXX: this is actually not needed unless the client has multiple callbacks per object and type.
+    inline const M2MCallbackAssociationList& get_callbacks() const;
+
+private:
+    bool does_callback_exist(const M2MBase &object, void *callback, M2MCallbackAssociation::M2MCallbackType type) const;
+    void do_remove_callbacks(const M2MBase &object);
+    void* do_remove_callback(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type);
+    bool do_add_callback(const M2MBase &object, void *callback, M2MCallbackAssociation::M2MCallbackType type, void *client_args);
+    void* do_get_callback(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type) const;
+
+    M2MCallbackAssociation* do_get_association_item(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type) const;
+
+private:
+
+    /**
+     * Currently there is only one storage object, which is shared between all the interfaces and
+     * M2M objects.
+     */
+    static M2MCallbackStorage *_static_instance;
+
+    /**
+     * Callback objects stored. There combination of <object>+<type> is used on searches and
+     * the code does not fully support for adding multiple callbacks for <object>+<type> -pair.
+     * But that should not be too hard if the feature was added to M2M object API too, it just
+     * requires the M2M objects to iterate through the callbacks associated to it, not just call
+     * the get_callback(<object>,<type>) and call the first one.
+     */
+    M2MCallbackAssociationList _callbacks;
+};
+
+inline const M2MCallbackAssociationList& M2MCallbackStorage::get_callbacks() const
+{
+    return _callbacks;
+}
+
+#endif // !__M2M_CALLBACK_STORAGE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2minterfaceimpl.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,572 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_INTERFACE_IMPL_H
+#define M2M_INTERFACE_IMPL_H
+
+#include "mbed-client/m2minterface.h"
+#include "mbed-client/m2mserver.h"
+#include "mbed-client/m2mconnectionobserver.h"
+#include "mbed-client/m2mconnectionsecurity.h"
+#include "include/m2mnsdlobserver.h"
+#include "include/m2mnsdlinterface.h"
+#include "mbed-client/m2mtimerobserver.h"
+#include "mbed-client/m2mtimer.h"
+#include "mbed-client/m2mconnectionhandler.h"
+#include "mbed-client/m2mconstants.h"
+
+//FORWARD DECLARATION
+class M2MConnectionSecurity;
+class EventData;
+class M2MUpdateRegisterData;
+/**
+ *  @brief M2MInterfaceImpl.
+ *  This class implements handling of all mbed Client Interface operations
+ *  defined in OMA LWM2M specifications.
+ *  This includes Bootstrapping, Client Registration, Device Management &
+ *  Service Enablement and Information Reporting.
+ */
+
+class  M2MInterfaceImpl : public M2MInterface,
+                          public M2MNsdlObserver,
+                          public M2MConnectionObserver,
+                          public M2MTimerObserver
+{
+private:
+    // Prevents the use of assignment operator by accident.
+    M2MInterfaceImpl& operator=( const M2MInterfaceImpl& /*other*/ );
+
+    // Prevents the use of copy constructor by accident
+    M2MInterfaceImpl( const M2MInterfaceImpl& /*other*/ );
+
+friend class M2MInterfaceFactory;
+
+private:
+
+    /**
+     * @brief Constructor
+     * @param observer, Observer to pass the event callbacks for various
+     * interface operations.
+     * @param endpoint_name Endpoint name of the client.
+     * @param endpoint_type Endpoint type of the client.
+     * @param life_time Life time of the client in seconds
+     * @param listen_port Listening port for the endpoint, default is 8000.
+     * @param domain Domain of the client.
+     * @param mode Binding mode of the client, default is UDP
+     * @param stack Network stack to be used for connection, default is LwIP_IPv4.
+     * @param context_address Context address, default is empty.
+     */
+    M2MInterfaceImpl(M2MInterfaceObserver& observer,
+                     const String &endpoint_name,
+                     const String &endpoint_type,
+                     const int32_t life_time,
+                     const uint16_t listen_port,
+                     const String &domain = "",
+                     BindingMode mode = M2MInterface::NOT_SET,
+                     M2MInterface::NetworkStack stack = M2MInterface::LwIP_IPv4,
+                     const String &context_address = "");
+
+public:
+
+    /**
+     * @brief Destructor
+     */
+    virtual ~M2MInterfaceImpl();
+
+    /**
+     * @brief Initiates bootstrapping of the client with the provided Bootstrap
+     * server information.
+     * @param security_object Security object which contains information
+     * required for successful bootstrapping of the client.
+     */
+    virtual void bootstrap(M2MSecurity *security);
+
+    /**
+     * @brief Cancels on going bootstrapping operation of the client. If the client has
+     * already successfully bootstrapped then this function deletes existing
+     * bootstrap information from the client.
+     */
+    virtual void cancel_bootstrap();
+
+    /**
+     * @brief Finishes on going bootstrap in cases where client is the one to finish it.
+     */
+    virtual void finish_bootstrap();
+
+    /**
+     * @brief Initiates registration of the provided Security object to the
+     * corresponding LWM2M server.
+     * @param security_object Security object which contains information
+     * required for registering to the LWM2M server.
+     * If client wants to register to multiple LWM2M servers then it has call
+     * this function once for each of LWM2M server object separately.
+     * @param object_list Objects which contains information
+     * which the client want to register to the LWM2M server.
+     */
+    virtual void register_object(M2MSecurity *security_object, const M2MBaseList &list);
+
+    /**
+     * @brief Initiates registration of the provided Security object to the
+     * corresponding LWM2M server.
+     * @param security_object Security object which contains information
+     * required for registering to the LWM2M server.
+     * If client wants to register to multiple LWM2M servers then it has call
+     * this function once for each of LWM2M server object separately.
+     * @param object_list Objects which contains information
+     * which the client want to register to the LWM2M server.
+     */
+    virtual void register_object(M2MSecurity *security_object, const M2MObjectList &object_list);
+
+    /**
+     * @brief Updates or refreshes the client's registration on the LWM2M
+     * server.
+     * @param security_object Security object from which the device object
+     * needs to update registration, if there is only one LWM2M server registered
+     * then this parameter can be NULL.
+     * @param lifetime Lifetime for the endpoint client in seconds.
+     */
+    virtual void update_registration(M2MSecurity *security_object, const uint32_t lifetime = 0);
+
+    /**
+     * @brief Updates or refreshes the client's registration on the LWM2M
+     * server. Use this function to publish new objects to LWM2M server.
+     * @param security_object The security object from which the device object
+     * needs to update the registration. If there is only one LWM2M server registered,
+     * this parameter can be NULL.
+     * @param object_list Objects that contain information about the
+     * client attempting to register to the LWM2M server.
+     * @param lifetime The lifetime of the endpoint client in seconds. If the same value
+     * has to be passed, set the default value to 0.
+     */
+    virtual void update_registration(M2MSecurity *security_object, const M2MBaseList &list,
+                                     const uint32_t lifetime = 0);
+
+    /**
+     * @brief Updates or refreshes the client's registration on the LWM2M
+     * server. Use this function to publish new objects to LWM2M server.
+     * @param security_object The security object from which the device object
+     * needs to update the registration. If there is only one LWM2M server registered,
+     * this parameter can be NULL.
+     * @param object_list Objects that contain information about the
+     * client attempting to register to the LWM2M server.
+     * @param lifetime The lifetime of the endpoint client in seconds. If the same value
+     * has to be passed, set the default value to 0.
+     */
+    virtual void update_registration(M2MSecurity *security_object, const M2MObjectList &object_list,
+                                     const uint32_t lifetime = 0);
+
+    /**
+     * @brief Unregisters the registered object from the LWM2M server
+     * @param security_object Security object from which the device object
+     * needs to be unregistered. If there is only one LWM2M server registered
+     * this parameter can be NULL.
+     */
+    virtual void unregister_object(M2MSecurity* security = NULL);
+
+    /**
+     * @brief Sets the function which will be called indicating client
+     * is going to sleep when the Binding mode is selected with Queue mode.
+     * @param callback A function pointer that will be called when client
+     * goes to sleep.
+     */
+    virtual void set_queue_sleep_handler(callback_handler handler);
+
+    /**
+     * @brief Sets the network interface handler that is used by client to connect
+     * to a network over IP.
+     * @param handler A network interface handler that is used by client to connect.
+     *  This API is optional but provides a mechanism for different platforms to
+     * manage usage of underlying network interface by client.
+     */
+    virtual void set_platform_network_handler(void *handler = NULL);
+
+    /**
+     * \brief Sets the function callback that will be called by mbed-client for
+     * fetching random number from application for ensuring strong entropy.
+     * \param random_callback A function pointer that will be called by mbed-client
+     * while performing secure handshake.
+     * Function signature should be uint32_t (*random_number_callback)(void);
+     */
+    virtual void set_random_number_callback(random_number_cb callback);
+
+    /**
+     * \brief Sets the function callback that will be called by mbed-client for
+     * providing entropy source from application for ensuring strong entropy.
+     * \param entropy_callback A function pointer that will be called by mbed-client
+     * while performing secure handshake.
+     * Function signature , if using mbed-client-mbedtls should be
+     * int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output,
+     *                                     size_t len, size_t *olen);
+     */
+    virtual void set_entropy_callback(entropy_cb callback);
+
+    /**
+      * \brief Removes an object from M2MInterfaceImpl.
+      * Does not call delete on the object though.
+      * \return true if the object was found and false if the object was not found.
+      */
+    virtual bool remove_object(M2MBase *object);
+
+    /**
+     * @brief Updates the endpoint name.
+     * @param name New endpoint name
+     */
+    virtual void update_endpoint(String &name);
+
+    /**
+     * @brief Updates the domain name.
+     * @param domain New domain name
+     */
+    virtual void update_domain(String &domain);
+
+    /**
+     * @brief Return internal endpoint name
+     * @return internal endpoint name
+     */
+    virtual const String internal_endpoint_name() const;
+
+    /**
+     * @brief Return error description for the latest error code
+     * @return Error description string
+     */
+    virtual const char *error_description() const;
+
+    /**
+     * @brief Sends the CoAP GET request to the server.
+     * @uri Uri path to the data.
+     * @offset Data offset.
+     * @async In async mode application must call this API again with the updated offset.
+     *        If set to false then client will automatically download the whole package.
+     * @get_data_cb Callback which is triggered once there is data available.
+     * @get_data_error_cb Callback which is trigged in case of any error.
+    */
+    virtual void get_data_request(const char *uri,
+                                  const size_t offset,
+                                  const bool async,
+                                  get_data_cb data_cb,
+                                  get_data_error_cb error_cb,
+                                  void *context);
+
+    /**
+     * @brief Sends the CoAP POST request to the server.
+     * @uri Uri path to the data.
+     * @async In async mode application must call this API again with the updated offset.
+     *        If set to false then client will automatically download the whole package.
+     * @payload_len Length of payload.
+     * @payload_ptr, Pointer to payload buffer.
+     * @get_data_cb Callback which is triggered once there is data available.
+     * @get_data_error_cb Callback which is trigged in case of any error.
+     */
+    virtual void post_data_request(const char *uri,
+                                   const bool async,
+                                   const uint16_t payload_len,
+                                   uint8_t *payload_ptr,
+                                   get_data_cb data_cb,
+                                   get_data_error_cb error_cb,
+                                   void *context);
+
+    /**
+     * @brief Set custom uri query paramaters used in LWM2M registration.
+     * @uri_query_params Uri query params. Parameters must be in key-value format:
+     * "a=100&b=200". Maximum length can be up to 64 bytes.
+     * @return False if maximum length exceeded otherwise True.
+    */
+    virtual bool set_uri_query_parameters(const char *uri_query_params);
+
+protected: // From M2MNsdlObserver
+
+    virtual void coap_message_ready(uint8_t *data_ptr,
+                                    uint16_t data_len,
+                                    sn_nsdl_addr_s *address_ptr);
+
+    virtual void client_registered(M2MServer *server_object);
+
+    virtual void registration_updated(const M2MServer &server_object);
+
+    virtual void registration_error(uint8_t error_code, bool retry = false);
+
+    virtual void client_unregistered();
+
+    virtual void bootstrap_done();
+
+    virtual void bootstrap_finish();
+
+    virtual void bootstrap_wait();
+
+    virtual void bootstrap_error_wait(const char *reason);
+
+    virtual void bootstrap_error(const char *reason);
+
+    virtual void coap_data_processed();
+
+    virtual void value_updated(M2MBase *base);
+
+protected: // From M2MConnectionObserver
+
+    virtual void data_available(uint8_t* data,
+                                uint16_t data_size,
+                                const M2MConnectionObserver::SocketAddress &address);
+
+    virtual void socket_error(uint8_t error_code, bool retry = true);
+
+    virtual void address_ready(const M2MConnectionObserver::SocketAddress &address,
+                               M2MConnectionObserver::ServerType server_type,
+                               const uint16_t server_port);
+
+    virtual void data_sent();
+
+protected: // from M2MTimerObserver
+
+    virtual void timer_expired(M2MTimerObserver::Type type);
+
+
+private: // state machine state functions
+
+    /**
+    * When the state is Idle.
+    */
+    void state_idle(EventData* data);
+
+    /**
+    * When the client starts bootstrap.
+    */
+    void state_bootstrap( EventData *data);
+
+    /**
+    * When the bootstrap server address is resolved.
+    */
+    void state_bootstrap_address_resolved( EventData *data);
+
+    /**
+    * When the bootstrap resource is created.
+    */
+    void state_bootstrap_resource_created( EventData *data);
+
+    /**
+    * When the server has sent response and bootstrapping is done.
+    */
+    void state_bootstrapped( EventData *data);
+
+    /**
+    * When the client starts register.
+    */
+    void state_register( EventData *data);
+
+    /**
+    * When the server address for register is resolved.
+    */
+    void state_register_address_resolved( EventData *data);
+
+    /**
+    * When the client is registered.
+    */
+    void state_registered( EventData *data);
+
+    /**
+    * When the client is updating registration.
+    */
+    void state_update_registration( EventData *data);
+
+    /**
+    * When the client starts unregister.
+    */
+    void state_unregister( EventData *data);
+
+    /**
+    * When the client has been unregistered.
+    */
+    void state_unregistered( EventData *data);
+
+    /**
+    * When the coap data is been sent through socket.
+    */
+    void state_sending_coap_data( EventData *data);
+
+    /**
+    * When the coap data is sent successfully.
+    */
+    void state_coap_data_sent( EventData *data);
+
+    /**
+    * When the socket is receiving coap data.
+    */
+    void state_receiving_coap_data( EventData *data);
+
+    /**
+    * When the socket has received coap data.
+    */
+    void state_coap_data_received( EventData *data);
+
+    /**
+    * When the coap message is being processed.
+    */
+    void state_processing_coap_data( EventData *data);
+
+    /**
+    * When the coap message has been processed.
+    */
+    void state_coap_data_processed( EventData *data);
+
+    /**
+    * When the client is waiting to receive or send data.
+    */
+    void state_waiting( EventData *data);
+
+    /**
+     * Start registration update.
+     */
+    void start_register_update(M2MUpdateRegisterData *data);
+
+    /**
+    * State enumeration order must match the order of state
+    * method entries in the state map
+    */
+    enum E_States {
+        STATE_IDLE = 0,
+        STATE_BOOTSTRAP,
+        STATE_BOOTSTRAP_ADDRESS_RESOLVED,
+        STATE_BOOTSTRAP_RESOURCE_CREATED,
+        STATE_BOOTSTRAP_WAIT,
+        STATE_BOOTSTRAP_ERROR_WAIT, // 5
+        STATE_BOOTSTRAPPED,
+        STATE_REGISTER,
+        STATE_REGISTER_ADDRESS_RESOLVED,
+        STATE_REGISTERED,
+        STATE_UPDATE_REGISTRATION, // 10
+        STATE_UNREGISTER,
+        STATE_UNREGISTERED,
+        STATE_SENDING_COAP_DATA,
+        STATE_COAP_DATA_SENT,
+        STATE_COAP_DATA_RECEIVED, // 15
+        STATE_PROCESSING_COAP_DATA,
+        STATE_COAP_DATA_PROCESSED,
+        STATE_WAITING,
+        STATE_MAX_STATES
+    };
+
+    /**
+     * @brief Redirects the state machine to right function.
+     * @param current_state Current state to be set.
+     * @param data Data to be passed to the state function.
+     */
+    void state_function( uint8_t current_state, EventData* data  );
+
+    /**
+     * @brief State Engine maintaining state machine logic.
+     */
+    void state_engine(void);
+
+    /**
+    * External event which can trigger the state machine.
+    * @param New The state to which the state machine should go.
+    * @param data The data to be passed to the state machine.
+    */
+    void external_event(uint8_t, EventData* = NULL);
+
+    /**
+    * Internal event generated by state machine.
+    * @param New State which the state machine should go to.
+    * @param data The data to be passed to the state machine.
+    */
+    void internal_event(uint8_t, EventData* = NULL);
+
+    /**
+    * Queue mode enabled or not.
+    * @return True if queue mode otherwise false.
+    */
+    bool queue_mode() const;
+
+    enum
+    {
+        EVENT_IGNORED = 0xFE,
+        CANNOT_HAPPEN
+    };
+
+    /**
+     * Helper method for extracting the IP address part and port from the
+     * given server address.
+     * @param server_address Source URL (without "coap" or "coaps" prefix).
+     * @param ip_address The extracted IP.
+     * @param port The extracted port.
+     */
+    static void process_address(const String& server_address, String& ip_address, uint16_t& port);
+
+    /**
+     * Helper method for storing the error description to _error_description if the feature
+     * has not been turned off.
+     * @param error description
+     */
+    void set_error_description(const char *description);
+
+    enum ReconnectionState{
+        None,
+        WithUpdate,
+        Unregistration
+    };
+
+private:
+
+    EventData                   *_event_data;
+    M2MTimer                    *_registration_flow_timer;
+    uint16_t                    _server_port;
+    uint16_t                    _listen_port;
+    int32_t                     _life_time;
+    String                      _server_ip_address;
+    M2MSecurity                 *_register_server; //TODO: to be the list not owned
+    M2MTimer                    _queue_sleep_timer;
+    M2MTimer                    _retry_timer;
+    callback_handler            _callback_handler;
+    const uint8_t               _max_states;
+    bool                        _event_ignored;
+    bool                        _event_generated;
+    bool                        _reconnecting;
+    bool                        _retry_timer_expired;
+    bool                        _bootstrapped;
+    bool                        _bootstrap_finished;
+    bool                        _queue_mode_timer_ongoing;
+    uint8_t                     _current_state;
+    BindingMode                 _binding_mode;
+    ReconnectionState           _reconnection_state;
+    M2MInterfaceObserver        &_observer;
+    M2MConnectionSecurity       *_security_connection; // Doesn't own
+    M2MConnectionHandler        _connection_handler;
+    M2MNsdlInterface            _nsdl_interface;
+    M2MSecurity                 *_security;
+
+#ifndef DISABLE_ERROR_DESCRIPTION
+    // The DISABLE_ERROR_DESCRIPTION macro will reduce the flash usage by ~1800 bytes.
+    char                        _error_description[MAX_ALLOWED_ERROR_STRING_LENGTH];
+#endif
+
+    uint8_t                     _initial_reconnection_time;
+    uint64_t                    _reconnection_time;
+
+    friend class Test_M2MInterfaceImpl;
+
+};
+
+#define BEGIN_TRANSITION_MAP \
+    static const uint8_t TRANSITIONS[] = {\
+
+#define TRANSITION_MAP_ENTRY(entry)\
+    entry,
+
+#define END_TRANSITION_MAP(data) \
+    0 };\
+    external_event(TRANSITIONS[_current_state], data);
+
+#endif //M2M_INTERFACE_IMPL_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mnotificationhandler.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifndef M2MNOTIFICATIONHANDLER_H
+#define M2MNOTIFICATIONHANDLER_H
+
+#include "ns_types.h"
+#include "eventOS_event.h"
+
+class M2MNsdlInterface;
+class M2MNotificationHandler {
+
+public:
+    M2MNotificationHandler();
+
+    ~M2MNotificationHandler();
+
+    void send_notification(M2MNsdlInterface *interface);
+
+private:
+    void initialize_event();
+
+private:
+    static int8_t       _tasklet_id;
+    arm_event_storage_t _event;
+};
+
+#endif // M2MNOTIFICATIONHANDLER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mnsdlinterface.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,682 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2MNSDLINTERFACE_H
+#define M2MNSDLINTERFACE_H
+
+#include "ns_list.h"
+#include "mbed-client/m2mvector.h"
+#include "mbed-client/m2mconfig.h"
+#include "mbed-client/m2minterface.h"
+#include "mbed-client/m2mtimerobserver.h"
+#include "mbed-client/m2mobservationhandler.h"
+#include "mbed-client/m2mtimer.h"
+#include "mbed-client/m2mbase.h"
+#include "mbed-client/m2mserver.h"
+#include "include/nsdllinker.h"
+#include "eventOS_event.h"
+
+//FORWARD DECLARARTION
+class M2MSecurity;
+class M2MObject;
+class M2MObjectInstance;
+class M2MResource;
+class M2MResourceInstance;
+class M2MNsdlObserver;
+class M2MServer;
+class M2MConnectionHandler;
+class M2MNotificationHandler;
+
+/**
+ * @brief M2MNsdlInterface
+ * Class which interacts between mbed Client C++ Library and mbed-client-c library.
+ */
+class M2MNsdlInterface : public M2MTimerObserver,
+                         public M2MObservationHandler
+{
+private:
+    // Prevents the use of assignment operator by accident.
+    M2MNsdlInterface& operator=( const M2MNsdlInterface& /*other*/ );
+
+    // Prevents the use of copy constructor by accident
+    M2MNsdlInterface( const M2MNsdlInterface& /*other*/ );
+
+public:
+
+    struct request_context_s {
+        request_data_cb     on_request_data_cb;
+        request_error_cb    on_request_error_cb;
+        size_t              received_size;
+        uint32_t            msg_token;
+        char                *uri_path;
+        void                *context;
+        bool                async_req;
+        sn_coap_msg_code_e  msg_code;
+        bool                resend;
+        ns_list_link_t      link;
+    };
+
+    struct nsdl_coap_data_s {
+        nsdl_s              *nsdl_handle;
+        sn_coap_hdr_s       *received_coap_header;
+        sn_nsdl_addr_s      address;
+    };
+
+    typedef NS_LIST_HEAD(request_context_s, link) request_context_list_t;
+
+    /**
+    * @brief Constructor
+    * @param observer, Observer to pass the event callbacks from nsdl library.
+    */
+    M2MNsdlInterface(M2MNsdlObserver &observer, M2MConnectionHandler &connection_handler);
+
+    /**
+     * @brief Destructor
+     */
+    virtual ~M2MNsdlInterface();
+
+    /**
+     * @brief Creates endpoint object for the nsdl stack.
+     * @param endpoint_name, Endpoint name of the client.
+     * @param endpoint_type, Endpoint type of the client.
+     * @param life_time, Life time of the client in seconds
+     * @param domain, Domain of the client.
+     * @param mode, Binding mode of the client, default is UDP
+     * @param context_address, Context address default is empty.
+    */
+    void create_endpoint(const String &endpoint_name,
+                         const String &endpoint_type,
+                         const int32_t life_time,
+                         const String &domain,
+                         const uint8_t mode,
+                         const String &context_address);
+
+    /**
+     * @brief Deletes the endpoint.
+    */
+    void delete_endpoint();
+
+    /**
+     * @brief Updates endpoint name.
+    */
+    void update_endpoint(const String &name);
+
+    /**
+     * @brief Updates domain.
+    */
+    void update_domain(const String &domain);
+
+    /**
+     * @brief Creates the NSDL structure for the registered objectlist.
+     * @param list, List of objects implementing the M2MBase interface to be registered.
+     * @return true if structure created successfully else false.
+    */
+    bool create_nsdl_list_structure(const M2MBaseList &list);
+
+    /**
+     * @brief Removed the NSDL resource for the given resource.
+     * @param base, Resource to be removed.
+     * @return true if removed successfully else false.
+    */
+    bool remove_nsdl_resource(M2MBase *base);
+
+    /**
+     * @brief Creates the bootstrap object.
+     * @param address Bootstrap address.
+     * @return true if created and sent successfully else false.
+    */
+    bool create_bootstrap_resource(sn_nsdl_addr_s *address);
+
+    /**
+     * @brief Sets the register message to the server.
+     * @param address M2MServer address.
+     * @param address_length M2MServer address length.
+     * @param port M2MServer port.
+     * @param address_type IP Address type.
+    */
+    void set_server_address(uint8_t* address,
+                            uint8_t address_length,
+                            const uint16_t port,
+                            sn_nsdl_addr_type_e address_type);
+    /**
+     * @brief Sends the register message to the server.
+     * @return  true if register sent successfully else false.
+    */
+    bool send_register_message();
+
+    /**
+     * @brief Sends the CoAP request to the server.
+     * @uri Uri path to the data.
+     * @msg_code CoAP message code of request to send.
+     * @offset Data offset.
+     * @async In async mode application must call this API again with the updated offset.
+     *        If set to false then client will automatically download the whole package.
+     * @payload_len Length of payload buffer.
+     * @payload_ptr Pointer to payload buffer.
+     * @request_data_cb Callback which is triggered once there is data available.
+     * @request_error_cb Callback which is trigged in case of any error.
+     * @context Application context.
+     */
+    void send_request(const char *uri,
+                      const sn_coap_msg_code_e msg_code,
+                      const size_t offset,
+                      const bool async,
+                      const uint16_t payload_len,
+                      uint8_t *payload_ptr,
+                      request_data_cb data_cb,
+                      request_error_cb error_cb,
+                      void *context);
+
+    /**
+     * @brief Sends the update registration message to the server.
+     * @param lifetime, Updated lifetime value in seconds.
+     * @return  true if sent successfully else false.
+     *
+    */
+    bool send_update_registration(const uint32_t lifetime = 0);
+
+    /**
+     * @brief Sends unregister message to the server.
+     * @return  true if unregister sent successfully else false.
+    */
+    bool send_unregister_message();
+
+    /**
+     * @brief Memory Allocation required for libCoap.
+     * @param size, Size of memory to be reserved.
+    */
+    static void* memory_alloc(uint32_t size);
+
+    /**
+     * @brief Memory free functions required for libCoap
+     * @param ptr, Object whose memory needs to be freed.
+    */
+    static void memory_free(void *ptr);
+
+    /**
+    * @brief Callback from nsdl library to inform the data is ready
+    * to be sent to server.
+    * @param nsdl_handle, Handler for the nsdl structure for this endpoint
+    * @param protocol, Protocol format of the data
+    * @param data, Data to be sent.
+    * @param data_len, Size of the data to be sent
+    * @param address, server address where data has to be sent.
+    * @return 1 if successful else 0.
+    */
+    uint8_t send_to_server_callback(struct nsdl_s * nsdl_handle,
+                                    sn_nsdl_capab_e protocol,
+                                    uint8_t *data,
+                                    uint16_t data_len,
+                                    sn_nsdl_addr_s *address);
+
+    /**
+    * @brief Callback from nsdl library to inform the data which is
+    * received from server for the client has been converted to coap message.
+    * @param nsdl_handle, Handler for the nsdl structure for this endpoint
+    * @param coap_header, Coap message formed from data.
+    * @param address, Server address from where the data is received.
+    * @return 1 if successful else 0.
+    */
+    uint8_t received_from_server_callback(struct nsdl_s * nsdl_handle,
+                                          sn_coap_hdr_s *coap_header,
+                                          sn_nsdl_addr_s *address);
+
+    /**
+    * @brief Callback from nsdl library to inform the data which is
+    * received from server for the resources has been converted to coap message.
+    * @param nsdl_handle, Handler for the nsdl resource structure for this endpoint..
+    * @param coap_header, Coap message formed from data.
+    * @param address, Server address from where the data is received.
+    * @param nsdl_capab, Protocol for the message, currently only coap is supported.
+    * @return 1 if successful else 0.
+    */
+    uint8_t resource_callback(struct nsdl_s *nsdl_handle, sn_coap_hdr_s *coap,
+                               sn_nsdl_addr_s *address,
+                               sn_nsdl_capab_e nsdl_capab);
+
+    /**
+    * @brief Callback from event loop for handling CoAP messages received from server for the resources
+    * that has been converted to coap message.
+    * @param coap_header, Coap message formed from data.
+    * @param address, Server address from where the data is received.
+    * @return 1 if successful else 0.
+    */
+    uint8_t resource_callback_handle_event(sn_coap_hdr_s *coap,
+                                           sn_nsdl_addr_s *address);
+
+
+    /**
+     * @brief Callback when there is data received from server and needs to be processed.
+     * @param data, data received from server.
+     * @param data_size, data size received from server.
+     * @param addres, address structure of the server.
+     * @return true if successfully processed else false.
+     */
+    bool process_received_data(uint8_t *data,
+                               uint16_t data_size,
+                               sn_nsdl_addr_s *address);
+
+    /**
+     * @brief Stops all the timers in case there is any errors.
+     */
+    void stop_timers();
+
+    /**
+     * @brief Returns nsdl handle.
+     * @return ndsl handle
+     */
+    nsdl_s* get_nsdl_handle() const;
+
+    /**
+     * @brief Get endpoint name
+     * @return endpoint name
+     */
+    const String& endpoint_name() const;
+
+    /**
+     * @brief Get internal endpoint name
+     * @return internal endpoint name
+     */
+    const String internal_endpoint_name() const;
+
+    /**
+     * @brief Set server address
+     * @param server_address, Bootstrap or M2M server address.
+     */
+    void set_server_address(const char *server_address);
+
+    /**
+     * @brief Remove an object from the list kept by the NSDLInteface.
+     * Does not call delete on the object.
+     */
+    bool remove_object_from_list(M2MBase *base);
+
+    /*
+     * @brief Get NSDL timer.
+     * @return NSDL execution timer.
+     */
+    M2MTimer &get_nsdl_execution_timer();
+
+    /**
+     * @brief Get unregister state.
+     * @return Is unregistration ongoing.
+     */
+    bool is_unregister_ongoing() const;
+
+    /**
+     * @brief Get update register state.
+     * @return Is updare registration ongoing.
+     */
+    bool is_update_register_ongoing() const;
+
+    /**
+     * @brief Starts the NSDL execution timer.
+     */
+    void start_nsdl_execution_timer();
+
+    /**
+     * @brief Returns security object.
+     * @return M2MSecurity object, contains lwm2m server information.
+     */
+    M2MSecurity* get_security_object();
+
+    /**
+     * @brief Returns auto-observation token.
+     * @param path, Resource path, used for searching the right object.
+     * @param token[OUT], Token data.
+     * @return Length of the token if found otherwise 0.
+     */
+    uint8_t find_auto_obs_token(const char *path, uint8_t *token) const;
+
+    /**
+     * @brief Set custom uri query paramaters used in LWM2M registration.
+     * @uri_query_params Uri query params. Parameters must be in key-value pair format:
+     * "a=100&b=200". Maximum length can be up to 64 bytes.
+     * @return False if maximum length exceeded otherwise True.
+    */
+    bool set_uri_query_parameters(const char *uri_query_params);
+
+    /**
+     * @brief Clears the sent blockwise message list in CoAP library.
+    */
+    void clear_sent_blockwise_messages();
+
+    /**
+     * @brief Send next notification message.
+    */
+    void send_next_notification(bool clear_token);
+
+    /**
+     * @brief Store the "BS finished" response id.
+     * @param msg_id Response id.
+    */
+    void store_bs_finished_response_id(uint16_t msg_id);
+
+    /**
+     * @brief Store the registration state.
+     * @param registered Registered to lwm2m server or not.
+    */
+    void set_registration_status(bool registered);
+
+    /**
+     * @brief Handle incoming bootstrap PUT message.
+     * @param coap_header, Received CoAP message
+     * @param address, Server address
+    */
+    void handle_bootstrap_put_message(sn_coap_hdr_s *coap_header, sn_nsdl_addr_s *address);
+
+    /**
+     * @brief Handle bootstrap finish acknowledgement.
+    */
+    void handle_bootstrap_finish_ack(uint16_t msg_id);
+
+    /**
+     * @brief Returns total retransmission time
+     * @resend_count Resend count
+     * @return Total retransmission time
+    */
+    uint32_t total_retransmission_time(int resend_count);
+
+    /**
+     * @brief Returns CoAP retransmission count
+     * @return CoAP retransmission count
+    */
+    uint8_t get_resend_count();
+
+    /**
+     * @brief Mark request to be resend again after network break
+    */
+    void set_request_context_to_be_resend();
+
+protected: // from M2MTimerObserver
+
+    virtual void timer_expired(M2MTimerObserver::Type type);
+
+protected: // from M2MObservationHandler
+
+    virtual bool observation_to_be_sent(M2MBase *object,
+                                        uint16_t obs_number,
+                                        const m2m::Vector<uint16_t> &changed_instance_ids,
+                                        bool send_object = false);
+
+    virtual void resource_to_be_deleted(M2MBase* base);
+
+    virtual void value_updated(M2MBase *base);
+
+    virtual void remove_object(M2MBase *object);
+#ifndef DISABLE_DELAYED_RESPONSE
+    virtual void send_delayed_response(M2MBase *base);
+#endif
+
+private:
+
+    /**
+     * Enum defining an LWM2M object type.
+    */
+    typedef enum {
+        SECURITY = 0x00,
+        SERVER   = 0x01,
+        DEVICE   = 0x02
+    }ObjectType;
+
+    /**
+    * @brief Initializes all the nsdl library component to be usable.
+    * @return true if initialization is successful else false.
+    */
+    bool initialize();
+
+    bool add_object_to_list(M2MBase *base);
+
+    bool create_nsdl_structure(M2MBase *base);
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+    bool create_nsdl_endpoint_structure(M2MEndpoint *endpoint);
+#endif
+
+    bool create_nsdl_object_structure(M2MObject *object);
+
+    bool create_nsdl_object_instance_structure(M2MObjectInstance *object_instance);
+
+    bool create_nsdl_resource_structure(M2MResource *resource,
+                                        bool multiple_instances = false);
+
+    bool create_nsdl_resource(M2MBase *base);
+
+    static String coap_to_string(const uint8_t *coap_data_ptr,
+                          int coap_data_ptr_length);
+
+    void execute_nsdl_process_loop();
+
+    uint64_t registration_time() const;
+
+    M2MBase* find_resource(const String &object,
+                           const uint16_t msg_id) const;
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+    M2MBase* find_resource(const M2MEndpoint *endpoint,
+                                             const String &object_name,
+                                             const uint16_t msg_id) const;
+#endif
+
+    M2MBase* find_resource(const M2MObject *object,
+                           const String &object_instance,
+                           const uint16_t msg_id) const;
+
+    M2MBase* find_resource(const M2MObjectInstance *object_instance,
+                           const String &resource_instance,
+                           const uint16_t msg_id) const;
+
+    M2MBase* find_resource(const M2MResource *resource,
+                           const String &object_name,
+                           const String &resource_instance) const;
+
+    bool object_present(M2MBase *base) const;
+
+    int object_index(M2MBase *base) const;
+
+    static M2MInterface::Error interface_error(const sn_coap_hdr_s &coap_header);
+
+    void send_object_observation(M2MObject *object,
+                                 uint16_t obs_number,
+                                 const m2m::Vector<uint16_t> &changed_instance_ids,
+                                 bool send_object);
+
+    void send_object_instance_observation(M2MObjectInstance *object_instance,
+                                          uint16_t obs_number);
+
+    void send_resource_observation(M2MResource *resource, uint16_t obs_number);
+
+
+
+    /**
+     * @brief Allocate (size + 1) amount of memory, copy size bytes into
+     * it and add zero termination.
+     * @param source Source string to copy, may not be NULL.
+     * @param size The size of memory to be reserved.
+    */
+    static uint8_t* alloc_string_copy(const uint8_t* source, uint16_t size);
+
+    /**
+     * @brief Utility method to convert given lifetime int to ascii
+     * and allocate a buffer for it and set it to _endpoint->lifetime_ptr.
+     * @param lifetime A new value for lifetime.
+    */
+    void set_endpoint_lifetime_buffer(int lifetime);
+
+    /**
+     * @brief Handle bootstrap finished message.
+     * @param coap_header, Received CoAP message
+     * @param address, Server address
+    */
+    void handle_bootstrap_finished(sn_coap_hdr_s *coap_header,sn_nsdl_addr_s *address);
+
+    /**
+     * @brief Handle bootstrap delete message.
+     * @param coap_header, Received CoAP message
+     * @param address, Server address
+    */
+    void handle_bootstrap_delete(sn_coap_hdr_s *coap_header,sn_nsdl_addr_s *address);
+
+    /**
+     * @brief Parse bootstrap TLV message.
+     * @param coap_header, Received CoAP message
+     * @return True if parsing was succesful else false
+    */
+    bool parse_bootstrap_message(sn_coap_hdr_s *coap_header, M2MNsdlInterface::ObjectType lwm2m_object_type);
+
+    /**
+     * @brief Parse bootstrap TLV message.
+     * @param coap_header, Received CoAP message
+     * @return True if parsing was succesful else false
+    */
+    bool validate_security_object();
+
+    /**
+     * @brief Handle bootstrap errors.
+     * @param reason, Reason for Bootstrap failure.
+     * @param wait, True if need to wait that ACK has been sent.
+     *              False if reconnection can start immediately.
+    */
+    void handle_bootstrap_error(const char *reason, bool wait);
+
+    /**
+     * @brief Handle different coap errors.
+     * @param coap_header, CoAP structure.
+     * @return Error reason.
+    */
+    static const char *coap_error(const sn_coap_hdr_s &coap_header);
+
+    /**
+     * @brief Claim
+     */
+    void claim_mutex();
+
+    /**
+     * @brief Release
+     */
+    void release_mutex();
+
+    /**
+     * @brief Change operation mode of every resource.
+     * @param object, Object to be updated.
+     * @return operation, New operation mode.
+    */
+    void change_operation_mode(M2MObject *object, M2MBase::Operation operation);
+
+    /**
+     * @brief Parse URI query parameters and pass those to nsdl-c.
+     * @return True if parsing success otherwise False
+    */
+    bool parse_and_send_uri_query_parameters();
+
+    /**
+     * @brief Callback function that triggers the registration update call.
+     * @param argument, Arguments part of the POST request.
+    */
+    void update_trigger_callback(void *argument);
+
+    bool lifetime_value_changed() const;
+
+    void execute_notification_delivery_status_cb(M2MBase* object, int32_t msgid);
+
+    bool is_response_to_request(const sn_coap_hdr_s *coap_header,
+                                struct request_context_s &get_data);
+
+    void free_request_context_list(const sn_coap_hdr_s *coap_header = NULL);
+
+    /**
+     * @brief Send next notification for object, return true if notification sent, false
+     *        if no notification to send or send already in progress.
+     * @param object, M2MObject whose next notification should be sent
+     * @param clear_token, Flag to indicate whether observation token should be cleared.
+     * @return True if notification sent, false otherwise or if send already in progress
+     */
+    bool send_next_notification_for_object(M2MObject& object, bool clear_token);
+
+    static char* parse_uri_query_parameters(char* uri);
+
+    void calculate_new_coap_ping_send_time();
+
+    void send_coap_ping();
+
+    void send_empty_ack(const sn_coap_hdr_s *header, sn_nsdl_addr_s *address);
+
+    struct M2MNsdlInterface::nsdl_coap_data_s* create_coap_event_data(sn_coap_hdr_s *received_coap_header,
+                                                  sn_nsdl_addr_s *address,
+                                                  struct nsdl_s *nsdl_handle,
+                                                  uint8_t coap_msg_code = COAP_MSG_CODE_EMPTY);
+
+    void handle_register_response(const sn_coap_hdr_s *coap_header);
+
+    void handle_unregister_response(const sn_coap_hdr_s *coap_header);
+
+    void handle_register_update_response(const sn_coap_hdr_s *coap_header);
+
+    void handle_request_response(const sn_coap_hdr_s *coap_header, struct request_context_s *request_context);
+
+    void handle_bootstrap_response(const sn_coap_hdr_s *coap_header);
+
+    void handle_notification_delivered(M2MBase *base);
+
+    void handle_empty_ack(const sn_coap_hdr_s *coap_header, bool is_bootstrap_msg);
+
+    bool handle_post_response(sn_coap_hdr_s *coap_header,
+                              sn_nsdl_addr_s *address,
+                              sn_coap_hdr_s *&coap_response,
+                              M2MObjectInstance *&obj_instance,
+                              bool is_bootstrap_msg);
+
+    bool is_blockwise_needed(uint32_t length) const;
+
+    void set_retransmission_parameters();
+
+    void send_pending_request();
+
+private:
+
+    M2MNsdlObserver                         &_observer;
+    M2MBaseList                             _base_list;
+    sn_nsdl_ep_parameters_s                 *_endpoint;
+    nsdl_s                                  *_nsdl_handle;
+    M2MSecurity                             *_security; // Not owned
+    M2MServer                               *_server;
+    M2MTimer                                _nsdl_execution_timer;
+    M2MTimer                                _registration_timer;
+    M2MConnectionHandler                    &_connection_handler;
+    String                                  _endpoint_name;
+    String                                  _internal_endpoint_name;
+    uint32_t                                _counter_for_nsdl;
+    uint32_t                                _next_coap_ping_send_time;
+    char                                    *_server_address; // BS or M2M address
+    request_context_list_t                  _request_context_list;
+    char                                    *_custom_uri_query_params;
+    M2MNotificationHandler                  *_notification_handler;
+    arm_event_storage_t                     _event;
+    uint16_t                                _auto_obs_token;
+    uint16_t                                _bootstrap_id;
+    static int8_t                           _tasklet_id;
+    uint8_t                                 _binding_mode;
+    bool                                    _identity_accepted;
+    bool                                    _nsdl_execution_timer_running;
+    bool                                    _notification_send_ongoing;
+    bool                                    _registered;
+    bool                                    _bootstrap_finish_ack_received;
+
+friend class Test_M2MNsdlInterface;
+
+};
+
+#endif // M2MNSDLINTERFACE_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mnsdlobserver.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2M_NSDL_OBSERVER_H
+#define M2M_NSDL_OBSERVER_H
+
+#include "include/nsdllinker.h"
+
+//FORWARD DECLARATION
+class M2MSecurity;
+class M2MServer;
+
+/**
+ * @brief Observer class for informing NSDL callback to the state machine
+ */
+
+class M2MNsdlObserver
+{
+
+public :
+
+    /**
+    * @brief Informs that coap message is ready.
+    * @param data_ptr, Data object of coap message.
+    * @param data_len, Length of the data object.
+    * @param address_ptr, Address structure of the server.
+    */
+    virtual void coap_message_ready(uint8_t *data_ptr,
+                                    uint16_t data_len,
+                                    sn_nsdl_addr_s *address_ptr) = 0;
+
+    /**
+    * @brief Informs that client is registered successfully.
+    * @param server_object, Server object associated with
+    * registered server.
+    */
+    virtual void client_registered(M2MServer *server_object) = 0;
+
+    /**
+    * @brief Informs that client registration is updated successfully.
+    * @param server_object, Server object associated with
+    * registered server.
+    */
+    virtual void registration_updated(const M2MServer &server_object) = 0;
+
+    /**
+    * @brief Informs that some error occured during
+    * registration.
+    * @param error_code, Error code for registration error
+    * @param retry, Indicates state machine to re-establish connection
+    */
+    virtual void registration_error(uint8_t error_code, bool retry = false) = 0;
+
+    /**
+    * @brief Informs that client is unregistered successfully.
+    */
+    virtual void client_unregistered() = 0;
+
+    /**
+    * @brief Informs that client bootstrapping is done.
+    * @param security_object, M2MSecurity Object which contains information about
+    * LWM2M server fetched from bootstrap server.
+    */
+    virtual void bootstrap_done() = 0;
+
+    /**
+    * @brief Informs that client bootstrap data has been received and final bootstrap
+    * finish message has been handled.
+    */
+    virtual void bootstrap_finish() = 0;
+
+    /**
+    * @brief Informs that client bootstrapping is waiting for message to be sent.
+    * @param security_object, M2MSecurity Object which contains information about
+    * LWM2M server fetched from bootstrap server.
+    */
+    virtual void bootstrap_wait() = 0;
+
+    /**
+    * @brief Informs that client bootstrapping is waiting for error message to be sent.
+    * @param reason, Error description.
+    */
+    virtual void bootstrap_error_wait(const char *reason) = 0;
+
+    /**
+    * @brief Informs that some error occured during
+    * bootstrapping.
+    * @param reason, Error string explaining the failure reason
+    */
+    virtual void bootstrap_error(const char *reason) = 0;
+
+    /**
+    * @brief Informs that received data has been processed.
+    */
+    virtual void coap_data_processed() = 0;
+
+    /**
+     * @brief Callback informing that the value of the resource object is updated by server.
+     * @param base Object whose value is updated.
+     */
+    virtual void value_updated(M2MBase *base) = 0;
+};
+#endif // M2M_NSDL_OBSERVER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mreporthandler.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef M2MREPORTHANDLER_H
+#define M2MREPORTHANDLER_H
+
+// Support for std args
+#include <stdint.h>
+#include "mbed-client/m2mconfig.h"
+#include "mbed-client/m2mbase.h"
+#include "mbed-client/m2mtimerobserver.h"
+#include "mbed-client/m2mresourceinstance.h"
+#include "mbed-client/m2mvector.h"
+#include "mbed-client/m2mtimer.h"
+
+//FORWARD DECLARATION
+class M2MReportObserver;
+class M2MTimer;
+class M2MResourceInstance;
+
+/**
+ *  @brief M2MReportHandler.
+ *  This class is handles all the observation related operations.
+ */
+class M2MReportHandler: public M2MTimerObserver
+{
+private:
+    // Prevents the use of assignment operator by accident.
+    M2MReportHandler& operator=( const M2MReportHandler& /*other*/ );
+
+public:
+
+    M2MReportHandler(M2MReportObserver &observer);
+
+public:
+
+    /**
+     * Enum defining which write attributes are set.
+    */
+    enum {
+        Cancel = 1,
+        Pmin = 2,
+        Pmax = 4,
+        Lt = 8,
+        Gt = 16,
+        St = 32
+    };
+
+    /**
+     * Destructor
+     */
+    virtual ~M2MReportHandler();
+
+    /**
+     * @brief Sets that object is under observation.
+     * @param Value for the observation.
+     * @param handler, Handler object for sending
+     * observation callbacks.
+     */
+    void set_under_observation(bool observed);
+
+    /**
+     * @brief Sets the value of the given resource.
+     * @param value, Value of the observed resource.
+     */
+    void set_value(float value);
+
+    /**
+     * @brief Sets notification trigger.
+     * @param obj_instance_id, Object instance id that has changed
+     */
+    void set_notification_trigger(uint16_t obj_instance_id = 0);
+
+    /**
+     * @brief Parses the received query for notification
+     * attribute.
+     * @param query Query to be parsed for attributes.
+     * @param type Type of the Base Object.
+     * @param resource_type Type of the Resource.
+     * @return true if required attributes are present else false.
+     */
+    bool parse_notification_attribute(const char *query,
+                                              M2MBase::BaseType type,
+                                              M2MResourceInstance::ResourceType resource_type = M2MResourceInstance::OPAQUE);
+
+    /**
+    * @brief Set back to default values.
+    */
+    void set_default_values();
+
+    /**
+     * @brief Return write attribute flags.
+     */
+    uint8_t attribute_flags() const;
+
+    /**
+     * \brief Sets the observation token value.
+     * \param token A pointer to the token of the resource.
+     * \param length The length of the token pointer.
+     */
+    void set_observation_token(const uint8_t *token, const uint8_t length);
+
+    /**
+     * \brief Provides a copy of the observation token of the object.
+     * \param value[OUT] A pointer to the value of the token.
+     * \param value_length[OUT] The length of the token pointer.
+     */
+    void get_observation_token(uint8_t *token, uint8_t &token_length) const;
+
+    /**
+     * \brief Returns the observation number.
+     * \return The observation number of the object.
+     */
+    uint16_t observation_number() const;
+
+    /**
+     * \brief Adds the observation level for the object.
+     * \param observation_level The level of observation.
+     */
+    void add_observation_level(M2MBase::Observation obs_level);
+
+    /**
+     * \brief Removes the observation level for the object.
+     * \param observation_level The level of observation.
+     */
+    void remove_observation_level(M2MBase::Observation obs_level);
+
+    /**
+     * \brief Returns the observation level of the object.
+     * \return The observation level of the object.
+     */
+    M2MBase::Observation observation_level() const;
+
+    /**
+     * @brief Returns whether this resource is under observation or not.
+     * @return True if the resource is under observation, else false,
+     */
+    bool is_under_observation() const;
+
+    /**
+     * @brief Schedule a report, if the pmin is exceeded
+     * report immediately, otherwise store the state to be
+     * reported once the time fires.
+     *
+     * @param in_queue If the message is queued message then it must be send even if
+     * current and last values are the same.
+     */
+    void schedule_report(bool in_queue = false);
+
+    /**
+     * @brief Set flag that new notification needs to be send.
+     *
+     * @param to_queue If True then notification is marked to be send
+     */
+    void set_notification_in_queue(bool to_queue);
+
+    /**
+     * @brief Returns whether notification needs to be send or not.
+     *
+     * @return Is notification sending needed or not.
+     */
+    bool notification_in_queue() const;
+
+    /**
+     * @brief Set flag that new notification needs to be send.
+     *
+     * @param to_queue If True then notification is marked to be send
+     */
+    void set_notification_send_in_progress(bool progress);
+
+    /**
+     * @brief Returns whether notification send is in progress or not.
+     *
+     * @return Is notification sending ongoing or not.
+     */
+    bool notification_send_in_progress() const;
+
+    /**
+     * @brief Sets whether notification will be sent using blockwise or not.
+     *
+     * @param blockwise_notify If True then notification is sent using blockwise.
+     */
+    void set_blockwise_notify(bool blockwise_notify);
+
+    /**
+     * @brief Returns whether notification is sent using blockwise or not.
+     *
+     * @return Is notification sent using blockwise.
+     */
+    bool blockwise_notify() const;
+
+protected : // from M2MTimerObserver
+
+    virtual void timer_expired(M2MTimerObserver::Type type =
+                               M2MTimerObserver::Notdefined);
+
+private:
+
+    bool set_notification_attribute(const char* option,
+            M2MBase::BaseType type,
+            M2MResourceInstance::ResourceType resource_type);
+
+    /**
+    * @brief Reports a sample that satisfies the reporting criteria.
+    *
+    * @param in_queue If the message is queued message then it must be send even
+    * current and last values are the same.
+    */
+    void report(bool in_queue = false);
+
+    /**
+    * @brief Manage timers for pmin and pmax.
+    */
+    void handle_timers();
+
+    /**
+    * @brief Check whether notification params can be accepted.
+    */
+    bool check_attribute_validity() const;
+
+    /**
+    * @brief Stop pmin & pmax timers.
+    */
+    void stop_timers();
+
+    /**
+     * @brief Check if current value match threshold values.
+     * @return True if notify can be send otherwise false.
+     */
+    bool check_threshold_values() const;
+
+    /**
+     * @brief Check whether current value matches with GT & LT.
+     * @return True if current value match with GT or LT values.
+     */
+    bool check_gt_lt_params() const;
+
+    /**
+     * \brief Allocate (size + 1) amount of memory, copy size bytes into
+     * it and add zero termination.
+     * \param source The source string to copy, may not be NULL.
+     * \param size The size of memory to be reserved.
+    */
+    static uint8_t* alloc_string_copy(const uint8_t* source, uint32_t size);
+
+private:
+    M2MReportObserver           &_observer;
+    bool                        _is_under_observation : 1;
+    M2MBase::Observation        _observation_level : 4;
+    uint8_t                     _attribute_state;
+    unsigned                    _token_length : 8;
+    bool                        _notify : 1;
+    bool                        _pmin_exceeded : 1;
+    bool                        _pmax_exceeded : 1;
+    unsigned                    _observation_number : 24;
+    M2MTimer                    _pmin_timer;
+    M2MTimer                    _pmax_timer;
+    uint8_t                     *_token;
+    int32_t                     _pmax;
+    int32_t                     _pmin;
+    float                       _current_value;
+    float                       _gt;
+    float                       _lt;
+    float                       _st;
+    float                       _high_step;
+    float                       _low_step;
+    float                       _last_value;
+    m2m::Vector<uint16_t>       _changed_instance_ids;
+    bool                        _notification_send_in_progress : 1;
+    bool                        _notification_in_queue : 1;
+    bool                        _blockwise_notify : 1;
+    bool                        _pmin_quiet_period : 1;
+
+friend class Test_M2MReportHandler;
+
+};
+
+#endif // M2MREPORTHANDLER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mtlvdeserializer.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "mbed-client/m2mvector.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mobjectinstance.h"
+#include "mbed-client/m2mresource.h"
+
+/**
+ * @brief M2MTLVDeserializer
+ * TLV Deserialiser get the object instances and resources as binary data and
+ * builds the <code>lwm2m</code> representation from it. See OMA-LWM2M
+ * specification, chapter 6.1 for the resource model and chapter 6.3.3 for
+ * the OMA-TLV specification.
+ */
+class M2MTLVDeserializer {
+
+public :
+
+    typedef enum {
+        None,
+        NotFound,
+        NotAllowed,
+        NotValid,
+        OutOfMemory
+    } Error;
+
+    typedef enum {
+        Put,
+        Post
+    } Operation;
+
+
+    /**
+     * This method checks whether the given binary encodes an object instance
+     * or something else. It returns <code>true</code> if bits 7-6 of the first
+     * byte is "00".
+     * @param tlv Binary to be checked as LWM2M object instance
+     * @return <code>true</code> or <code>false</code>.
+     */
+    static bool is_object_instance(const uint8_t *tlv);
+
+    /**
+     * This method checks whether the given binary encodes a resource or
+     * something else. It returns <code>true</code> if bits 7-6 of the first
+     * byte is "11".
+     * @param tlv Binary to be checked as LWM2M resource.
+     * @return <code>true</code> or <code>false</code>.
+     */
+    static bool is_resource(const uint8_t *tlv);
+
+    /**
+     * This method checks whether the given binary encodes a multiple resource
+     * or something else. It returns <code>true</code> if bits 7-6 of the first
+     * byte is "10".
+     * @param tlv Binary to be checked as LWM2M multiple resource.
+     * @return <code>true</code> or <code>false</code>.
+     */
+    static bool is_multiple_resource(const uint8_t *tlv);
+
+    /**
+     * This method checks whether the given binary encodes a resource instance
+     * or something else. It returns <code>true</code> if bits 7-6 of the first
+     * byte is "01".
+     * @param tlv Binary to be checked as LWM2M resource instance.
+     * @return <code>true</code> or <code>false</code>.
+     */
+    static bool is_resource_instance(const uint8_t *tlv);
+
+    /**
+     * Deserialises the given binary that must encode object instances. Binary
+     * array can be checked before invoking this method with
+     */
+    static M2MTLVDeserializer::Error deserialise_object_instances(const uint8_t* tlv,
+                                                           uint32_t tlv_size,
+                                                           M2MObject &object,
+                                                           M2MTLVDeserializer::Operation operation);
+
+    /**
+     * Deserialises the given binary that must encode resources. Binary array
+     * can be checked before invoking this method.
+     */
+    static M2MTLVDeserializer::Error deserialize_resources(const uint8_t *tlv,
+                                                    uint32_t tlv_size,
+                                                    M2MObjectInstance &object_instance,
+                                                    M2MTLVDeserializer::Operation operation);
+
+    /**
+     * Deserialises the given binary that must encode resource instances. Binary array
+     * can be checked before invoking this method.
+     */
+    static M2MTLVDeserializer::Error deserialize_resource_instances(const uint8_t *tlv,
+                                                             uint32_t tlv_size,
+                                                             M2MResource &resource,
+                                                             M2MTLVDeserializer::Operation operation);
+    /**
+     * This method return object instance id or resource id.
+     * @param tlv Binary to be checked
+     * @return Object instance id or resource id.
+     */
+    static uint16_t instance_id(const uint8_t *tlv);
+
+private:
+
+    static M2MTLVDeserializer::Error deserialize_object_instances(const uint8_t *tlv,
+                                                           uint32_t tlv_size,
+                                                           uint32_t offset,
+                                                           M2MObject &object,
+                                                           M2MTLVDeserializer::Operation operation,
+                                                           bool update_value);
+
+    static M2MTLVDeserializer::Error deserialize_resources(const uint8_t *tlv,
+                                                    uint32_t tlv_size,
+                                                    uint32_t offset,
+                                                    M2MObjectInstance &object_instance,
+                                                    M2MTLVDeserializer::Operation operation,
+                                                    bool update_value);
+
+    static M2MTLVDeserializer::Error deserialize_resource_instances(const uint8_t *tlv,
+                                                             uint32_t tlv_size,
+                                                             uint32_t offset,
+                                                             M2MResource &resource,
+                                                             M2MObjectInstance &object_instance,
+                                                             M2MTLVDeserializer::Operation operation,
+                                                             bool update_value);
+
+    static M2MTLVDeserializer::Error deserialize_resource_instances(const uint8_t *tlv,
+                                                             uint32_t tlv_size,
+                                                             uint32_t offset,
+                                                             M2MResource &resource,
+                                                             M2MTLVDeserializer::Operation operation,
+                                                             bool update_value);
+
+    static bool is_object_instance(const uint8_t *tlv, uint32_t offset);
+
+    static bool is_resource(const uint8_t *tlv, uint32_t offset);
+
+    static bool is_multiple_resource(const uint8_t *tlv, uint32_t offset);
+
+    static bool is_resource_instance(const uint8_t *tlv, uint32_t offset);
+
+    static bool set_resource_instance_value(M2MResourceBase *res, const uint8_t *tlv, const uint32_t size);
+
+    static void remove_resources(const uint8_t *tlv,
+                                 uint32_t tlv_size,
+                                 M2MObjectInstance &object_instance,
+                                 uint32_t offset_size);
+
+    static void remove_resource_instances(const uint8_t *tlv,
+                                 uint32_t tlv_size,
+                                 M2MResource &resource,
+                                 uint32_t offset_size);
+};
+
+class TypeIdLength {
+
+public:
+    TypeIdLength(const uint8_t *tlv, uint32_t offset);
+
+    void deserialize();
+
+    void deserialiseID(uint32_t idLength);
+
+    void deserialiseLength(uint32_t lengthType);
+
+    const uint8_t     *_tlv;
+    uint32_t    _offset;
+    uint32_t    _type;
+    uint16_t    _id;
+    uint32_t    _length;
+
+    friend class Test_M2MTLVDeserializer;
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/m2mtlvserializer.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "mbed-client/m2mvector.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mobjectinstance.h"
+#include "mbed-client/m2mresource.h"
+
+class M2MResourceBase;
+
+/**
+ * @brief M2MTLVSerializer
+ * TLV Serialiser constructs the binary representation of object instances,
+ * resources and resource instances (see OMA-LWM2M specification, chapter 6.1
+ * for resource model) as OMA-TLV according described in chapter 6.3.3. 
+ * 
+ */
+class M2MTLVSerializer {
+
+public:
+
+    /**
+     * Serialises given objects instances that contain resources or multiple 
+     * resources. Object instance IDs are also encoded. This method must be 
+     * used when an operation targets an object with (potential) multiple 
+     * instances like "GET /1". In that case the generated TLV will contain the
+     * following data:
+     * <ul>
+     * <li> ./0
+     * <li> ./0/0
+     * <li> ./0/1
+     * <li> ...
+     * <li> ./1
+     * <li> ./1/0
+     * <li> ./1/1
+     * <li> ...
+     * </ul>
+     *    
+     * @param objects List of object instances.
+     * @return Object instances encoded binary as OMA-TLV 
+     * @see #serializeObjectInstances(List) 
+     */
+    static uint8_t* serialize(const M2MObjectInstanceList &object_instance_list, uint32_t &size);
+
+    /**
+     * Serialises given resources with no information about the parent object
+     * instance. This method must be used when an operation targets an object
+     * instance like "GET /1/0" or a single-instance object like "GET /3//".
+     * Resources may have single or multiple instances. The generated TLV will 
+     * contain the following data as response to "GET /3//":
+     * <ul>
+     * <li> ./0
+     * <li> ./1
+     * <li> ./2
+     * <li> ./6/0 (1st instance of a multiple resource)
+     * <li> ./6/1 (2nd instance of a multiple resource)
+     * <li> ...
+     * </ul>
+     * @param resources Array of resources and resource instances.
+     * @return Resources encoded binary as OMA-TLV
+     * @see #serializeResources(List)
+     */
+    static uint8_t* serialize(const M2MResourceList &resource_list, uint32_t &size);
+
+    static uint8_t* serialize(const M2MResource *resource, uint32_t &size);
+
+private :
+
+    static uint8_t* serialize_object_instances(const M2MObjectInstanceList &object_instance_list, uint32_t &size);
+
+    static uint8_t* serialize_resources(const M2MResourceList &resource_list, uint32_t &size, bool &valid);
+
+    static bool serialize(uint16_t id, const M2MObjectInstance *object_instance, uint8_t *&data, uint32_t &size);
+    
+    static bool serialize(const M2MResource *resource, uint8_t *&data, uint32_t &size);
+
+    static bool serialize_resource(const M2MResource *resource, uint8_t *&data, uint32_t &size);
+
+    static bool serialize_multiple_resource(const M2MResource *resource, uint8_t *&data, uint32_t &size);
+
+    static bool serialize_resource_instance(uint16_t id, const M2MResourceInstance *resource, uint8_t *&data, uint32_t &size);
+    
+    static bool serialize_TILV (uint8_t type, uint16_t id, uint8_t *value, uint32_t value_length, uint8_t *&data, uint32_t &size);
+
+    static void serialize_id(uint16_t id, uint32_t &size, uint8_t *id_ptr);
+
+    static void serialize_length(uint32_t length, uint32_t &size, uint8_t *length_ptr);
+
+    static bool serialize_TLV_binary_int(const M2MResourceBase *resource, uint8_t type, uint16_t id, uint8_t *&data, uint32_t &size);
+
+    static bool serialize_TLV_binary_float(const M2MResourceBase *resource, uint8_t type, uint16_t id, uint8_t *&data, uint32_t &size);
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/nsdlaccesshelper.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef NSDL_ACCESS_HELPER_H
+#define NSDL_ACCESS_HELPER_H
+#include "mbed-client/m2mconnectionhandler.h"
+#include "include/m2mnsdlinterface.h"
+
+typedef Vector<M2MNsdlInterface  *> M2MNsdlInterfaceList;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+uint8_t __nsdl_c_callback(struct nsdl_s * nsdl_handle,
+                          sn_coap_hdr_s *received_coap_ptr,
+                          sn_nsdl_addr_s *address,
+                          sn_nsdl_capab_e nsdl_capab);
+
+void *__nsdl_c_memory_alloc(uint16_t size);
+
+void __nsdl_c_memory_free(void *ptr);
+
+uint8_t __nsdl_c_send_to_server(struct nsdl_s * nsdl_handle,
+                                sn_nsdl_capab_e protocol,
+                                uint8_t *data_ptr,
+                                uint16_t data_len,
+                                sn_nsdl_addr_s *address_ptr);
+
+uint8_t __nsdl_c_received_from_server(struct nsdl_s * nsdl_handle,
+                                      sn_coap_hdr_s *coap_header,
+                                      sn_nsdl_addr_s *address_ptr);
+
+uint8_t __nsdl_c_auto_obs_token(struct nsdl_s *nsdl_handle, const char *path, uint8_t *token);
+
+void *__socket_malloc( void * context, size_t size);
+
+void __socket_free(void * context, void * ptr);
+
+M2MNsdlInterface* get_interface(struct nsdl_s* nsdl_handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NSDL_ACCESS_HELPER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/nsdllinker.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef NSDL_LINKER_H
+#define NSDL_LINKER_H
+
+#include <stdint.h>
+#include "nsdl-c/sn_nsdl.h"
+#include "sn_coap_header.h"
+#include "sn_coap_protocol.h"
+#include "nsdl-c/sn_nsdl_lib.h"
+#include "ns_list.h"
+
+#endif // NSDL_LINKER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/include/smartpointer.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef SMART_POINTER_H
+#define SMART_POINTER_H
+
+class ReferenceCount
+{
+private:
+
+    int _count; // Reference count
+
+public:
+
+void add_ref()
+{
+    // Increment the reference count
+    _count++;
+}
+
+int release()
+{
+    // Decrement the reference count and
+    // return the reference count.
+    return --_count;
+}
+};
+
+template < typename T > class SmartPointer
+{
+private:
+
+    T                   *_data;         // Generic pointer to be stored
+    ReferenceCount      *_reference;    // Reference count
+
+
+public:
+
+SmartPointer()
+: _data(0), _reference(0)
+{
+    // Create a new reference
+    _reference = new ReferenceCount();
+    // Increment the reference count
+    _reference->add_ref();
+}
+
+SmartPointer(T* value)
+: _data(value), _reference(0)
+{
+    // Create a new reference
+    _reference = new ReferenceCount();
+    // Increment the reference count
+    _reference->add_ref();
+}
+
+SmartPointer(const SmartPointer<T>& smart_pointer)
+: _data(smart_pointer._data), reference(smart_pointer._reference)
+{
+    // Copy constructor
+    // Copy the data and reference pointer
+    // and increment the reference count
+    _reference->add_ref();
+}
+
+~SmartPointer()
+{
+    if(_reference->release() == 0) {
+        delete _data;
+        delete _reference;
+    }
+}
+
+T& operator* ()
+{
+    return *_data;
+}
+
+T* operator-> ()
+{
+    return _data;
+}
+
+SmartPointer<T>& operator = (const SmartPointer<T>& smart_pointer)
+{
+    // Assignment operator
+    if (this != &SmartPointer) { // Avoid self assignment
+        // Decrement the old reference count
+        // if reference become zero delete the old data
+        if(_reference->release() == 0) {
+           delete _data;
+           delete _reference;
+        }
+
+        // Copy the data and reference pointer
+        // and increment the reference count
+        _data = SmartPointer._data;
+        _reference = SmartPointer._reference;
+        _reference->add_ref();
+    }
+    return *this;
+}
+
+};
+
+#endif // SMART_POINTER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mbase.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,906 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#include "mbed-client/m2mbase.h"
+#include "mbed-client/m2mobservationhandler.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2mtimer.h"
+
+#include "mbed-client/m2mendpoint.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mobjectinstance.h"
+#include "mbed-client/m2mresource.h"
+
+#include "include/m2mreporthandler.h"
+#include "include/nsdlaccesshelper.h"
+#include "include/m2mcallbackstorage.h"
+#include "mbed-trace/mbed_trace.h"
+
+#include "sn_nsdl_lib.h"
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include "common_functions.h"
+
+#define TRACE_GROUP "mClt"
+
+M2MBase::M2MBase(const String& resource_name,
+                 M2MBase::Mode mode,
+#ifndef DISABLE_RESOURCE_TYPE
+                 const String &resource_type,
+#endif
+                 char *path,
+                 bool external_blockwise_store,
+                 bool multiple_instance,
+                 M2MBase::DataType type)
+:
+  _sn_resource(NULL),
+  _report_handler(NULL)
+{
+    // Checking the name length properly, i.e returning error is impossible from constructor without exceptions
+    assert(resource_name.length() <= MAX_ALLOWED_STRING_LENGTH);
+
+    _sn_resource = (lwm2m_parameters_s*)memory_alloc(sizeof(lwm2m_parameters_s));
+    if(_sn_resource) {
+        memset(_sn_resource, 0, sizeof(lwm2m_parameters_s));
+        _sn_resource->free_on_delete = true;
+        _sn_resource->multiple_instance = multiple_instance;
+        _sn_resource->data_type = type;
+        _sn_resource->read_write_callback_set = false;
+        _sn_resource->dynamic_resource_params =
+                (sn_nsdl_dynamic_resource_parameters_s*)memory_alloc(sizeof(sn_nsdl_dynamic_resource_parameters_s));
+        if(_sn_resource->dynamic_resource_params) {
+            memset(_sn_resource->dynamic_resource_params,
+                   0, sizeof(sn_nsdl_dynamic_resource_parameters_s));
+            _sn_resource->dynamic_resource_params->static_resource_parameters =
+                    (sn_nsdl_static_resource_parameters_s*)memory_alloc(sizeof(sn_nsdl_static_resource_parameters_s));
+
+            // Set callback function in case of both dynamic and static resource
+            _sn_resource->dynamic_resource_params->sn_grs_dyn_res_callback = __nsdl_c_callback;
+
+            if(_sn_resource->dynamic_resource_params->static_resource_parameters) {
+                // Cast const away to able to compile using MEMORY_OPTIMIZED_API flag
+                sn_nsdl_static_resource_parameters_s *params =
+                        const_cast<sn_nsdl_static_resource_parameters_s *>(_sn_resource->dynamic_resource_params->static_resource_parameters);
+                memset(params, 0, sizeof(sn_nsdl_static_resource_parameters_s));
+                const size_t len = strlen(resource_type.c_str());
+                params->free_on_delete = true;
+                if (len > 0) {
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_RESOURCE_TYPE
+                    params->resource_type_ptr = (char*)alloc_string_copy((uint8_t*) resource_type.c_str(), len);
+#endif
+#else
+                    sn_nsdl_attribute_item_s item;
+                    item.attribute_name = ATTR_RESOURCE_TYPE;
+                    item.value = (char*)alloc_string_copy((uint8_t*) resource_type.c_str(), len);
+                    sn_nsdl_set_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, &item);
+#endif
+                }
+                params->path = path;
+                params->mode = (unsigned)mode;
+                params->external_memory_block = external_blockwise_store;
+                _sn_resource->dynamic_resource_params->static_resource_parameters = params;
+            }
+        }
+
+        if((!resource_name.empty())) {
+            _sn_resource->identifier_int_type = false;
+            _sn_resource->identifier.name = stringdup((char*)resource_name.c_str());
+        } else {
+            tr_debug("M2MBase::M2Mbase resource name is EMPTY ===========");
+            _sn_resource->identifier_int_type = true;
+            _sn_resource->identifier.instance_id = 0;
+        }
+        _sn_resource->dynamic_resource_params->publish_uri = true;
+        _sn_resource->dynamic_resource_params->free_on_delete = true;
+        _sn_resource->dynamic_resource_params->auto_observable = false;
+        _sn_resource->dynamic_resource_params->publish_value = false;
+    }
+}
+
+M2MBase::M2MBase(const lwm2m_parameters_s *s):
+    _sn_resource((lwm2m_parameters_s*) s),
+    _report_handler(NULL)
+{
+    tr_debug("M2MBase::M2MBase(const lwm2m_parameters_s *s)");
+    // Set callback function in case of both dynamic and static resource
+    _sn_resource->dynamic_resource_params->sn_grs_dyn_res_callback = __nsdl_c_callback;
+}
+
+M2MBase::~M2MBase()
+{
+    tr_debug("M2MBase::~M2MBase() %p", this);
+    delete _report_handler;
+
+    value_updated_callback* callback = (value_updated_callback*)M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback);
+    delete callback;
+
+    M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2);
+    M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback);
+}
+
+char* M2MBase::create_path_base(const M2MBase &parent, const char *name)
+{
+    char * result = NULL;
+    // Expectation is that every element can be MAX_NAME_SZE, + 4 /'s + \0
+    StringBuffer<(MAX_NAME_SIZE * 4 + (4 + 1))> path;
+    path.append(parent.uri_path());
+    path.append('/');
+    path.append(name);
+    result = stringdup(path.c_str());
+
+    return result;
+}
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+char* M2MBase::create_path(const M2MEndpoint &parent, const char *name)
+{
+    return create_path_base(parent, name);
+}
+#endif
+
+char* M2MBase::create_path(const M2MObject &parent, uint16_t object_instance)
+{
+    StringBuffer<6> obj_inst_id;
+    obj_inst_id.append_int(object_instance);
+
+    return create_path_base(parent, obj_inst_id.c_str());
+}
+
+char* M2MBase::create_path(const M2MObject &parent, const char *name)
+{
+    return create_path_base(parent, name);
+}
+
+char* M2MBase::create_path(const M2MResource &parent, uint16_t resource_instance)
+{
+    StringBuffer<6> res_inst;
+    res_inst.append_int(resource_instance);
+
+    return create_path_base(parent, res_inst.c_str());
+}
+
+char* M2MBase::create_path(const M2MResource &parent, const char *name)
+{
+    return create_path_base(parent, name);
+}
+
+char* M2MBase::create_path(const M2MObjectInstance &parent, const char *name)
+{
+    return create_path_base(parent, name);
+}
+
+void M2MBase::set_operation(M2MBase::Operation opr)
+{
+    // If the mode is Static, there is only GET_ALLOWED supported.
+    if(M2MBase::Static == mode()) {
+        _sn_resource->dynamic_resource_params->access = M2MBase::GET_ALLOWED;
+    } else {
+        _sn_resource->dynamic_resource_params->access = opr;
+    }
+}
+
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef MEMORY_OPTIMIZED_API
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+void M2MBase::set_interface_description(const char *desc)
+{
+    assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
+    free(_sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr);
+    _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr = NULL;
+    const size_t len = strlen(desc);
+    if (len > 0 ) {
+        _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr =
+                (char*)alloc_string_copy((uint8_t*) desc, len);
+    }
+    set_changed();
+}
+
+void M2MBase::set_interface_description(const String &desc)
+{
+    assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
+    set_interface_description(desc.c_str());
+}
+#endif // DISABLE_INTERFACE_DESCRIPTION
+
+#ifndef DISABLE_RESOURCE_TYPE
+void M2MBase::set_resource_type(const String &res_type)
+{
+    assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
+    set_resource_type(res_type.c_str());
+}
+
+void M2MBase::set_resource_type(const char *res_type)
+{
+    assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
+    free(_sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr);
+    _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr = NULL;
+    const size_t len = strlen(res_type);
+    if (len > 0) {
+        _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr = (char*)
+                alloc_string_copy((uint8_t*) res_type, len);
+    }
+    set_changed();
+}
+#endif // DISABLE_RESOURCE_TYPE
+#endif //MEMORY_OPTIMIZED_API
+#else // RESOURCE_ATTRIBUTES_LIST
+void M2MBase::set_interface_description(const char *desc)
+{
+    assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
+    const size_t len = strlen(desc);
+    if (len > 0 ) {
+        sn_nsdl_attribute_item_s item;
+        item.attribute_name = ATTR_INTERFACE_DESCRIPTION;
+        item.value = (char*)alloc_string_copy((uint8_t*) desc, len);
+        sn_nsdl_set_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, &item);
+        set_changed();
+    }
+}
+
+void M2MBase::set_interface_description(const String &desc)
+{
+    assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
+    set_interface_description(desc.c_str());
+}
+
+void M2MBase::set_resource_type(const String &res_type)
+{
+    assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
+    set_resource_type(res_type.c_str());
+}
+
+void M2MBase::set_resource_type(const char *res_type)
+{
+    assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
+    const size_t len = strlen(res_type);
+    if (len > 0) {
+        sn_nsdl_attribute_item_s item;
+        item.attribute_name = ATTR_RESOURCE_TYPE;
+        item.value = (char*)alloc_string_copy((uint8_t*) res_type, len);
+        sn_nsdl_set_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, &item);
+        set_changed();
+    }
+}
+#endif // RESOURCE_ATTRIBUTES_LIST
+
+void M2MBase::set_coap_content_type(const uint16_t con_type)
+{
+    _sn_resource->dynamic_resource_params->coap_content_type = con_type;
+    set_changed();
+}
+
+void M2MBase::set_observable(bool observable)
+{
+    _sn_resource->dynamic_resource_params->observable = observable;
+    set_changed();
+}
+
+void M2MBase::set_auto_observable(bool auto_observable)
+{
+    _sn_resource->dynamic_resource_params->auto_observable = auto_observable;
+    set_changed();
+}
+
+void M2MBase::add_observation_level(M2MBase::Observation obs_level)
+{
+    if(_report_handler) {
+        _report_handler->add_observation_level(obs_level);
+    }
+}
+
+void M2MBase::remove_observation_level(M2MBase::Observation obs_level)
+{
+    if(_report_handler) {
+        _report_handler->remove_observation_level(obs_level);
+    }
+}
+
+
+void M2MBase::set_under_observation(bool observed,
+                                    M2MObservationHandler *handler)
+{
+    tr_debug("M2MBase::set_under_observation - observed: %d", observed);
+    tr_debug("M2MBase::set_under_observation - base_type: %d", base_type());
+    if(_report_handler) {
+        _report_handler->set_under_observation(observed);
+    }
+
+    set_observation_handler(handler);
+
+    if (handler) {
+        if (base_type() != M2MBase::ResourceInstance) {
+            // Create report handler only if it does not exist and one wants observation
+            // This saves 76 bytes of memory on most usual case.
+            if (observed) {
+                if(!_report_handler) {
+                    _report_handler = new M2MReportHandler(*this);
+                }
+            }
+            if (_report_handler) {
+                _report_handler->set_under_observation(observed);
+            }
+        }
+    } else {
+        delete _report_handler;
+        _report_handler = NULL;
+    }
+}
+
+void M2MBase::set_observation_token(const uint8_t *token, const uint8_t length)
+{
+    if (_report_handler) {
+        _report_handler->set_observation_token(token, length);
+        // This relates to sn_nsdl_auto_obs_token_callback in sn_nsdl.c
+        set_changed();
+    }
+}
+
+void M2MBase::set_instance_id(const uint16_t inst_id)
+{
+    _sn_resource->identifier_int_type = true;
+    _sn_resource->identifier.instance_id = inst_id;
+}
+
+void M2MBase::set_max_age(const uint32_t max_age)
+{
+    _sn_resource->max_age = max_age;
+}
+
+M2MBase::BaseType M2MBase::base_type() const
+{
+    return (M2MBase::BaseType)_sn_resource->base_type;
+}
+
+M2MBase::Operation M2MBase::operation() const
+{
+    return (M2MBase::Operation)_sn_resource->dynamic_resource_params->access;
+}
+
+const char* M2MBase::name() const
+{
+    assert(_sn_resource->identifier_int_type == false);
+    return _sn_resource->identifier.name;
+}
+
+int32_t M2MBase::name_id() const
+{
+    int32_t name_id = -1;
+    assert(_sn_resource->identifier_int_type == false);
+    if(is_integer(_sn_resource->identifier.name) && strlen(_sn_resource->identifier.name) <= MAX_ALLOWED_STRING_LENGTH) {
+        name_id = strtoul(_sn_resource->identifier.name, NULL, 10);
+        if(name_id > 65535){
+            name_id = -1;
+        }
+    }
+    return name_id;
+}
+
+uint16_t M2MBase::instance_id() const
+{
+    assert(_sn_resource->identifier_int_type == true);
+    return _sn_resource->identifier.instance_id;
+}
+
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+const char* M2MBase::interface_description() const
+{
+    return (reinterpret_cast<char*>(
+        _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr));
+}
+#endif
+
+#ifndef DISABLE_RESOURCE_TYPE
+const char* M2MBase::resource_type() const
+{
+    return (reinterpret_cast<char*>(
+        _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr));
+}
+#endif
+#else // RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+const char* M2MBase::interface_description() const
+{
+    return sn_nsdl_get_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, ATTR_INTERFACE_DESCRIPTION);
+}
+#endif
+
+#ifndef DISABLE_RESOURCE_TYPE
+const char* M2MBase::resource_type() const
+{
+    return sn_nsdl_get_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, ATTR_RESOURCE_TYPE);
+}
+#endif
+#endif // RESOURCE_ATTRIBUTES_LIST
+const char* M2MBase::uri_path() const
+{
+    return (reinterpret_cast<char*>(
+        _sn_resource->dynamic_resource_params->static_resource_parameters->path));
+}
+
+uint16_t M2MBase::coap_content_type() const
+{
+    return _sn_resource->dynamic_resource_params->coap_content_type;
+}
+
+bool M2MBase::is_observable() const
+{
+    if (_sn_resource->dynamic_resource_params->auto_observable) {
+        return true;
+    } else {
+        return _sn_resource->dynamic_resource_params->observable;
+    }
+}
+
+M2MBase::Observation M2MBase::observation_level() const
+{
+    M2MBase::Observation obs_level = M2MBase::None;
+    if(_report_handler) {
+        obs_level = _report_handler->observation_level();
+    }
+    return obs_level;
+}
+
+void M2MBase::get_observation_token(uint8_t *token, uint8_t &token_length) const
+{
+    if(_report_handler) {
+        _report_handler->get_observation_token(token, token_length);
+    }
+}
+
+M2MBase::Mode M2MBase::mode() const
+{
+    return (M2MBase::Mode)_sn_resource->dynamic_resource_params->static_resource_parameters->mode;
+}
+
+uint16_t M2MBase::observation_number() const
+{
+    uint16_t obs_number = 0;
+    if(_report_handler) {
+        obs_number = _report_handler->observation_number();
+    }
+    return obs_number;
+}
+
+uint32_t M2MBase::max_age() const
+{
+    return _sn_resource->max_age;
+}
+
+bool M2MBase::handle_observation_attribute(const char *query)
+{
+    tr_debug("M2MBase::handle_observation_attribute - under observation(%d)", is_under_observation());
+    bool success = false;
+    // Create handler if not already exists. Client must able to parse write attributes even when
+    // observation is not yet set
+    if (!_report_handler) {
+        _report_handler = new M2MReportHandler(*this);
+    }
+
+    success = _report_handler->parse_notification_attribute(query,base_type());
+    if (success) {
+        if (is_under_observation()) {
+            _report_handler->set_under_observation(true);
+        }
+     } else {
+        _report_handler->set_default_values();
+    }
+    return success;
+}
+
+bool M2MBase::observation_to_be_sent(const m2m::Vector<uint16_t> &changed_instance_ids,
+                                     uint16_t obs_number,
+                                     bool send_object)
+{
+    //TODO: Move this to M2MResourceInstance
+    M2MObservationHandler *obs_handler = observation_handler();
+    if (obs_handler) {
+        return obs_handler->observation_to_be_sent(this,
+                                            obs_number,
+                                            changed_instance_ids,
+                                            send_object);
+    }
+    return false;
+}
+
+void M2MBase::set_base_type(M2MBase::BaseType type)
+{
+    assert(_sn_resource->free_on_delete);
+    _sn_resource->base_type = type;
+}
+
+sn_coap_hdr_s* M2MBase::handle_get_request(nsdl_s */*nsdl*/,
+                                           sn_coap_hdr_s */*received_coap_header*/,
+                                           M2MObservationHandler */*observation_handler*/)
+{
+    //Handled in M2MResource, M2MObjectInstance and M2MObject classes
+    return NULL;
+}
+
+sn_coap_hdr_s* M2MBase::handle_put_request(nsdl_s */*nsdl*/,
+                                           sn_coap_hdr_s */*received_coap_header*/,
+                                           M2MObservationHandler */*observation_handler*/,
+                                           bool &)
+{
+    //Handled in M2MResource, M2MObjectInstance and M2MObject classes
+    return NULL;
+}
+
+sn_coap_hdr_s* M2MBase::handle_post_request(nsdl_s */*nsdl*/,
+                                            sn_coap_hdr_s */*received_coap_header*/,
+                                            M2MObservationHandler */*observation_handler*/,
+                                            bool &,
+                                            sn_nsdl_addr_s *)
+{
+    //Handled in M2MResource, M2MObjectInstance and M2MObject classes
+    return NULL;
+}
+
+void *M2MBase::memory_alloc(uint32_t size)
+{
+    if(size)
+        return malloc(size);
+    else
+        return 0;
+}
+
+void M2MBase::memory_free(void *ptr)
+{
+    free(ptr);
+}
+
+char* M2MBase::alloc_string_copy(const char* source)
+{
+    assert(source != NULL);
+
+    // Note: the armcc's libc does not have strdup, so we need to implement it here
+    const size_t len = strlen(source);
+
+    return (char*)alloc_string_copy((uint8_t*)source, len);
+}
+
+uint8_t* M2MBase::alloc_string_copy(const uint8_t* source, uint32_t size)
+{
+    assert(source != NULL);
+
+    uint8_t* result = (uint8_t*)memory_alloc(size + 1);
+    if (result) {
+        memcpy(result, source, size);
+        result[size] = '\0';
+    }
+    return result;
+}
+
+uint8_t* M2MBase::alloc_copy(const uint8_t* source, uint32_t size)
+{
+    assert(source != NULL);
+
+    uint8_t* result = (uint8_t*)memory_alloc(size);
+    if (result) {
+        memcpy(result, source, size);
+    }
+    return result;
+}
+
+bool M2MBase::validate_string_length(const String &string, size_t min_length, size_t max_length)
+{
+    bool valid = false;
+
+    const size_t len = string.length();
+    if ((len >= min_length) && (len <= max_length)) {
+        valid = true;
+    }
+
+    return valid;
+}
+
+bool M2MBase::validate_string_length(const char* string, size_t min_length, size_t max_length)
+{
+    bool valid = false;
+
+    if (string != NULL) {
+        const size_t len = strlen(string);
+        if ((len >= min_length) && (len <= max_length)) {
+            valid = true;
+        }
+    }
+    return valid;
+}
+
+M2MReportHandler* M2MBase::create_report_handler()
+{
+    if (!_report_handler) {
+        _report_handler = new M2MReportHandler(*this);
+    }
+    return _report_handler;
+}
+
+M2MReportHandler* M2MBase::report_handler() const
+{
+    return _report_handler;
+}
+
+void M2MBase::set_register_uri(bool register_uri)
+{
+    _sn_resource->dynamic_resource_params->publish_uri = register_uri;
+}
+
+bool M2MBase::register_uri()
+{
+    return _sn_resource->dynamic_resource_params->publish_uri;
+}
+
+bool M2MBase::is_integer(const String &value)
+{
+    const char *s = value.c_str();
+    if(value.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) {
+        return false;
+    }
+    char * p;
+    strtol(value.c_str(), &p, 10);
+    return (*p == 0);
+}
+
+bool M2MBase::is_integer(const char *value)
+{
+    assert(value != NULL);
+
+    if((strlen(value) < 1) || ((!isdigit(value[0])) && (value[0] != '-') && (value[0] != '+'))) {
+        return false;
+    }
+    char * p;
+    strtol(value, &p, 10);
+    return (*p == 0);
+}
+
+bool M2MBase::is_under_observation() const
+{
+   bool under_observation = false;
+    if(_report_handler) {
+        under_observation = _report_handler->is_under_observation();
+    }
+    return under_observation;
+}
+
+bool M2MBase::set_value_updated_function(value_updated_callback callback)
+{
+    value_updated_callback* old_callback = (value_updated_callback*)M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback);
+    delete old_callback;
+    // XXX: create a copy of the copy of callback object. Perhaps it would better to
+    // give a reference as parameter and just store that, as it would save some memory.
+    value_updated_callback* new_callback = new value_updated_callback(callback);
+
+    return M2MCallbackStorage::add_callback(*this, new_callback, M2MCallbackAssociation::M2MBaseValueUpdatedCallback);
+}
+
+bool M2MBase::set_value_updated_function(value_updated_callback2 callback)
+{
+    M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2);
+
+    return M2MCallbackStorage::add_callback(*this, (void*)callback, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2);
+}
+
+bool M2MBase::is_value_updated_function_set() const
+{
+    bool func_set = false;
+    if ((M2MCallbackStorage::does_callback_exist(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback) == true) ||
+        (M2MCallbackStorage::does_callback_exist(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2) == true)) {
+
+        func_set = true;
+    }
+    return func_set;
+}
+
+void M2MBase::execute_value_updated(const String& name)
+{
+    // Q: is there a point to call both callback types? Or should we call just one of them?
+
+    value_updated_callback* callback = (value_updated_callback*)M2MCallbackStorage::get_callback(*this,
+                                                                                                 M2MCallbackAssociation::M2MBaseValueUpdatedCallback);
+    if (callback) {
+        (*callback)(name.c_str());
+    }
+
+    value_updated_callback2 callback2 = (value_updated_callback2)M2MCallbackStorage::get_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2);
+    if (callback2) {
+        (*callback2)(name.c_str());
+    }
+}
+
+bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE> &buffer, const char *s1, uint16_t i1, const char *s2, uint16_t i2)
+{
+
+    if(!buffer.ensure_space(strlen(s1) + strlen(s2) + (MAX_INSTANCE_SIZE * 2) + 3 + 1)){
+        return false;
+    }
+
+    buffer.append(s1);
+    buffer.append('/');
+    buffer.append_int(i1);
+    buffer.append('/');
+    buffer.append(s2);
+    buffer.append('/');
+    buffer.append_int(i2);
+
+    return true;
+
+}
+
+bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_2> &buffer, const char *s1, uint16_t i1, const char *s2)
+{
+    if(!buffer.ensure_space(strlen(s1) + strlen(s2) + MAX_INSTANCE_SIZE + 2 + 1)){
+        return false;
+    }
+
+    buffer.append(s1);
+    buffer.append('/');
+    buffer.append_int(i1);
+    buffer.append('/');
+    buffer.append(s2);
+
+    return true;
+}
+
+bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_3> &buffer, const char *s1, uint16_t i1, uint16_t i2)
+{
+    if(!buffer.ensure_space(strlen(s1) + (MAX_INSTANCE_SIZE * 2) + 2 + 1)){
+        return false;
+    }
+
+    buffer.append(s1);
+    buffer.append('/');
+    buffer.append_int(i1);
+    buffer.append('/');
+    buffer.append_int(i2);
+
+    return true;
+}
+
+bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_4> &buffer, const char *s1, uint16_t i1)
+{
+    if(!buffer.ensure_space(strlen(s1) + MAX_INSTANCE_SIZE + 1 + 1)){
+        return false;
+    }
+
+    buffer.append(s1);
+    buffer.append('/');
+    buffer.append_int(i1);
+
+    return true;
+}
+
+char* M2MBase::stringdup(const char* src)
+{
+    assert(src != NULL);
+
+    const size_t len = strlen(src) + 1;
+
+    char *dest = (char*)malloc(len);
+
+    if (dest) {
+        memcpy(dest, src, len);
+    }
+    return dest;
+}
+
+void M2MBase::free_resources()
+{
+    // remove the nsdl structures from the nsdlinterface's lists.
+    M2MObservationHandler *obs_handler = observation_handler();
+    if (obs_handler) {
+        tr_debug("M2MBase::free_resources()");
+        obs_handler->resource_to_be_deleted(this);
+    }
+
+    if (_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete) {
+        sn_nsdl_static_resource_parameters_s *params =
+                const_cast<sn_nsdl_static_resource_parameters_s *>(_sn_resource->dynamic_resource_params->static_resource_parameters);
+
+        free(params->path);
+        //free(params->resource);
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_RESOURCE_TYPE
+        free(params->resource_type_ptr);
+#endif
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+        free(params->interface_description_ptr);
+#endif
+#else
+        sn_nsdl_free_resource_attributes_list(_sn_resource->dynamic_resource_params->static_resource_parameters);
+#endif
+        free(params);
+    }
+    if (_sn_resource->dynamic_resource_params->free_on_delete) {
+        free(_sn_resource->dynamic_resource_params->resource);
+        free(_sn_resource->dynamic_resource_params);
+    }
+
+    if(_sn_resource->free_on_delete && _sn_resource->identifier_int_type == false) {
+        tr_debug("M2MBase::free_resources()");
+        free(_sn_resource->identifier.name);
+    }
+    if(_sn_resource->free_on_delete) {
+        free(_sn_resource);
+    }
+}
+
+size_t M2MBase::resource_name_length() const
+{
+    assert(_sn_resource->identifier_int_type == false);
+    return strlen(_sn_resource->identifier.name);
+}
+
+sn_nsdl_dynamic_resource_parameters_s* M2MBase::get_nsdl_resource() const
+{
+    return _sn_resource->dynamic_resource_params;
+}
+
+M2MBase::lwm2m_parameters_s* M2MBase::get_lwm2m_parameters() const
+{
+    return _sn_resource;
+}
+
+uint16_t M2MBase::get_notification_msgid() const
+{
+    return _sn_resource->dynamic_resource_params->msg_id;
+}
+
+void M2MBase::set_notification_msgid(uint16_t msgid)
+{
+    _sn_resource->dynamic_resource_params->msg_id = msgid;
+}
+
+bool M2MBase::set_notification_delivery_status_cb(notification_delivery_status_cb callback, void *client_args)
+{
+    M2MCallbackStorage::remove_callback(*this,
+                                        M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback);
+
+    return M2MCallbackStorage::add_callback(*this,
+                                            (void*)callback,
+                                            M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback,
+                                            client_args);
+}
+
+void M2MBase::send_notification_delivery_status(const M2MBase& object, const NotificationDeliveryStatus status)
+{
+    M2MCallbackAssociation* item = M2MCallbackStorage::get_association_item(object,
+                                                                            M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback);
+    if (item) {
+        notification_delivery_status_cb callback = (notification_delivery_status_cb)item->_callback;
+        if (callback) {
+            (*callback)(object, status, item->_client_args);
+        }
+    }
+}
+
+void M2MBase::set_changed()
+{
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+    M2MBase *parent = get_parent();
+    if (parent) {
+        parent->set_changed();
+    }
+#endif
+}
+
+M2MBase *M2MBase::get_parent() const
+{
+    return NULL;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mblockmessage.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "mbed-client/m2mblockmessage.h"
+#include "mbed-client/m2mconfig.h"
+#include <stdlib.h>
+#include <string.h>
+
+M2MBlockMessage::M2MBlockMessage() :
+    _block_data_ptr(NULL),
+    _total_message_size(0),
+    _block_data_len(0),
+    _block_number(0),
+    _error_code(M2MBlockMessage::ErrorNone),
+    _is_last_block(false),
+    _is_block_message(false)
+{
+}
+
+M2MBlockMessage::~M2MBlockMessage()
+{
+    free(_block_data_ptr);
+    _block_data_ptr = NULL;
+}
+
+void M2MBlockMessage::set_message_info(sn_coap_hdr_s *coap_header)
+{
+    _is_block_message = (coap_header &&
+                coap_header->options_list_ptr &&
+                coap_header->options_list_ptr->block1 != -1) ? true : false;
+
+    if (coap_header && coap_header->options_list_ptr) {
+        // Check total size
+        if (coap_header->options_list_ptr->use_size1) {
+            _total_message_size = coap_header->options_list_ptr->size1;
+        }
+
+        // Default value in coap library is 65kb
+        uint32_t max_size = SN_COAP_MAX_INCOMING_MESSAGE_SIZE;
+        if (_total_message_size > max_size) {
+            _error_code = M2MBlockMessage::EntityTooLarge;
+        } else {
+            _error_code = M2MBlockMessage::ErrorNone;
+        }
+        if (M2MBlockMessage::ErrorNone == _error_code) {
+            // Is last block
+            if (coap_header->options_list_ptr->block1 != -1) {
+//                if (!(*(coap_header->options_list_ptr->block1_ptr + (coap_header->options_list_ptr->block1_len - 1)) & 0x08)) {
+                if (!((coap_header->options_list_ptr->block1) & 0x08)) {
+                    _is_last_block = true;
+                } else {
+                    _is_last_block = false;
+                }
+            }
+
+            _block_number = coap_header->options_list_ptr->block1 >> 4;
+            // Block number
+//            if (coap_header->options_list_ptr->block1_len == 3) {
+//                _block_number = *(coap_header->options_list_ptr->block1_ptr) << 12;
+//                _block_number |= *(coap_header->options_list_ptr->block1_ptr + 1) << 4;
+//                _block_number |= (*(coap_header->options_list_ptr->block1_ptr + 2)) >> 4;
+//            }
+
+//            else if (coap_header->options_list_ptr->block1_len == 2) {
+//                _block_number = *(coap_header->options_list_ptr->block1_ptr) << 4;
+//                _block_number |= (*(coap_header->options_list_ptr->block1_ptr + 1)) >> 4;
+//            }
+//            else if (coap_header->options_list_ptr->block1_len == 1) {
+//                _block_number = (*coap_header->options_list_ptr->block1_ptr) >> 4;
+//            }
+//            else {
+//                _block_number = 0;
+//            }
+
+            // Payload
+            free(_block_data_ptr);
+            _block_data_ptr = NULL;
+            _block_data_len = coap_header->payload_len;
+            if(_block_data_len > 0) {
+                _block_data_ptr = (uint8_t *)malloc(_block_data_len);
+                if (_block_data_ptr) {
+                    memcpy(_block_data_ptr, coap_header->payload_ptr, _block_data_len);
+                }
+            }
+        }
+    }
+}
+
+void M2MBlockMessage::clear_values()
+{
+    free(_block_data_ptr);
+    _block_data_ptr = NULL;
+    _block_data_len = 0;
+    _block_number = 0;
+    _total_message_size = 0;
+    _is_last_block = false;
+    _error_code = M2MBlockMessage::ErrorNone;
+}
+
+bool M2MBlockMessage::is_block_message() const
+{
+    return _is_block_message;
+}
+
+uint16_t M2MBlockMessage::block_number() const
+{
+    return _block_number;
+}
+
+uint32_t M2MBlockMessage::total_message_size() const
+{
+    return _total_message_size;
+}
+
+bool M2MBlockMessage::is_last_block() const
+{
+    return _is_last_block;
+}
+
+uint8_t* M2MBlockMessage::block_data() const
+{
+    return _block_data_ptr;
+}
+
+uint32_t M2MBlockMessage::block_data_len() const
+{
+    return _block_data_len;
+}
+
+M2MBlockMessage::Error M2MBlockMessage::error_code() const
+{
+    return _error_code;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mcallbackstorage.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2017 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#include "include/m2mcallbackstorage.h"
+
+#include <cstddef>
+
+// Dummy constructor, which does not init any value to something meaningful but needed for array construction.
+// It is better to leave values unintialized, so the Valgrind will point out if the Vector is used without
+// setting real values in there.
+M2MCallbackAssociation::M2MCallbackAssociation()
+{
+}
+
+M2MCallbackAssociation::M2MCallbackAssociation(const M2MBase *object, void *callback, M2MCallbackType type, void *client_args)
+: _object(object), _callback(callback), _type(type), _client_args(client_args)
+{
+}
+
+M2MCallbackStorage* M2MCallbackStorage::_static_instance = NULL;
+
+M2MCallbackStorage *M2MCallbackStorage::get_instance()
+{
+    if (M2MCallbackStorage::_static_instance == NULL) {
+        M2MCallbackStorage::_static_instance = new M2MCallbackStorage();
+    }
+    return M2MCallbackStorage::_static_instance;
+}
+
+void M2MCallbackStorage::delete_instance()
+{
+    delete M2MCallbackStorage::_static_instance;
+    M2MCallbackStorage::_static_instance = NULL;
+}
+
+M2MCallbackStorage::~M2MCallbackStorage()
+{
+    // TODO: go through the list and delete all the FP<n> objects if there are any.
+    // On the other hand, if the system is done properly, each m2mobject should actually
+    // remove its callbacks from its destructor so there is nothing here to do
+}
+
+bool M2MCallbackStorage::add_callback(const M2MBase &object,
+                                      void *callback,
+                                      M2MCallbackAssociation::M2MCallbackType type,
+                                      void *client_args)
+{
+    bool add_success = false;
+    M2MCallbackStorage* instance = get_instance();
+    if (instance) {
+
+        add_success = instance->do_add_callback(object, callback, type, client_args);
+    }
+    return add_success;
+}
+
+bool M2MCallbackStorage::do_add_callback(const M2MBase &object, void *callback, M2MCallbackAssociation::M2MCallbackType type, void *client_args)
+{
+    bool add_success = false;
+
+    // verify that the same callback is not re-added.
+    if (does_callback_exist(object, callback, type) == false) {
+
+        const M2MCallbackAssociation association(&object, callback, type, client_args);
+        _callbacks.push_back(association);
+        add_success = true;
+    }
+
+    return add_success;
+}
+
+#if 0 // Functions not used currently
+void M2MCallbackStorage::remove_callbacks(const M2MBase &object)
+{
+   // do not use the get_instance() here as it might create the instance
+    M2MCallbackStorage* instance = M2MCallbackStorage::_static_instance;
+    if (instance) {
+
+        instance->do_remove_callbacks(object);
+    }
+}
+
+void M2MCallbackStorage::do_remove_callbacks(const M2MBase &object)
+{
+    // find any association to given object and delete them from the vector
+    for (int index = 0; index < _callbacks.size();) {
+        if (_callbacks[index]._object == &object) {
+            _callbacks.erase(index);
+        } else {
+            index++;
+        }
+    }
+}
+#endif
+
+void* M2MCallbackStorage::remove_callback(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type)
+{
+    void* callback = NULL;
+
+    // do not use the get_instance() here as it might create the instance
+    M2MCallbackStorage* instance = M2MCallbackStorage::_static_instance;
+    if (instance) {
+
+        callback = instance->do_remove_callback(object, type);
+    }
+    return callback;
+}
+
+void* M2MCallbackStorage::do_remove_callback(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type)
+{
+    void* callback = NULL;
+    for (int index = 0; index < _callbacks.size(); index++) {
+
+        if ((_callbacks[index]._object == &object) && (_callbacks[index]._type == type)) {
+            callback = _callbacks[index]._callback;
+            _callbacks.erase(index);
+            break;
+        }
+    }
+    return callback;
+}
+
+void* M2MCallbackStorage::get_callback(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type)
+{
+    void* callback = NULL;
+    const M2MCallbackStorage* instance = get_instance();
+    if (instance) {
+
+        callback = instance->do_get_callback(object, type);
+    }
+    return callback;
+}
+
+void* M2MCallbackStorage::do_get_callback(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type) const
+{
+    void* callback = NULL;
+    if (!_callbacks.empty()) {
+        M2MCallbackAssociationList::const_iterator it = _callbacks.begin();
+
+        for ( ; it != _callbacks.end(); it++ ) {
+
+            if ((it->_object == &object) && (it->_type == type)) {
+                callback = it->_callback;
+                break;
+            }
+        }
+    }
+    return callback;
+}
+
+M2MCallbackAssociation* M2MCallbackStorage::get_association_item(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type)
+{
+    M2MCallbackAssociation* callback_association = NULL;
+    const M2MCallbackStorage* instance = get_instance();
+    if (instance) {
+
+        callback_association = instance->do_get_association_item(object, type);
+    }
+    return callback_association;
+}
+
+M2MCallbackAssociation* M2MCallbackStorage::do_get_association_item(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type) const
+{
+    M2MCallbackAssociation* callback_association = NULL;
+    if (!_callbacks.empty()) {
+        M2MCallbackAssociationList::const_iterator it = _callbacks.begin();
+
+        for ( ; it != _callbacks.end(); it++ ) {
+
+            if ((it->_object == &object) && (it->_type == type)) {
+                callback_association = (M2MCallbackAssociation*)it;
+                break;
+            }
+        }
+    }
+    return callback_association;
+}
+
+bool M2MCallbackStorage::does_callback_exist(const M2MBase &object, M2MCallbackAssociation::M2MCallbackType type)
+{
+    bool found = false;
+    if (get_callback(object, type) != NULL) {
+        found = true;
+    }
+    return found;
+}
+
+bool M2MCallbackStorage::does_callback_exist(const M2MBase &object, void *callback, M2MCallbackAssociation::M2MCallbackType type) const
+{
+    bool match_found = false;
+
+    if (!_callbacks.empty()) {
+        M2MCallbackAssociationList::const_iterator it = _callbacks.begin();
+
+        for ( ; it != _callbacks.end(); it++ ) {
+
+            if ((it->_object == &object) && (it->_callback == callback) && (it->_type == type)) {
+                match_found = true;
+                break;
+            }
+        }
+    }
+
+    return match_found;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mdevice.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,566 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#include "mbed-client/m2mdevice.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mobjectinstance.h"
+#include "mbed-client/m2mresource.h"
+#include "mbed-trace/mbed_trace.h"
+
+#define BUFFER_SIZE 21
+#define TRACE_GROUP "mClt"
+
+M2MDevice* M2MDevice::_instance = NULL;
+
+M2MDevice* M2MDevice::get_instance()
+{
+    if(_instance == NULL) {
+        // ownership of this path is transferred to M2MBase.
+        // Since this object is a singleton, we could use the C-structs to avoid heap
+        // allocation on a lot of M2MDevice -objects data.
+        char *path = stringdup(M2M_DEVICE_ID);
+        if (path) {
+            _instance = new M2MDevice(path);
+        }
+    }
+    return _instance;
+}
+
+void M2MDevice::delete_instance()
+{
+    delete _instance;
+    _instance = NULL;
+}
+
+M2MDevice::M2MDevice(char *path)
+: M2MObject(M2M_DEVICE_ID, path)
+{
+    M2MBase::set_register_uri(false);
+    M2MBase::set_operation(M2MBase::GET_ALLOWED);
+
+    _device_instance = M2MObject::create_object_instance();
+    if(_device_instance) {
+        _device_instance->set_operation(M2MBase::GET_ALLOWED);
+        _device_instance->set_register_uri(true);
+        _device_instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE);
+        M2MResource* res = _device_instance->create_dynamic_resource(DEVICE_REBOOT,
+                                                                     OMA_RESOURCE_TYPE,
+                                                                     M2MResourceInstance::OPAQUE,
+                                                                     false);
+        if(res) {
+            res->set_operation(M2MBase::POST_ALLOWED);
+            res->set_register_uri(false);
+        }
+
+        M2MResourceInstance* instance = _device_instance->create_dynamic_resource_instance(DEVICE_ERROR_CODE,
+                                                                 OMA_RESOURCE_TYPE,
+                                                                 M2MResourceInstance::INTEGER,
+                                                                 true,0);
+        if(instance) {
+            M2MResource * dev_res = _device_instance->resource(DEVICE_ERROR_CODE);
+            if(dev_res) {
+                dev_res->set_register_uri(false);
+            }
+            instance->set_operation(M2MBase::GET_ALLOWED);
+
+            instance->set_value(0);
+
+            instance->set_register_uri(false);
+        }
+        res = _device_instance->create_dynamic_resource(DEVICE_SUPPORTED_BINDING_MODE,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::STRING,
+                                                        true);
+        if(res) {
+            res->set_operation(M2MBase::GET_ALLOWED);
+            res->set_value((const uint8_t*)BINDING_MODE_UDP,sizeof(BINDING_MODE_UDP)-1);
+            res->set_register_uri(false);
+        }
+    }
+}
+
+M2MDevice::~M2MDevice()
+{
+}
+
+M2MResource* M2MDevice::create_resource(DeviceResource resource, const String &value)
+{
+    M2MResource* res = NULL;
+    const char* device_id_ptr = "";
+    M2MBase::Operation operation = M2MBase::GET_ALLOWED;
+    if(!is_resource_present(resource) && value.size() <= MAX_ALLOWED_STRING_LENGTH) {
+        switch(resource) {
+            case Manufacturer:
+               device_id_ptr = DEVICE_MANUFACTURER;
+               break;
+            case DeviceType:
+                device_id_ptr = DEVICE_DEVICE_TYPE;
+                break;
+            case ModelNumber:
+                device_id_ptr = DEVICE_MODEL_NUMBER;
+                break;
+            case SerialNumber:
+                device_id_ptr = DEVICE_SERIAL_NUMBER;
+                break;
+            case HardwareVersion:
+                device_id_ptr = DEVICE_HARDWARE_VERSION;
+                break;
+            case FirmwareVersion:
+                device_id_ptr = DEVICE_FIRMWARE_VERSION;
+                break;
+            case SoftwareVersion:
+                device_id_ptr = DEVICE_SOFTWARE_VERSION;
+                break;
+            case UTCOffset:
+                device_id_ptr = DEVICE_UTC_OFFSET;
+                operation = M2MBase::GET_PUT_ALLOWED;
+                break;
+            case Timezone:
+                device_id_ptr = DEVICE_TIMEZONE;
+                operation = M2MBase::GET_PUT_ALLOWED;
+                break;
+            default:
+                break;
+        }
+    }
+    const String device_id(device_id_ptr);
+
+    if(!device_id.empty()) {
+        if(_device_instance) {
+            res = _device_instance->create_dynamic_resource(device_id,
+                                                            OMA_RESOURCE_TYPE,
+                                                            M2MResourceInstance::STRING,
+                                                            true);
+
+            if(res ) {
+                res->set_operation(operation);
+                if (value.empty()) {
+                    res->clear_value();
+                } else {
+                    res->set_value((const uint8_t*)value.c_str(),
+                                   (uint32_t)value.length());
+                }
+                res->set_register_uri(false);
+            }
+        }
+    }
+    return res;
+}
+
+M2MResource* M2MDevice::create_resource(DeviceResource resource, int64_t value)
+{
+    M2MResource* res = NULL;
+    const char* device_id_ptr = "";
+    M2MBase::Operation operation = M2MBase::GET_ALLOWED;
+    if(!is_resource_present(resource)) {
+        switch(resource) {
+        case BatteryLevel:
+            if(check_value_range(resource, value)) {
+                device_id_ptr = DEVICE_BATTERY_LEVEL;
+            }
+            break;
+        case BatteryStatus:
+            if(check_value_range(resource, value)) {
+                device_id_ptr = DEVICE_BATTERY_STATUS;
+            }
+            break;
+        case MemoryFree:
+            device_id_ptr = DEVICE_MEMORY_FREE;
+            break;
+        case MemoryTotal:
+            device_id_ptr = DEVICE_MEMORY_TOTAL;
+            break;
+        case CurrentTime:
+            device_id_ptr = DEVICE_CURRENT_TIME;
+            operation = M2MBase::GET_PUT_ALLOWED;
+            break;
+        default:
+            break;
+        }
+    }
+
+    const String device_id(device_id_ptr);
+
+    if(!device_id.empty()) {
+        if(_device_instance) {
+            res = _device_instance->create_dynamic_resource(device_id,
+                                                            OMA_RESOURCE_TYPE,
+                                                            M2MResourceInstance::INTEGER,
+                                                            true);
+
+            if(res) {
+
+
+                res->set_operation(operation);
+                res->set_value(value);
+
+                res->set_register_uri(false);
+            }
+        }
+    }
+    return res;
+}
+
+M2MResourceInstance* M2MDevice::create_resource_instance(DeviceResource resource, int64_t value,
+                                                 uint16_t instance_id)
+{
+    M2MResourceInstance* res_instance = NULL;
+    const char* device_id_ptr = "";
+    // For these resources multiple instance can exist
+    if(AvailablePowerSources == resource) {
+        if(check_value_range(resource, value)) {
+            device_id_ptr = DEVICE_AVAILABLE_POWER_SOURCES;
+        }
+    } else if(PowerSourceVoltage == resource) {
+        device_id_ptr = DEVICE_POWER_SOURCE_VOLTAGE;
+    } else if(PowerSourceCurrent == resource) {
+        device_id_ptr = DEVICE_POWER_SOURCE_CURRENT;
+    } else if(ErrorCode == resource) {
+        if(check_value_range(resource, value)) {
+            device_id_ptr = DEVICE_ERROR_CODE;
+        }
+    }
+
+    const String device_id(device_id_ptr);
+
+    if(!device_id.empty()) {
+        if(_device_instance) {
+            res_instance = _device_instance->create_dynamic_resource_instance(device_id,OMA_RESOURCE_TYPE,
+                                                                     M2MResourceInstance::INTEGER,
+                                                                     true, instance_id);
+
+            M2MResource *res = _device_instance->resource(device_id);
+            if(res) {
+                res->set_register_uri(false);
+            }
+            if(res_instance) {
+                res_instance->set_value(value);
+                // Only read operation is allowed for above resources
+                res_instance->set_operation(M2MBase::GET_ALLOWED);
+
+                res_instance->set_register_uri(false);
+            }
+        }
+    }
+    return res_instance;
+}
+M2MResource* M2MDevice::create_resource(DeviceResource resource)
+{
+    M2MResource* res = NULL;
+    if(!is_resource_present(resource)) {
+        const char* device_Id_ptr = "";
+        if(FactoryReset == resource) {
+            device_Id_ptr = DEVICE_FACTORY_RESET;
+        } else if(ResetErrorCode == resource) {
+            device_Id_ptr = DEVICE_RESET_ERROR_CODE;
+        }
+        const String device_Id(device_Id_ptr);
+
+        if(_device_instance && !device_Id.empty()) {
+            res = _device_instance->create_dynamic_resource(device_Id,
+                                                            OMA_RESOURCE_TYPE,
+                                                            M2MResourceInstance::OPAQUE,
+                                                            true);
+            if(res) {
+                res->set_operation(M2MBase::POST_ALLOWED);
+                res->set_register_uri(false);
+            }
+        }
+    }
+    return res;
+}
+
+bool M2MDevice::delete_resource(DeviceResource resource)
+{
+    bool success = false;
+    if(M2MDevice::Reboot != resource             &&
+       M2MDevice::ErrorCode != resource          &&
+       M2MDevice::SupportedBindingMode != resource) {
+        if(_device_instance) {
+            success = _device_instance->remove_resource(resource_name(resource));
+        }
+    }
+    return success;
+}
+
+bool M2MDevice::delete_resource_instance(DeviceResource resource,
+                                         uint16_t instance_id)
+{
+    bool success = false;
+    if(M2MDevice::Reboot != resource             &&
+       M2MDevice::ErrorCode != resource          &&
+       M2MDevice::SupportedBindingMode != resource) {
+        if(_device_instance) {
+            success = _device_instance->remove_resource_instance(resource_name(resource),instance_id);
+        }
+    }
+    return success;
+}
+
+bool M2MDevice::set_resource_value(DeviceResource resource,
+                                   const String &value,
+                                   uint16_t instance_id)
+{
+    bool success = false;
+    M2MResourceBase* res = get_resource_instance(resource, instance_id);
+    if(res && value.size() <= MAX_ALLOWED_STRING_LENGTH) {
+        if(M2MDevice::Manufacturer == resource          ||
+           M2MDevice::ModelNumber == resource           ||
+           M2MDevice::DeviceType == resource            ||
+           M2MDevice::SerialNumber == resource          ||
+           M2MDevice::HardwareVersion == resource       ||
+           M2MDevice::FirmwareVersion == resource       ||
+           M2MDevice::SoftwareVersion == resource       ||
+           M2MDevice::UTCOffset == resource             ||
+           M2MDevice::Timezone == resource              ||
+           M2MDevice::SupportedBindingMode == resource) {
+                if (value.empty()) {
+                    res->clear_value();
+                    success = true;
+                } else {
+                    success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length());
+                }
+        }
+    }
+    return success;
+}
+
+bool M2MDevice::set_resource_value(DeviceResource resource,
+                                       int64_t value,
+                                       uint16_t instance_id)
+{
+    bool success = false;
+    M2MResourceBase* res = get_resource_instance(resource, instance_id);
+    if(res) {
+        if(M2MDevice::BatteryLevel == resource          ||
+           M2MDevice::BatteryStatus == resource         ||
+           M2MDevice::MemoryFree == resource            ||
+           M2MDevice::MemoryTotal == resource           ||
+           M2MDevice::ErrorCode == resource             ||
+           M2MDevice::CurrentTime == resource           ||
+           M2MDevice::AvailablePowerSources == resource ||
+           M2MDevice::PowerSourceVoltage == resource    ||
+           M2MDevice::PowerSourceCurrent == resource) {
+            // If it is any of the above resource
+            // set the value of the resource.
+            if (check_value_range(resource, value)) {
+
+                success = res->set_value(value);
+            }
+        }
+    }
+    return success;
+}
+
+String M2MDevice::resource_value_string(DeviceResource resource,
+                                        uint16_t instance_id) const
+{
+    String value = "";
+    const M2MResourceBase* res = get_resource_instance(resource, instance_id);
+    if(res) {
+        if(M2MDevice::Manufacturer == resource          ||
+           M2MDevice::ModelNumber == resource           ||
+           M2MDevice::DeviceType == resource            ||
+           M2MDevice::SerialNumber == resource          ||
+           M2MDevice::HardwareVersion == resource       ||
+           M2MDevice::FirmwareVersion == resource       ||
+           M2MDevice::SoftwareVersion == resource       ||
+           M2MDevice::UTCOffset == resource             ||
+           M2MDevice::Timezone == resource              ||
+           M2MDevice::SupportedBindingMode == resource) {
+
+
+            value = res->get_value_string();
+        }
+    }
+    return value;
+}
+
+int64_t M2MDevice::resource_value_int(DeviceResource resource,
+                                      uint16_t instance_id) const
+{
+    int64_t value = -1;
+    M2MResourceBase* res = get_resource_instance(resource, instance_id);
+    if(res) {
+        if(M2MDevice::BatteryLevel == resource          ||
+           M2MDevice::BatteryStatus == resource         ||
+           M2MDevice::MemoryFree == resource            ||
+           M2MDevice::MemoryTotal == resource           ||
+           M2MDevice::ErrorCode == resource             ||
+           M2MDevice::CurrentTime == resource           ||
+           M2MDevice::AvailablePowerSources == resource ||
+           M2MDevice::PowerSourceVoltage == resource    ||
+           M2MDevice::PowerSourceCurrent == resource) {
+
+            // note: the value may be 32bit int on 32b archs.
+            value = res->get_value_int();
+        }
+    }
+    return value;
+}
+
+bool M2MDevice::is_resource_present(DeviceResource resource) const
+{
+    bool success = false;
+    const M2MResourceBase* res = get_resource_instance(resource,0);
+    if(res) {
+        success = true;
+    }
+    return success;
+}
+
+uint16_t M2MDevice::per_resource_count(DeviceResource res) const
+{
+    uint16_t count = 0;
+    if(_device_instance) {
+        count = _device_instance->resource_count(resource_name(res));
+    }
+    return count;
+}
+
+uint16_t M2MDevice::total_resource_count() const
+{
+    uint16_t count = 0;
+    if(_device_instance) {
+        count = _device_instance->resources().size();
+    }
+    return count;
+}
+
+M2MResourceBase* M2MDevice::get_resource_instance(DeviceResource dev_res,
+                                                      uint16_t instance_id) const
+{
+    M2MResource* res = NULL;
+    M2MResourceBase* inst = NULL;
+    if(_device_instance) {
+        res = _device_instance->resource(resource_name(dev_res));
+        if(res) {
+            if(res->supports_multiple_instances()) {
+               inst = res->resource_instance(instance_id);
+            } else {
+                inst = res;
+            }
+        }
+    }
+    return inst;
+}
+
+const char* M2MDevice::resource_name(DeviceResource resource)
+{
+    const char* res_name = "";
+    switch(resource) {
+        case Manufacturer:
+            res_name = DEVICE_MANUFACTURER;
+            break;
+        case DeviceType:
+            res_name = DEVICE_DEVICE_TYPE;
+            break;
+        case ModelNumber:
+            res_name = DEVICE_MODEL_NUMBER;
+            break;
+        case SerialNumber:
+            res_name = DEVICE_SERIAL_NUMBER;
+            break;
+        case HardwareVersion:
+            res_name = DEVICE_HARDWARE_VERSION;
+            break;
+        case FirmwareVersion:
+            res_name = DEVICE_FIRMWARE_VERSION;
+            break;
+        case SoftwareVersion:
+            res_name = DEVICE_SOFTWARE_VERSION;
+            break;
+        case Reboot:
+            res_name = DEVICE_REBOOT;
+            break;
+        case FactoryReset:
+            res_name = DEVICE_FACTORY_RESET;
+            break;
+        case AvailablePowerSources:
+            res_name = DEVICE_AVAILABLE_POWER_SOURCES;
+            break;
+        case PowerSourceVoltage:
+            res_name = DEVICE_POWER_SOURCE_VOLTAGE;
+            break;
+        case PowerSourceCurrent:
+            res_name = DEVICE_POWER_SOURCE_CURRENT;
+            break;
+        case BatteryLevel:
+            res_name = DEVICE_BATTERY_LEVEL;
+            break;
+        case BatteryStatus:
+            res_name = DEVICE_BATTERY_STATUS;
+            break;
+        case MemoryFree:
+            res_name = DEVICE_MEMORY_FREE;
+            break;
+        case MemoryTotal:
+            res_name = DEVICE_MEMORY_TOTAL;
+            break;
+        case ErrorCode:
+            res_name = DEVICE_ERROR_CODE;
+            break;
+        case ResetErrorCode:
+            res_name = DEVICE_RESET_ERROR_CODE;
+            break;
+        case CurrentTime:
+            res_name = DEVICE_CURRENT_TIME;
+            break;
+        case UTCOffset:
+            res_name = DEVICE_UTC_OFFSET;
+            break;
+        case Timezone:
+            res_name = DEVICE_TIMEZONE;
+            break;
+        case SupportedBindingMode:
+            res_name = DEVICE_SUPPORTED_BINDING_MODE;
+            break;
+    }
+    return res_name;
+}
+
+bool M2MDevice::check_value_range(DeviceResource resource, int64_t value)
+{
+    bool success = false;
+    switch (resource) {
+        case AvailablePowerSources:
+            if(value >= 0 && value <= 7) {
+                success = true;
+            }
+            break;
+        case BatteryLevel:
+            if (value >= 0 && value <= 100) {
+                success = true;
+            }
+            break;
+        case BatteryStatus:
+            if (value >= 0 && value <= 6) {
+                success = true;
+            }
+            break;
+        case ErrorCode:
+            if (value >= 0 && value <= 8) {
+                success = true;
+            }
+            break;
+    default:
+        success = true;
+        break;
+    }
+    return success;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mendpoint.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+
+#include "mbed-client/m2mendpoint.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mconstants.h"
+#include "include/m2mtlvserializer.h"
+#include "include/m2mtlvdeserializer.h"
+#include "include/m2mreporthandler.h"
+#include "mbed-trace/mbed_trace.h"
+#include "mbed-client/m2mstringbuffer.h"
+#include "mbed-client/m2mstring.h"
+#include "nsdl-c/sn_nsdl_lib.h"
+
+#include <stdlib.h>
+
+#define BUFFER_SIZE 10
+#define TRACE_GROUP "mClt"
+
+M2MEndpoint::M2MEndpoint(const String &object_name, char *path)
+: M2MBase(object_name,
+          M2MBase::Dynamic,
+#ifndef DISABLE_RESOURCE_TYPE
+          "",
+#endif
+          path,
+          false,
+          false),
+    _observation_handler(NULL),
+    _ctx(NULL),
+    _changed(true)
+{
+    M2MBase::set_base_type(M2MBase::ObjectDirectory);
+    get_nsdl_resource()->always_publish = false;
+#ifdef RESOURCE_ATTRIBUTES_LIST
+    sn_nsdl_attribute_item_s item;
+    item.attribute_name = ATTR_ENDPOINT_NAME;
+    item.value = (char*)alloc_string_copy((uint8_t*) object_name.c_str(), object_name.length());
+    sn_nsdl_set_resource_attribute(get_nsdl_resource()->static_resource_parameters, &item);
+#endif
+}
+
+
+M2MEndpoint::~M2MEndpoint()
+{
+    tr_debug("~M2MEndpoint %p", this);
+    if(!_object_list.empty()) {
+
+        M2MObjectList::const_iterator it;
+        it = _object_list.begin();
+        M2MObject* obj = NULL;
+        uint16_t index = 0;
+        for (; it!=_object_list.end(); it++, index++ ) {
+            //Free allocated memory for object instances.
+            obj = *it;
+            tr_debug("  deleting object %p", obj);
+            delete obj;
+        }
+
+        _object_list.clear();
+    }
+
+    free_resources();
+}
+
+M2MObject* M2MEndpoint::create_object(const String &name)
+{
+    M2MObject *obj = NULL;
+    if (object(name) == NULL) {
+        char *path = create_path(*this, name.c_str());
+        obj = new M2MObject(name, path, false);
+        if (obj != NULL) {
+            _object_list.push_back(obj);
+        }
+    }
+    return obj;
+}
+
+bool M2MEndpoint::remove_object(const String &name)
+{
+    bool success = false;
+    if (object_count() == 0) {
+        return success;
+    }
+    M2MObjectList::const_iterator it;
+    M2MObject *obj = NULL;
+    int pos = 0;
+    it = _object_list.begin();
+    for (; it != _object_list.end(); it++, pos++) {
+        obj = *it;
+        if (name == obj->name()) {
+            delete obj;
+            _object_list.erase(pos);
+            success = true;
+            break;
+        }
+    }
+    return success;
+
+}
+
+M2MObject* M2MEndpoint::object(const String &name) const
+{
+    M2MObject *obj = NULL;
+    if (object_count() == 0) {
+        return obj;
+    }
+    M2MObjectList::const_iterator it = _object_list.begin();
+    for (; it != _object_list.end(); it++) {
+        if (name == (*it)->name()) {
+            obj = *it;
+            break;
+        }
+    }
+    return obj;
+}
+
+const M2MObjectList& M2MEndpoint::objects() const
+{
+    return _object_list;
+}
+
+uint16_t M2MEndpoint::object_count() const
+{
+    return _object_list.size();
+}
+
+M2MObservationHandler* M2MEndpoint::observation_handler() const
+{
+    return _observation_handler;
+}
+
+void M2MEndpoint::set_observation_handler(M2MObservationHandler *handler)
+{
+    _observation_handler = handler;
+}
+
+void M2MEndpoint::add_observation_level(M2MBase::Observation observation_level)
+{
+    (void)observation_level;
+}
+
+void M2MEndpoint::remove_observation_level(M2MBase::Observation observation_level)
+{
+    (void)observation_level;
+}
+
+sn_coap_hdr_s* M2MEndpoint::handle_get_request(nsdl_s *nsdl,
+                                             sn_coap_hdr_s *received_coap_header,
+                                             M2MObservationHandler *observation_handler)
+{
+    tr_debug("M2MEndpoint::handle_get_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+    sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
+            received_coap_header, msg_code);
+    return coap_response;
+
+}
+
+sn_coap_hdr_s* M2MEndpoint::handle_put_request(nsdl_s *nsdl,
+                                             sn_coap_hdr_s *received_coap_header,
+                                             M2MObservationHandler */*observation_handler*/,
+                                             bool &/*execute_value_updated*/)
+{
+    tr_debug("M2MEndpoint::handle_put_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+    sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
+            received_coap_header, msg_code);
+    return coap_response;
+}
+
+
+sn_coap_hdr_s* M2MEndpoint::handle_post_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler,
+                                              bool &execute_value_updated,
+                                              sn_nsdl_addr_s *)
+{
+    tr_debug("M2MEndpoint::handle_post_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+    sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
+            received_coap_header, msg_code);
+    return coap_response;
+}
+
+void M2MEndpoint::set_context(void *ctx)
+{
+    _ctx = ctx;
+}
+
+void* M2MEndpoint::get_context() const
+{
+    return _ctx;
+}
+
+void M2MEndpoint::set_changed()
+{
+    _changed = true;
+}
+
+void M2MEndpoint::clear_changed()
+{
+    _changed = false;
+}
+
+bool M2MEndpoint::get_changed() const
+{
+    return _changed;
+}
+
+#endif // MBED_CLOUD_CLIENT_EDGE_EXTENSION
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mfirmware.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,756 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#include "mbed-client/m2mfirmware.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mobjectinstance.h"
+#include "mbed-client/m2mresource.h"
+#include "include/nsdlaccesshelper.h"
+
+#define BUFFER_SIZE 21
+#define TRACE_GROUP "mClt"
+
+M2MFirmware* M2MFirmware::_instance = NULL;
+
+M2MFirmware* M2MFirmware::get_instance()
+{
+    if(_instance == NULL) {
+        _instance = new M2MFirmware();
+    }
+    return _instance;
+}
+
+void M2MFirmware::delete_instance()
+{
+    delete _instance;
+    _instance = NULL;
+}
+
+M2MFirmware::M2MFirmware()
+: M2MObject(M2M_FIRMWARE_ID, stringdup(M2M_FIRMWARE_ID))
+{
+    M2MBase::set_register_uri(false);
+    M2MBase::set_operation(M2MBase::GET_PUT_ALLOWED);
+    _firmware_instance = M2MObject::create_object_instance();
+    if(_firmware_instance) {
+        _firmware_instance->set_operation(M2MBase::GET_PUT_ALLOWED);
+        create_mandatory_resources();
+    }
+}
+
+M2MFirmware::~M2MFirmware()
+{
+}
+
+// Conditionally put the static part of parameter struct into flash.
+// Unfortunately this can't be done yet by default as there is old API which
+// may be used to modify the values in sn_nsdl_static_resource_parameters_s.
+#ifdef MEMORY_OPTIMIZED_API
+#define STATIC_PARAM_TYPE const
+#else
+#define STATIC_PARAM_TYPE
+#endif
+
+#define PACKAGE_PATH FIRMWARE_PATH_PREFIX FIRMWARE_PACKAGE
+
+#ifdef RESOURCE_ATTRIBUTES_LIST
+sn_nsdl_attribute_item_s default_attributes[2] = {
+        {ATTR_RESOURCE_TYPE, OMA_RESOURCE_TYPE},
+        {ATTR_END, 0}
+};
+#endif
+
+STATIC_PARAM_TYPE
+static sn_nsdl_static_resource_parameters_s firmware_package_params_static = {
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_RESOURCE_TYPE
+    (char*)OMA_RESOURCE_TYPE,      // resource_type_ptr
+#endif
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+    (char*)"",                     // interface_description_ptr
+#endif
+#else
+    default_attributes,
+#endif
+    (char*)PACKAGE_PATH,    // path
+//    (uint8_t*)"",           // resource
+//    0,                      // resourcelen
+    false,                  // external_memory_block
+    SN_GRS_DYNAMIC,         // mode
+    false                   // free_on_delete
+};
+
+#define PACKAGE_URI_PATH FIRMWARE_PATH_PREFIX FIRMWARE_PACKAGE_URI
+
+STATIC_PARAM_TYPE
+static sn_nsdl_static_resource_parameters_s firmware_package_uri_params_static = {
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_RESOURCE_TYPE
+    (char*)OMA_RESOURCE_TYPE,      // resource_type_ptr
+#endif
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+    (char*)"",                     // interface_description_ptr
+#endif
+#else
+    default_attributes,
+#endif
+    (char*)PACKAGE_URI_PATH, // path
+//    (uint8_t*)"",           // resource
+//    0,                      // resourcelen
+    false,                  // external_memory_block
+    SN_GRS_DYNAMIC,         // mode
+    false                   // free_on_delete
+};
+
+#define UPDATE_PATH FIRMWARE_PATH_PREFIX FIRMWARE_UPDATE
+
+STATIC_PARAM_TYPE
+static sn_nsdl_static_resource_parameters_s firmware_update_params_static = {
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_RESOURCE_TYPE
+    (char*)OMA_RESOURCE_TYPE,      // resource_type_ptr
+#endif
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+    (char*)"",                     // interface_description_ptr
+#endif
+#else
+    default_attributes,
+#endif
+    (char*)UPDATE_PATH,     // path
+//    (uint8_t*)"",           // resource
+//    0,                      // resourcelen
+    false,                  // external_memory_block
+    SN_GRS_DYNAMIC,         // mode
+    false                   // free_on_delete
+};
+
+#define STATE_URI_PATH FIRMWARE_PATH_PREFIX FIRMWARE_STATE
+
+STATIC_PARAM_TYPE
+static sn_nsdl_static_resource_parameters_s firmware_state_params_static = {
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_RESOURCE_TYPE
+    (char*)OMA_RESOURCE_TYPE,      // resource_type_ptr
+#endif
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+    (char*)"",                     // interface_description_ptr
+#endif
+#else
+    default_attributes,
+#endif
+    (char*)STATE_URI_PATH,   // path
+    false,                  // external_memory_block
+    SN_GRS_DYNAMIC,         // mode
+    false                   // free_on_delete
+};
+
+#define UPDATE_RESULT_PATH FIRMWARE_PATH_PREFIX FIRMWARE_UPDATE_RESULT
+
+STATIC_PARAM_TYPE
+static sn_nsdl_static_resource_parameters_s firmware_update_result_params_static = {
+#ifndef RESOURCE_ATTRIBUTES_LIST
+#ifndef DISABLE_RESOURCE_TYPE
+    (char*)OMA_RESOURCE_TYPE,      // resource_type_ptr
+#endif
+#ifndef DISABLE_INTERFACE_DESCRIPTION
+    (char*)"",                     // interface_description_ptr
+#endif
+#else
+    default_attributes,
+#endif
+    (char*)UPDATE_RESULT_PATH, // path
+    false,                  // external_memory_block
+    SN_GRS_DYNAMIC,         // mode
+    false                   // free_on_delete
+};
+
+static sn_nsdl_dynamic_resource_parameters_s firmware_package_params_dynamic = {
+    __nsdl_c_callback,
+    &firmware_package_params_static,
+    NULL,
+    {NULL, NULL},                     // link
+    0,
+    COAP_CONTENT_OMA_PLAIN_TEXT_TYPE, // coap_content_type
+    0, // msg_id
+    M2MBase::PUT_ALLOWED,   // access
+    0,                      // registered
+    false,                  // publish_uri
+    false,                  // free_on_delete
+    true,                   // observable
+    false,                  // auto-observable
+    NOTIFICATION_STATUS_INIT
+};
+
+static sn_nsdl_dynamic_resource_parameters_s firmware_package_uri_params_dynamic = {
+    __nsdl_c_callback,
+    &firmware_package_uri_params_static,
+    NULL,
+    {NULL, NULL},                     // link
+    0,
+    COAP_CONTENT_OMA_PLAIN_TEXT_TYPE, // coap_content_type
+    0, // msg_id
+    M2MBase::PUT_ALLOWED,   // access
+    0,                      // registered
+    false,                  // publish_uri
+    false,                  // free_on_delete
+    true,                   // observable
+    false,                  // auto-observable
+    NOTIFICATION_STATUS_INIT
+};
+
+static sn_nsdl_dynamic_resource_parameters_s firmware_update_params_dynamic = {
+    __nsdl_c_callback,
+    &firmware_update_params_static,
+    NULL,
+    {NULL, NULL},                     // link
+    0,
+    COAP_CONTENT_OMA_PLAIN_TEXT_TYPE, // coap_content_type
+    0, // msg_id
+    M2MBase::NOT_ALLOWED,   // access
+    0,                      // registered
+    false,                  // publish_uri
+    false,                  // free_on_delete
+    true,                   // observable
+    false,                  // auto-observable
+    NOTIFICATION_STATUS_INIT
+};
+
+static sn_nsdl_dynamic_resource_parameters_s firmware_state_params_dynamic = {
+    __nsdl_c_callback,
+    &firmware_state_params_static,
+    NULL,                   // resource
+    {NULL, NULL},           // link
+    0,                      // resourcelen
+    COAP_CONTENT_OMA_PLAIN_TEXT_TYPE, // coap_content_type
+    0, // msg_id
+    M2MBase::GET_ALLOWED,   // access
+    0,                      // registered
+    false,                  // publish_uri
+    false,                  // free_on_delete
+    true,                   // observable
+    false,                  // auto-observable
+    NOTIFICATION_STATUS_INIT
+};
+
+static sn_nsdl_dynamic_resource_parameters_s firmware_update_result_params_dynamic = {
+    __nsdl_c_callback,
+    &firmware_update_result_params_static,
+    NULL,                   // resource
+    {NULL, NULL},           // link
+    0,                      // resourcelen
+    COAP_CONTENT_OMA_PLAIN_TEXT_TYPE, // coap_content_type
+    0, // msg_id
+    M2MBase::GET_ALLOWED,   // access
+    0,                      // registered
+    false,                  // publish_uri
+    false,                  // free_on_delete
+    true,                   // observable
+    false,                  // auto-observable
+    NOTIFICATION_STATUS_INIT
+};
+
+const static M2MBase::lwm2m_parameters firmware_package_params = {
+    0, // max_age
+    (char*)FIRMWARE_PACKAGE,
+    &firmware_package_params_dynamic,
+    M2MBase::Resource, // base_type
+    M2MBase::OPAQUE,
+    false,
+    false, // free_on_delete
+    false  // identifier_int_type
+};
+
+const static M2MBase::lwm2m_parameters firmware_package_uri_params = {
+    0, // max_age
+    (char*)FIRMWARE_PACKAGE_URI,
+    &firmware_package_uri_params_dynamic,
+    M2MBase::Resource, // base_type
+    M2MBase::STRING,
+    false,
+    false, // free_on_delete
+    false  // identifier_int_type
+};
+
+const static M2MBase::lwm2m_parameters firmware_update_params = {
+    0, // max_age
+    (char*)FIRMWARE_UPDATE,
+    &firmware_update_params_dynamic,
+    M2MBase::Resource, // base_type
+    M2MBase::OPAQUE,
+    false,
+    false, // free_on_delete
+    false  // identifier_int_type
+};
+
+const static M2MBase::lwm2m_parameters firmware_state_params = {
+    0, // max_age
+    (char*)FIRMWARE_STATE,
+    &firmware_state_params_dynamic,
+    M2MBase::Resource, // base_type
+    M2MBase::INTEGER,
+    false,
+    false, // free_on_delete
+    false  // identifier_int_type
+};
+
+const static M2MBase::lwm2m_parameters firmware_update_result_params = {
+    0, // max_age
+    (char*)FIRMWARE_UPDATE_RESULT,
+    &firmware_update_result_params_dynamic,
+    M2MBase::Resource, // base_type
+    M2MBase::INTEGER,
+    false,
+    false, // free_on_delete
+    false  // identifier_int_type
+};
+
+void M2MFirmware::create_mandatory_resources()
+{
+    _firmware_instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE);
+
+    M2MResource* res;
+
+    // todo:
+    // perhaps we should have a API for batch creation of objects by using a array
+    // of lwm2m_parameters.
+    res = _firmware_instance->create_dynamic_resource(&firmware_package_params,
+                                                        M2MResourceInstance::OPAQUE,
+                                                        false);
+
+    res = _firmware_instance->create_dynamic_resource(&firmware_package_uri_params,
+                                                    M2MResourceInstance::STRING,
+                                                    false);
+
+    res = _firmware_instance->create_dynamic_resource(&firmware_update_params,
+                                                    M2MResourceInstance::OPAQUE,
+                                                    false);
+
+    res = _firmware_instance->create_dynamic_resource(&firmware_state_params,
+                                                    M2MResourceInstance::INTEGER,
+                                                    true);
+
+    // XXX: some of the tests expect to have some value available here
+    if (res) {
+        res->set_value(0);
+    }
+
+    res = _firmware_instance->create_dynamic_resource(&firmware_update_result_params,
+                                                    M2MResourceInstance::INTEGER,
+                                                    true);
+
+    // XXX: some of the tests expect to have some value available here
+    if (res) {
+        res->set_value(0);
+    }
+}
+
+M2MResource* M2MFirmware::create_resource(FirmwareResource resource, const String &value)
+{
+    M2MResource* res = NULL;
+    const char* firmware_id_ptr = "";
+    M2MBase::Operation operation = M2MBase::GET_ALLOWED;
+    if(!is_resource_present(resource)) {
+        switch(resource) {
+            case PackageName:
+                firmware_id_ptr = FIRMWARE_PACKAGE_NAME;
+                break;
+            case PackageVersion:
+                firmware_id_ptr = FIRMWARE_PACKAGE_VERSION;
+                break;
+            default:
+                break;
+        }
+    }
+    String firmware_id(firmware_id_ptr);
+
+    if(!firmware_id.empty() && value.size() < 256) {
+        if(_firmware_instance) {
+            res = _firmware_instance->create_dynamic_resource(firmware_id,
+                                                            OMA_RESOURCE_TYPE,
+                                                            M2MResourceInstance::STRING,
+                                                            false);
+
+            if(res) {
+                res->set_register_uri(false);
+                res->set_operation(operation);
+                if(value.empty()) {
+                    res->clear_value();
+                } else {
+                    res->set_value((const uint8_t*)value.c_str(),
+                                   (uint32_t)value.length());
+                }
+            }
+        }
+    }
+    return res;
+}
+
+M2MResource* M2MFirmware::create_resource(FirmwareResource resource, int64_t value)
+{
+    M2MResource* res = NULL;
+    const char* firmware_id_ptr = "";
+    M2MBase::Operation operation = M2MBase::GET_ALLOWED;
+    if(!is_resource_present(resource)) {
+        switch(resource) {
+        case UpdateSupportedObjects:
+            if(check_value_range(resource, value)) {
+                firmware_id_ptr = FIRMWARE_UPDATE_SUPPORTED_OBJECTS;
+                operation = M2MBase::GET_PUT_ALLOWED;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+
+    const String firmware_id(firmware_id_ptr);
+
+    if(!firmware_id.empty()) {
+        if(_firmware_instance) {
+            res = _firmware_instance->create_dynamic_resource(firmware_id,
+                                                            OMA_RESOURCE_TYPE,
+                                                            M2MResourceInstance::INTEGER,
+                                                            false);
+
+            if(res) {
+                res->set_register_uri(false);
+
+                res->set_operation(operation);
+                res->set_value(value);
+            }
+        }
+    }
+    return res;
+}
+
+bool M2MFirmware::set_resource_value(FirmwareResource resource,
+                                   const String &value)
+{
+    bool success = false;
+    M2MResource* res = get_resource(resource);
+    if(res) {
+        if(M2MFirmware::PackageUri == resource  ||
+           M2MFirmware::PackageName == resource ||
+           M2MFirmware::PackageVersion == resource) {
+            if (value.size() < 256) {
+                if(value.empty()) {
+                    res->clear_value();
+                    success = true;
+                } else {
+                    success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length());
+                }
+            }
+        }
+    }
+    return success;
+}
+
+bool M2MFirmware::set_resource_value(FirmwareResource resource,
+                                       int64_t value)
+{
+    bool success = false;
+    M2MResource* res = get_resource(resource);
+    if(res) {
+        if(M2MFirmware::State == resource          ||
+           M2MFirmware::UpdateSupportedObjects == resource ||
+           M2MFirmware::UpdateResult == resource) {
+            // If it is any of the above resource
+            // set the value of the resource.
+            if (check_value_range(resource, value)) {
+
+                success = res->set_value(value);
+            }
+        }
+    }
+    return success;
+}
+
+bool M2MFirmware::set_resource_value(FirmwareResource resource,
+                                     const uint8_t *value,
+                                     const uint32_t length)
+{
+    bool success = false;
+    M2MResource* res = get_resource(resource);
+    if(res) {
+        if(M2MFirmware::Package == resource) {
+            success = res->set_value(value,length);
+        }
+    }
+    return success;
+}
+
+bool M2MFirmware::is_resource_present(FirmwareResource resource) const
+{
+    bool success = false;
+    M2MResource* res = get_resource(resource);
+    if(res) {
+        success = true;
+    }
+    return success;
+}
+
+const char* M2MFirmware::resource_name(FirmwareResource resource)
+{
+    const char* res_name = "";
+    switch(resource) {
+        case Package:
+            res_name = FIRMWARE_PACKAGE;
+            break;
+        case PackageUri:
+            res_name = FIRMWARE_PACKAGE_URI;
+            break;
+        case Update:
+            res_name = FIRMWARE_UPDATE;
+            break;
+        case State:
+            res_name = FIRMWARE_STATE;
+            break;
+        case UpdateSupportedObjects:
+            res_name = FIRMWARE_UPDATE_SUPPORTED_OBJECTS;
+            break;
+        case UpdateResult:
+            res_name = FIRMWARE_UPDATE_RESULT;
+            break;
+        case PackageName:
+            res_name = FIRMWARE_PACKAGE_NAME;
+            break;
+        case PackageVersion:
+            res_name = FIRMWARE_PACKAGE_VERSION;
+            break;
+    }
+    return res_name;
+}
+
+uint16_t M2MFirmware::per_resource_count(FirmwareResource res) const
+{
+    uint16_t count = 0;
+    if(_firmware_instance) {
+        count = _firmware_instance->resource_count(resource_name(res));
+    }
+    return count;
+}
+
+uint16_t M2MFirmware::total_resource_count() const
+{
+    uint16_t count = 0;
+    if(_firmware_instance) {
+        count = _firmware_instance->resources().size();
+    }
+    return count;
+}
+
+uint32_t M2MFirmware::resource_value_buffer(FirmwareResource resource,
+                               uint8_t *&data) const
+{
+    uint32_t size = 0;
+    M2MResource* res = get_resource(resource);
+    if(res) {
+        if(M2MFirmware::Package == resource) {
+            res->get_value(data,size);
+        }
+    }
+    return size;
+}
+
+M2MResource* M2MFirmware::get_resource(FirmwareResource res) const
+{
+    M2MResource* res_object = NULL;
+    if(_firmware_instance) {
+        const char* res_name_ptr = "";
+        switch(res) {
+            case Package:
+                res_name_ptr = FIRMWARE_PACKAGE;
+                break;
+            case PackageUri:
+                res_name_ptr = FIRMWARE_PACKAGE_URI;
+                break;
+            case Update:
+                res_name_ptr = FIRMWARE_UPDATE;
+                break;
+            case State:
+                res_name_ptr = FIRMWARE_STATE;
+                break;
+            case UpdateSupportedObjects:
+                res_name_ptr = FIRMWARE_UPDATE_SUPPORTED_OBJECTS;
+                break;
+            case UpdateResult:
+                res_name_ptr = FIRMWARE_UPDATE_RESULT;
+                break;
+            case PackageName:
+                res_name_ptr = FIRMWARE_PACKAGE_NAME;
+                break;
+            case PackageVersion:
+                res_name_ptr = FIRMWARE_PACKAGE_VERSION;
+                break;
+        }
+
+        res_object = _firmware_instance->resource(res_name_ptr);
+    }
+    return res_object;
+}
+
+bool M2MFirmware::delete_resource(FirmwareResource resource)
+{
+    bool success = false;
+    if(M2MFirmware::UpdateSupportedObjects == resource ||
+       M2MFirmware::PackageName == resource            ||
+       M2MFirmware::PackageVersion == resource) {
+        if(_firmware_instance) {
+            success = _firmware_instance->remove_resource(resource_name(resource));
+        }
+    }
+    return success;
+}
+
+int64_t M2MFirmware::resource_value_int(FirmwareResource resource) const
+{
+    int64_t value = -1;
+    M2MResource* res = get_resource(resource);
+    if(res) {
+        if(M2MFirmware::State == resource          ||
+           M2MFirmware::UpdateSupportedObjects == resource         ||
+           M2MFirmware::UpdateResult == resource) {
+
+            value = res->get_value_int();
+        }
+    }
+    return value;
+}
+
+String M2MFirmware::resource_value_string(FirmwareResource resource) const
+{
+    String value = "";
+    M2MResource* res = get_resource(resource);
+    if(res) {
+        if(M2MFirmware::PackageUri == resource          ||
+           M2MFirmware::PackageName == resource           ||
+           M2MFirmware::PackageVersion == resource) {
+
+            value = res->get_value_string();
+        }
+    }
+    return value;
+}
+
+bool M2MFirmware::check_value_range(FirmwareResource resource, int64_t value) const
+{
+    bool success = false;
+    switch (resource) {
+        case UpdateSupportedObjects:
+            if(value == 0 || value == 1) {
+                success = true;
+            }
+            break;
+        case State:
+            if (value >= 0 && value <= 3) {
+                success = true;
+                M2MResource* updateRes = get_resource(M2MFirmware::Update);
+                if (updateRes){
+                    if (value == M2MFirmware::Downloaded) {
+                        updateRes->set_operation(M2MBase::POST_ALLOWED);
+                    }
+                    else {
+                        updateRes->set_operation(M2MBase::NOT_ALLOWED);
+                    }
+                }
+            }
+            break;
+        case UpdateResult:
+            if (value >= 0 && value <= 7) {
+                success = true;
+            }
+            break;
+    default:
+        break;
+    }
+    return success;
+}
+
+bool M2MFirmware::set_update_execute_callback(execute_callback callback)
+{
+    M2MResource* m2mresource;
+
+    m2mresource = get_resource(Update);
+
+    if(m2mresource) {
+        m2mresource->set_execute_function(callback);
+        return true;
+    }
+
+    return false;
+}
+
+bool M2MFirmware::set_resource_value_update_callback(FirmwareResource resource,
+                                        value_updated_callback callback)
+{
+    M2MResource* m2mresource;
+
+    m2mresource = get_resource(resource);
+
+    if(m2mresource) {
+        m2mresource->set_value_updated_function(callback);
+        return true;
+    }
+
+    return false;
+}
+
+bool M2MFirmware::set_resource_notification_sent_callback(FirmwareResource resource,
+                                             notification_sent_callback_2 callback)
+{
+    M2MResource* m2mresource;
+
+    m2mresource = get_resource(resource);
+
+    if(m2mresource) {
+        m2mresource->set_notification_sent_callback(callback);
+        return true;
+    }
+
+    return false;
+}
+
+bool M2MFirmware::set_resource_notification_sent_callback(FirmwareResource resource,
+                                             notification_delivery_status_cb callback)
+{
+    M2MResource* m2mresource;
+
+    m2mresource = get_resource(resource);
+
+    if(m2mresource) {
+        m2mresource->set_notification_delivery_status_cb(callback, 0);
+        return true;
+    }
+
+    return false;
+}
+
+#ifndef DISABLE_BLOCK_MESSAGE
+bool M2MFirmware::set_package_block_message_callback(incoming_block_message_callback callback)
+{
+    M2MResource* m2mresource;
+
+    m2mresource = get_resource(Package);
+
+    if(m2mresource) {
+        m2mresource->set_incoming_block_message_callback(callback);
+        return true;
+    }
+
+    return false;
+}
+#endif // DISABLE_BLOCK_MESSAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2minterfacefactory.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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 macro is needed on armcc to get the the PRI*32 macros
+// from inttypes.h in a C++ code.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include "mbed-client/m2minterfacefactory.h"
+#include "mbed-client/m2mserver.h"
+#include "mbed-client/m2mdevice.h"
+#include "mbed-client/m2mfirmware.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mendpoint.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2mconfig.h"
+#include "include/m2minterfaceimpl.h"
+#include "mbed-trace/mbed_trace.h"
+
+#include <inttypes.h>
+
+#define TRACE_GROUP "mClt"
+
+M2MInterface* M2MInterfaceFactory::create_interface(M2MInterfaceObserver &observer,
+                                                    const String &endpoint_name,
+                                                    const String &endpoint_type,
+                                                    const int32_t life_time,
+                                                    const uint16_t listen_port,
+                                                    const String &domain,
+                                                    M2MInterface::BindingMode mode,
+                                                    M2MInterface::NetworkStack stack,
+                                                    const String &context_address)
+{
+    tr_debug("M2MInterfaceFactory::create_interface - IN");
+    tr_info("M2MInterfaceFactory::create_interface - parameters endpoint name : %s",endpoint_name.c_str());
+    tr_info("M2MInterfaceFactory::create_interface - parameters endpoint type : %s",endpoint_type.c_str());
+    tr_info("M2MInterfaceFactory::create_interface - parameters life time(in secs): %" PRId32,life_time);
+    tr_info("M2MInterfaceFactory::create_interface - parameters Listen Port : %d",listen_port);
+    tr_info("M2MInterfaceFactory::create_interface - parameters Binding Mode : %d",(int)mode);
+    tr_info("M2MInterfaceFactory::create_interface - parameters NetworkStack : %d",(int)stack);
+    M2MInterfaceImpl *interface = NULL;
+
+
+    bool endpoint_type_valid = true;
+    if(!endpoint_type.empty()) {
+        if(endpoint_type.size() > MAX_ALLOWED_STRING_LENGTH){
+            endpoint_type_valid = false;
+        }
+    }
+
+    bool domain_valid = true;
+    if(!domain.empty()) {
+        if(domain.size() > MAX_ALLOWED_STRING_LENGTH){
+            domain_valid = false;
+        }
+    }
+
+    if(((life_time == -1) || (life_time >= MINIMUM_REGISTRATION_TIME)) &&
+       !endpoint_name.empty() && (endpoint_name.size() <= MAX_ALLOWED_STRING_LENGTH) &&
+       endpoint_type_valid && domain_valid) {
+        tr_debug("M2MInterfaceFactory::create_interface - Creating M2MInterfaceImpl");
+        interface = new M2MInterfaceImpl(observer, endpoint_name,
+                                         endpoint_type, life_time,
+                                         listen_port, domain, mode,
+                                         stack, context_address);
+
+    }
+    tr_debug("M2MInterfaceFactory::create_interface - OUT");
+    return interface;
+}
+
+M2MSecurity* M2MInterfaceFactory::create_security(M2MSecurity::ServerType server_type)
+{
+    tr_debug("M2MInterfaceFactory::create_security");
+    M2MSecurity *security = M2MSecurity::get_instance();
+    return security;
+}
+
+M2MServer* M2MInterfaceFactory::create_server()
+{
+    tr_debug("M2MInterfaceFactory::create_server");
+    M2MServer *server = new M2MServer();
+    return server;
+}
+
+M2MDevice* M2MInterfaceFactory::create_device()
+{
+    tr_debug("M2MInterfaceFactory::create_device");
+    M2MDevice* device = M2MDevice::get_instance();
+    return device;
+}
+
+M2MFirmware* M2MInterfaceFactory::create_firmware()
+{
+    tr_debug("M2MInterfaceFactory::create_firmware");
+    M2MFirmware* firmware = M2MFirmware::get_instance();
+    return firmware;
+}
+
+M2MObject* M2MInterfaceFactory::create_object(const String &name)
+{
+    tr_debug("M2MInterfaceFactory::create_object : Name : %s", name.c_str());
+    if(name.size() > MAX_ALLOWED_STRING_LENGTH || name.empty()){
+        return NULL;
+    }
+
+    M2MObject *object = NULL;
+    char *name_copy = M2MBase::stringdup(name.c_str());
+    if (name_copy) {
+        object = new M2MObject(name, name_copy);
+    }
+    return object;
+}
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+M2MEndpoint* M2MInterfaceFactory::create_endpoint(const String &name)
+{
+    tr_debug("M2MInterfaceFactory::create_endpoint : Name : %s", name.c_str());
+    if(name.size() > MAX_ALLOWED_STRING_LENGTH || name.empty()){
+        return NULL;
+    }
+
+    M2MEndpoint *object = NULL;
+    char *path = (char*)malloc(2 + name.size() + 1);
+    if (path) {
+        // Prepend path with directory prefix "d/" so that all endpoints will be under common path
+        path[0] = 'd';
+        path[1] = '/';
+        memcpy(&path[2], name.c_str(), name.size());
+        path[name.size() + 2] = '\0';
+        object = new M2MEndpoint(name, path);
+    }
+    return object;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2minterfaceimpl.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1349 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+// Needed for PRIu64 on FreeRTOS
+#include <stdio.h>
+// Note: this macro is needed on armcc to get the the PRI*32 macros
+// from inttypes.h in a C++ code.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+#include <inttypes.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include "include/m2minterfaceimpl.h"
+#include "include/eventdata.h"
+#include "mbed-client/m2minterfaceobserver.h"
+#include "mbed-client/m2mconnectionhandler.h"
+#include "mbed-client/m2mconnectionsecurity.h"
+#include "include/m2mnsdlinterface.h"
+#include "mbed-client/m2msecurity.h"
+#include "mbed-client/m2mtimer.h"
+#include "mbed-trace/mbed_trace.h"
+#include "randLIB.h"
+
+#include <stdlib.h>
+
+#define TRACE_GROUP "mClt"
+
+#define RESOLVE_SEC_MODE(mode)  ((mode == M2MInterface::TCP || mode == M2MInterface::TCP_QUEUE) ? M2MConnectionSecurity::TLS : M2MConnectionSecurity::DTLS)
+
+M2MInterfaceImpl::M2MInterfaceImpl(M2MInterfaceObserver& observer,
+                                   const String &ep_name,
+                                   const String &ep_type,
+                                   const int32_t l_time,
+                                   const uint16_t listen_port,
+                                   const String &dmn,
+                                   M2MInterface::BindingMode mode,
+                                   M2MInterface::NetworkStack stack,
+                                   const String &con_addr)
+: _event_data(NULL),
+  _registration_flow_timer(NULL),
+  _server_port(0),
+  _listen_port(listen_port),
+  _life_time(l_time),
+  _register_server(NULL),
+  _queue_sleep_timer(*this),
+  _retry_timer(*this),
+  _callback_handler(NULL),
+  _max_states( STATE_MAX_STATES ),
+  _event_ignored(false),
+  _event_generated(false),
+  _reconnecting(false),
+  _retry_timer_expired(false),
+  _bootstrapped(true), // True as default to get it working with connector only configuration
+  _bootstrap_finished(false),
+  _queue_mode_timer_ongoing(false),
+  _current_state(0),
+  _binding_mode(mode),
+  _reconnection_state(M2MInterfaceImpl::None),
+  _observer(observer),
+  _security_connection( new M2MConnectionSecurity( RESOLVE_SEC_MODE(mode) )),
+  _connection_handler(*this, _security_connection, mode, stack),
+  _nsdl_interface(*this, _connection_handler),
+  _security(NULL)
+{
+    tr_debug("M2MInterfaceImpl::M2MInterfaceImpl() -IN");
+    //TODO:Increase the range from 1 to 100 seconds
+    randLIB_seed_random();
+    // Range is from 2 to 10
+    _initial_reconnection_time = randLIB_get_random_in_range(2, 10);
+
+    tr_info("M2MInterfaceImpl::M2MInterfaceImpl() initial random time %d\n", _initial_reconnection_time);
+    _reconnection_time = _initial_reconnection_time;
+
+#ifndef DISABLE_ERROR_DESCRIPTION
+    memset(_error_description, 0, sizeof(_error_description));
+#endif
+
+    _nsdl_interface.create_endpoint(ep_name,
+                                     ep_type,
+                                     _life_time,
+                                     dmn,
+                                     (uint8_t)_binding_mode,
+                                     con_addr);
+
+    //Here we must use TCP still
+    _connection_handler.bind_connection(_listen_port);
+
+    // We need this timer only in case of TCP
+    if (_binding_mode == M2MInterface::TCP ||
+        _binding_mode == M2MInterface::TCP_QUEUE ) {
+        _registration_flow_timer = new M2MTimer(*this);
+    }
+    tr_debug("M2MInterfaceImpl::M2MInterfaceImpl() -OUT");
+}
+
+
+M2MInterfaceImpl::~M2MInterfaceImpl()
+{
+    tr_debug("M2MInterfaceImpl::~M2MInterfaceImpl() - IN");
+    delete _registration_flow_timer;
+    _security_connection = NULL;
+    tr_debug("M2MInterfaceImpl::~M2MInterfaceImpl() - OUT");
+}
+
+void M2MInterfaceImpl::bootstrap(M2MSecurity *security)
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_debug("M2MInterfaceImpl::bootstrap - IN - current state %d", _current_state);
+    _retry_timer.stop_timer();
+    _security = NULL;
+    if(!security) {
+        set_error_description(ERROR_REASON_1);
+        _observer.error(M2MInterface::InvalidParameters);
+        return;
+    }
+    // Transition to a new state based upon
+    // the current state of the state machine
+    _connection_handler.claim_mutex();
+    M2MSecurityData data;
+    data._object = security;
+    BEGIN_TRANSITION_MAP                                    // - Current State -
+        TRANSITION_MAP_ENTRY (STATE_BOOTSTRAP)              // state_idle
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_wait
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_error_wait
+        TRANSITION_MAP_ENTRY (STATE_BOOTSTRAP)              // state_bootstrapped
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_registered
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_waiting
+    END_TRANSITION_MAP(&data)
+    if(_event_ignored) {
+        _event_ignored = false;
+        set_error_description(ERROR_REASON_2);
+        _observer.error(M2MInterface::NotAllowed);
+    }
+    _connection_handler.release_mutex();
+    tr_debug("M2MInterfaceImpl::bootstrap - OUT");
+#else
+    set_error_description(ERROR_REASON_3);
+    _observer.error(M2MInterface::NotAllowed);
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+
+}
+
+void M2MInterfaceImpl::cancel_bootstrap()
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+//TODO: Do we need this ?
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+void M2MInterfaceImpl::finish_bootstrap()
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_debug("M2MInterfaceImpl::finish_bootstrap");
+    _security = NULL;
+    bootstrap_done();
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+void M2MInterfaceImpl::register_object(M2MSecurity *security, const M2MObjectList &object_list)
+{
+    M2MBaseList list;
+    M2MObjectList::const_iterator it = object_list.begin();
+    for ( ; it != object_list.end(); it++ ) {
+        list.push_back(*it);
+    }
+    register_object(security, list);
+}
+
+void M2MInterfaceImpl::register_object(M2MSecurity *security, const M2MBaseList &list)
+{
+    tr_debug("M2MInterfaceImpl::register_object - IN - current state %d", _current_state);
+    if(!security) {
+        set_error_description(ERROR_REASON_4);
+        _observer.error(M2MInterface::InvalidParameters);
+        return;
+    }
+    // Transition to a new state based upon
+    // the current state of the state machine
+    //TODO: manage register object in a list.
+    _connection_handler.claim_mutex();
+    _register_server = security;
+    M2MRegisterData data;
+    data._object = security;
+    data._base_list = list;
+    BEGIN_TRANSITION_MAP                                    // - Current State -
+        TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_idle
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_wait
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_error_wait
+        TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_bootstrapped
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
+        TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_registered
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
+        TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_waiting
+    END_TRANSITION_MAP(&data)
+    if(_event_ignored) {
+        _event_ignored = false;
+        set_error_description(ERROR_REASON_5);
+        _observer.error(M2MInterface::NotAllowed);
+    }
+    _connection_handler.release_mutex();
+    tr_debug("M2MInterfaceImpl::register_object - OUT");
+}
+
+void M2MInterfaceImpl::update_registration(M2MSecurity *security_object, const uint32_t lifetime)
+{
+    tr_debug("M2MInterfaceImpl::update_registration()");
+    _connection_handler.claim_mutex();
+    M2MUpdateRegisterData data;
+    data._object = security_object;
+    data._lifetime = lifetime;
+    start_register_update(&data);
+    _connection_handler.release_mutex();
+}
+
+void M2MInterfaceImpl::update_registration(M2MSecurity *security_object,
+                                           const M2MObjectList &object_list,
+                                           const uint32_t lifetime)
+{
+    tr_debug("M2MInterfaceImpl::update_registration - with object list");
+    _connection_handler.claim_mutex();
+    M2MBaseList list;
+    M2MObjectList::const_iterator it = object_list.begin();
+    for ( ; it != object_list.end(); it++ ) {
+        list.push_back(*it);
+    }
+    update_registration(security_object, list, lifetime);
+    _connection_handler.release_mutex();
+}
+
+void M2MInterfaceImpl::update_registration(M2MSecurity *security_object,
+                                           const M2MBaseList &list,
+                                           const uint32_t lifetime)
+{
+    tr_debug("M2MInterfaceImpl::update_registration(M2MSecurity *security_object, const M2MObjectList &object_list, const uint32_t lifetime)");
+    _connection_handler.claim_mutex();
+    M2MUpdateRegisterData data;
+    data._object = security_object;
+    data._lifetime = lifetime;
+    data._base_list = list;
+    start_register_update(&data);
+    _connection_handler.release_mutex();
+}
+
+void M2MInterfaceImpl::unregister_object(M2MSecurity* /*security*/)
+{
+    tr_debug("M2MInterfaceImpl::unregister_object - IN - current state %d", _current_state);
+    if (_nsdl_interface.is_unregister_ongoing()) {
+        set_error_description(ERROR_REASON_27);
+        _observer.error(M2MInterface::NotAllowed);
+        return;
+    }
+
+    _connection_handler.claim_mutex();
+    // Transition to a new state based upon
+    // the current state of the state machine
+    BEGIN_TRANSITION_MAP                                // - Current State -
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTERED)                // state_idle
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTERED)           // state_bootstrap
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTERED)           // state__bootstrap_address_resolved
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTERED)           // state_bootstrap_resource_created
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTERED)           // state_bootstrap_wait
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTERED)           // state_bootstrap_error_wait
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTERED)           // state_bootstrapped
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTERED)           // state_register
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTERED)           // state_register_address_resolved
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_registered
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_update_registration
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_sending_coap_data
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_coap_data_sent
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_coap_data_received
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_processing_coap_data
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_coap_data_processed
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_waiting
+    END_TRANSITION_MAP(NULL)
+
+    _connection_handler.release_mutex();
+    tr_debug("M2MInterfaceImpl::unregister_object - OUT");
+}
+
+void M2MInterfaceImpl::set_queue_sleep_handler(callback_handler handler)
+{
+    _callback_handler = handler;
+}
+
+void M2MInterfaceImpl::set_random_number_callback(random_number_cb callback)
+{
+    if(_security_connection) {
+        _security_connection->set_random_number_callback(callback);
+    }
+}
+
+void M2MInterfaceImpl::set_entropy_callback(entropy_cb callback)
+{
+    if(_security_connection) {
+        _security_connection->set_entropy_callback(callback);
+    }
+}
+
+void M2MInterfaceImpl::set_platform_network_handler(void *handler)
+{
+    _connection_handler.set_platform_network_handler(handler);
+}
+
+void M2MInterfaceImpl::coap_message_ready(uint8_t *data_ptr,
+                                          uint16_t data_len,
+                                          sn_nsdl_addr_s *address_ptr)
+{
+    tr_debug("M2MInterfaceImpl::coap_message_ready");
+    if (_current_state != STATE_IDLE) {
+        internal_event(STATE_SENDING_COAP_DATA);
+        if(!_connection_handler.send_data(data_ptr,data_len,address_ptr)) {
+            internal_event( STATE_IDLE);
+            tr_error("M2MInterfaceImpl::coap_message_ready() - M2MInterface::NetworkError");
+            if (!_reconnecting) {
+                _queue_mode_timer_ongoing = false;
+                socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR, true);
+            } else {
+                socket_error(M2MConnectionHandler::SOCKET_ABORT);
+            }
+        }
+    }
+}
+
+void M2MInterfaceImpl::client_registered(M2MServer *server_object)
+{
+    tr_info("M2MInterfaceImpl::client_registered");
+    internal_event(STATE_REGISTERED);
+    //Inform client is registered.
+    //TODO: manage register object in a list.
+    _observer.object_registered(_register_server,*server_object);
+}
+
+void M2MInterfaceImpl::registration_updated(const M2MServer &server_object)
+{
+    tr_info("M2MInterfaceImpl::registration_updated");
+    internal_event(STATE_REGISTERED);
+    _observer.registration_updated(_register_server,server_object);
+}
+
+void M2MInterfaceImpl::registration_error(uint8_t error_code, bool retry)
+{
+    tr_error("M2MInterfaceImpl::registration_error code [%d]", error_code);
+
+    _nsdl_interface.set_registration_status(false);
+    // Try to register again
+    if (retry) {
+        _queue_mode_timer_ongoing = false;
+        if (error_code == M2MInterface::UnregistrationFailed) {
+            _reconnection_state = M2MInterfaceImpl::Unregistration;
+        }
+
+        socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR);
+    } else {
+        _security = NULL;
+        internal_event(STATE_IDLE);
+        if (error_code == M2MInterface::UnregistrationFailed) {
+            set_error_description(ERROR_REASON_24);
+        } else {
+            set_error_description(ERROR_REASON_8);
+        }
+        _observer.error((M2MInterface::Error)error_code);
+    }
+}
+
+void M2MInterfaceImpl::client_unregistered()
+{
+    tr_info("M2MInterfaceImpl::client_unregistered()");
+    _nsdl_interface.set_registration_status(false);
+
+    // Zero the flag otherwise next registered response will start unregistration process
+    _reconnection_state = M2MInterfaceImpl::None;
+
+    internal_event(STATE_UNREGISTERED);
+    //TODO: manage register object in a list.
+}
+
+void M2MInterfaceImpl::bootstrap_done()
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_info("M2MInterfaceImpl::bootstrap_done");
+    _reconnection_time = _initial_reconnection_time;
+    _reconnecting = false;
+    _reconnection_state = M2MInterfaceImpl::None;
+    _bootstrapped = true;
+
+    if (_registration_flow_timer) {
+        _registration_flow_timer->stop_timer();
+    }
+
+    // Force close connection since either server already closed (sent PEER_CLOSE_NOTIFY)
+    // or bootstrap flow has finished.
+    _connection_handler.force_close();
+
+    if (_bootstrap_finished) {
+        // Inform to observer only if bootstrap has already been finished
+        // This has to be done like this since we might get bootstrap_done
+        // callback BEFORE bootstrap_finish
+        internal_event(STATE_BOOTSTRAPPED);
+        _observer.bootstrap_done(_nsdl_interface.get_security_object());
+    }
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+void M2MInterfaceImpl::bootstrap_finish()
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_info("M2MInterfaceImpl::bootstrap_finish");
+    internal_event(STATE_BOOTSTRAP_WAIT);
+    _observer.bootstrap_data_ready(_nsdl_interface.get_security_object());
+    _bootstrap_finished = true;
+
+    if (_bootstrapped) {
+        // If _bootstrapped is set, we have already received the bootstrap_done
+        // callback so we must inform observer now
+        bootstrap_done();
+    }
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+void M2MInterfaceImpl::bootstrap_wait()
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_info("M2MInterfaceImpl::bootstrap_wait");
+    internal_event(STATE_BOOTSTRAP_WAIT);
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+void M2MInterfaceImpl::bootstrap_error_wait(const char *reason)
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_error("M2MInterfaceImpl::bootstrap_error_wait");
+    set_error_description(reason);
+    internal_event(STATE_BOOTSTRAP_ERROR_WAIT);
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+void M2MInterfaceImpl::bootstrap_error(const char *reason)
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_error("M2MInterfaceImpl::bootstrap_error(%s)", reason);
+    _bootstrapped = false;
+    if (_registration_flow_timer) {
+        _registration_flow_timer->stop_timer();
+    }
+
+    _reconnection_state = M2MInterfaceImpl::None;
+
+    set_error_description(reason);
+
+    _observer.error(M2MInterface::BootstrapFailed);
+
+    internal_event(STATE_IDLE);
+    _reconnecting = true;
+    _connection_handler.stop_listening();
+
+    _retry_timer_expired = false;
+    _retry_timer.start_timer(_reconnection_time * 1000,
+                              M2MTimerObserver::RetryTimer);
+    tr_info("M2MInterfaceImpl::bootstrap_error - reconnecting in %" PRIu64 "(s)", _reconnection_time);
+    _reconnection_time = _reconnection_time * RECONNECT_INCREMENT_FACTOR;
+    if(_reconnection_time >= MAX_RECONNECT_TIMEOUT) {
+        _reconnection_time = MAX_RECONNECT_TIMEOUT;
+    }
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+void M2MInterfaceImpl::coap_data_processed()
+{
+    tr_debug("M2MInterfaceImpl::coap_data_processed()");
+    internal_event(STATE_COAP_DATA_PROCESSED);
+}
+
+void M2MInterfaceImpl::value_updated(M2MBase *base)
+{
+    tr_debug("M2MInterfaceImpl::value_updated");
+    if(base) {
+        M2MBase::BaseType type = base->base_type();
+        _observer.value_updated(base, type);
+    }
+}
+
+void M2MInterfaceImpl::data_available(uint8_t* data,
+                                      uint16_t data_size,
+                                      const M2MConnectionObserver::SocketAddress &address)
+{
+    tr_debug("M2MInterfaceImpl::data_available");
+    ReceivedData event;
+    event._data = data;
+    event._size = data_size;
+    event._address = &address;
+    internal_event(STATE_COAP_DATA_RECEIVED, &event);
+}
+
+void M2MInterfaceImpl::socket_error(uint8_t error_code, bool retry)
+{
+    // Bootstrap completed once PEER CLOSE notify received from the server.
+    if (_current_state == STATE_BOOTSTRAP_WAIT &&
+        error_code == M2MConnectionHandler::SSL_PEER_CLOSED) {
+        _security = NULL;
+        bootstrap_done();
+        return;
+    }
+
+    tr_error("M2MInterfaceImpl::socket_error: (%d), retry (%d), reconnecting (%d), reconnection_state (%d)",
+             error_code, retry, _reconnecting, (int)_reconnection_state);
+
+    // Ignore errors while client is sleeping
+    if (queue_mode()) {
+        if(_callback_handler && _queue_mode_timer_ongoing) {
+            tr_info("M2MInterfaceImpl::socket_error - Queue Mode - don't try to reconnect while in QueueMode");
+            return;
+        }
+    }
+    _queue_sleep_timer.stop_timer();
+
+    if (_registration_flow_timer) {
+        _registration_flow_timer->stop_timer();
+    }
+
+    const char *error_code_des;
+    M2MInterface::Error error = M2MInterface::ErrorNone;
+    switch (error_code) {
+    case M2MConnectionHandler::SSL_CONNECTION_ERROR:
+        error = M2MInterface::SecureConnectionFailed;
+        error_code_des = ERROR_SECURE_CONNECTION;
+        break;
+    case M2MConnectionHandler::DNS_RESOLVING_ERROR:
+        error = M2MInterface::DnsResolvingFailed;
+        error_code_des = ERROR_DNS;
+        break;
+    case M2MConnectionHandler::SOCKET_READ_ERROR:
+        error = M2MInterface::NetworkError;
+        error_code_des = ERROR_NETWORK;
+        break;
+    case M2MConnectionHandler::SOCKET_SEND_ERROR:
+        error = M2MInterface::NetworkError;
+        error_code_des = ERROR_NETWORK;
+        break;
+    case M2MConnectionHandler::SSL_HANDSHAKE_ERROR:
+        error = M2MInterface::SecureConnectionFailed;
+        error_code_des = ERROR_SECURE_CONNECTION;
+        break;
+    case M2MConnectionHandler::SOCKET_ABORT:
+        error = M2MInterface::NetworkError;
+        error_code_des = ERROR_NETWORK;
+        break;
+    default:
+        error_code_des = ERROR_NO;
+        break;
+    }
+
+    internal_event(STATE_IDLE);
+    // Try to do reconnecting
+    if (retry) {
+        _nsdl_interface.set_request_context_to_be_resend();
+        _reconnecting = true;
+        _connection_handler.stop_listening();
+        _retry_timer_expired = false;
+        _retry_timer.start_timer(_reconnection_time * 1000,
+                                  M2MTimerObserver::RetryTimer);
+        tr_info("M2MInterfaceImpl::socket_error - reconnecting in %" PRIu64 "(s)", _reconnection_time);
+        _reconnection_time = _reconnection_time * RECONNECT_INCREMENT_FACTOR;
+        if(_reconnection_time >= MAX_RECONNECT_TIMEOUT) {
+            _reconnection_time = MAX_RECONNECT_TIMEOUT;
+        }
+#ifndef DISABLE_ERROR_DESCRIPTION
+        snprintf(_error_description, sizeof(_error_description), ERROR_REASON_9, error_code_des);
+#endif
+    }
+    // Inform application
+    if (!retry && M2MInterface::ErrorNone != error) {
+        tr_info("M2MInterfaceImpl::socket_error - send error to application");
+        _connection_handler.stop_listening();
+        _retry_timer.stop_timer();
+        _security = NULL;
+        _reconnecting = false;
+        _reconnection_time = _initial_reconnection_time;
+        _reconnection_state = M2MInterfaceImpl::None;
+#ifndef DISABLE_ERROR_DESCRIPTION
+        snprintf(_error_description, sizeof(_error_description), ERROR_REASON_10, error_code_des);
+#endif
+    }
+    if(M2MInterface::ErrorNone != error) {
+        _observer.error(error);
+    }
+}
+
+void M2MInterfaceImpl::address_ready(const M2MConnectionObserver::SocketAddress &address,
+                                     M2MConnectionObserver::ServerType server_type,
+                                     const uint16_t server_port)
+{
+    tr_debug("M2MInterfaceImpl::address_ready");
+    ResolvedAddressData data;
+    data._address = &address;
+    data._port = server_port;
+    if( M2MConnectionObserver::Bootstrap == server_type) {
+        tr_info("M2MInterfaceImpl::address_ready() Server Type Bootstrap");
+        internal_event(STATE_BOOTSTRAP_ADDRESS_RESOLVED, &data);
+    } else {
+        tr_info("M2MInterfaceImpl::address_ready() Server Type LWM2M");
+        internal_event(STATE_REGISTER_ADDRESS_RESOLVED, &data);
+    }
+}
+
+void M2MInterfaceImpl::data_sent()
+{
+    tr_debug("M2MInterfaceImpl::data_sent()");
+    if(queue_mode()) {
+        if(_callback_handler && (_nsdl_interface.is_unregister_ongoing() == false)) {
+            _queue_sleep_timer.stop_timer();
+            // Multiply by two to get enough time for coap retransmissions.
+            _queue_sleep_timer.start_timer(_nsdl_interface.total_retransmission_time(_nsdl_interface.get_resend_count())*1000,
+                                            M2MTimerObserver::QueueSleep);
+        }
+    }
+
+    if (_current_state == STATE_BOOTSTRAP_ERROR_WAIT) {
+        // bootstrap_error to be called only after we have sent the last ACK.
+        // Otherwise client will goto reconnection mode before ACK has sent.
+        bootstrap_error(error_description());
+    } else if (_current_state != STATE_BOOTSTRAP_WAIT) {
+        internal_event(STATE_COAP_DATA_SENT);
+    }
+
+}
+
+void M2MInterfaceImpl::timer_expired(M2MTimerObserver::Type type)
+{
+    if (M2MTimerObserver::QueueSleep == type) {
+        if (_reconnecting) {
+            tr_debug("M2MInterfaceImpl::timer_expired() - reconnection ongoing, continue sleep timer");
+            _queue_sleep_timer.start_timer(_nsdl_interface.total_retransmission_time(_nsdl_interface.get_resend_count())*1000,
+                                            M2MTimerObserver::QueueSleep);
+        } else {
+            tr_debug("M2MInterfaceImpl::timer_expired() - sleep");
+            M2MTimer &timer = _nsdl_interface.get_nsdl_execution_timer();
+            timer.stop_timer();
+            _queue_mode_timer_ongoing = true;
+            if(_callback_handler) {
+                _callback_handler();
+            }
+        }
+    } else if (M2MTimerObserver::RetryTimer == type) {
+        tr_debug("M2MInterfaceImpl::timer_expired() - retry");
+        _retry_timer_expired = true;
+        if (_bootstrapped) {
+            internal_event(STATE_REGISTER);
+        } else {
+            internal_event(STATE_BOOTSTRAP);
+        }
+    } else if (M2MTimerObserver::BootstrapFlowTimer == type) {
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+        tr_debug("M2MInterfaceImpl::timer_expired() - bootstrap");
+        _bootstrapped = false;
+        if (_registration_flow_timer) {
+            _registration_flow_timer->stop_timer();
+        }
+        bootstrap_error(ERROR_REASON_23);
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    } else if (M2MTimerObserver::RegistrationFlowTimer == type) {
+        tr_debug("M2MInterfaceImpl::timer_expired() - register");
+        registration_error(M2MInterface::Timeout, true);
+    }
+}
+
+// state machine sits here.
+void M2MInterfaceImpl::state_idle(EventData* /*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_idle");
+    _nsdl_interface.stop_timers();
+    _nsdl_interface.clear_sent_blockwise_messages();
+    _queue_sleep_timer.stop_timer();
+}
+
+void M2MInterfaceImpl::state_bootstrap(EventData *data)
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_debug("M2MInterfaceImpl::state_bootstrap");
+    // Start with bootstrapping preparation
+    _bootstrapped = false;
+    _bootstrap_finished = false;
+    _nsdl_interface.set_registration_status(false);
+    M2MSecurityData *event = static_cast<M2MSecurityData *> (data);
+    if(!_security) {
+        M2MInterface::Error error = M2MInterface::InvalidParameters;
+        if (event) {
+            _security = event->_object;
+            if(_security) {
+                int32_t bs_id = _security->get_security_instance_id(M2MSecurity::Bootstrap);
+                tr_info("M2MInterfaceImpl::state_bootstrap - bs_id = %" PRId32 "(s)", bs_id);
+                if(bs_id >= 0) {
+                    String server_address = _security->resource_value_string(M2MSecurity::M2MServerUri, bs_id);
+                    _nsdl_interface.set_server_address(server_address.c_str());
+                    tr_info("M2MInterfaceImpl::state_bootstrap - server_address %s", server_address.c_str());
+                    String coap;
+                    if(server_address.compare(0,sizeof(COAP)-1,COAP) == 0) {
+                         coap = COAP;
+                    }
+                    else if(server_address.compare(0,sizeof(COAPS)-1,COAPS) == 0) {
+                        _security->resource_value_int(M2MSecurity::SecurityMode, bs_id) != M2MSecurity::NoSecurity ? coap = COAPS: coap = "";
+                    }
+                    if(!coap.empty()) {
+                        server_address = server_address.substr(coap.size(),
+                                                           server_address.size()-coap.size());
+
+                        process_address(server_address, _server_ip_address, _server_port);
+
+                        tr_info("M2MInterfaceImpl::state_bootstrap - IP address %s, Port %d", _server_ip_address.c_str(), _server_port);
+                        // If bind and resolving server address succeed then proceed else
+                        // return error to the application and go to Idle state.
+                        if(!_server_ip_address.empty()) {
+                            error = M2MInterface::ErrorNone;
+                            if (_registration_flow_timer) {
+                                _registration_flow_timer->stop_timer();
+                                _registration_flow_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
+                                                              M2MTimerObserver::BootstrapFlowTimer);
+                            }
+                            _connection_handler.resolve_server_address(_server_ip_address,
+                                                                        _server_port,
+                                                                        M2MConnectionObserver::Bootstrap,
+                                                                        _security);
+                        }
+                    }
+                }
+            }
+        }
+        if (error != M2MInterface::ErrorNone) {
+            tr_error("M2MInterfaceImpl::state_bootstrap - set error as M2MInterface::InvalidParameters");
+            internal_event(STATE_IDLE);
+            set_error_description(ERROR_REASON_11);
+            _observer.error(error);
+        }
+    } else {
+        _listen_port = 0;
+        _connection_handler.bind_connection(_listen_port);
+        if (_registration_flow_timer) {
+            _registration_flow_timer->stop_timer();
+            _registration_flow_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
+                                          M2MTimerObserver::BootstrapFlowTimer);
+        }
+        tr_info("M2MInterfaceImpl::state_bootstrap (reconnect) - IP address %s, Port %d", _server_ip_address.c_str(), _server_port);
+        _connection_handler.resolve_server_address(_server_ip_address,
+                                                    _server_port,
+                                                    M2MConnectionObserver::Bootstrap,
+                                                    _security);
+    }
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+void M2MInterfaceImpl::state_bootstrap_address_resolved( EventData *data)
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved");
+    if (data) {
+        ResolvedAddressData *event = static_cast<ResolvedAddressData *> (data);
+        sn_nsdl_addr_s address;
+
+        M2MInterface::NetworkStack stack = event->_address->_stack;
+
+        if(M2MInterface::LwIP_IPv4 == stack) {
+            tr_info("M2MInterfaceImpl::state_bootstrap_address_resolved : IPv4 address");
+            address.type = SN_NSDL_ADDRESS_TYPE_IPV4;
+        } else if((M2MInterface::LwIP_IPv6 == stack) ||
+                  (M2MInterface::Nanostack_IPv6 == stack)) {
+            tr_info("M2MInterfaceImpl::state_bootstrap_address_resolved : IPv6 address");
+            address.type = SN_NSDL_ADDRESS_TYPE_IPV6;
+        }
+        address.port = event->_port;
+        address.addr_ptr = (uint8_t*)event->_address->_address;
+        address.addr_len = event->_address->_length;
+        _connection_handler.start_listening_for_data();
+
+        if(_nsdl_interface.create_bootstrap_resource(&address)) {
+           internal_event(STATE_BOOTSTRAP_RESOURCE_CREATED);
+        } else{
+            // If resource creation fails then inform error to application
+            tr_error("M2MInterfaceImpl::state_bootstrap_address_resolved : M2MInterface::InvalidParameters");
+            internal_event(STATE_IDLE);
+            set_error_description(ERROR_REASON_12);
+            _observer.error(M2MInterface::InvalidParameters);
+        }
+    }
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+void M2MInterfaceImpl::state_bootstrap_resource_created( EventData */*data*/)
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_debug("M2MInterfaceImpl::state_bootstrap_resource_created");
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+void M2MInterfaceImpl::state_bootstrapped( EventData */*data*/)
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_debug("M2MInterfaceImpl::state_bootstrapped");
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+void M2MInterfaceImpl::state_register(EventData *data)
+{
+    tr_debug("M2MInterfaceImpl::state_register");
+    _nsdl_interface.set_registration_status(false);
+    M2MRegisterData *event = static_cast<M2MRegisterData *> (data);
+    if (!_security) {
+        M2MInterface::Error error = M2MInterface::InvalidParameters;
+        // Start with registration preparation
+        if(event) {
+            _security = event->_object;
+            if(_security) {
+                int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
+                if(m2m_id >= 0) {
+                    if(_nsdl_interface.create_nsdl_list_structure(event->_base_list)) {
+                        // If the nsdl resource structure is created successfully
+                        String server_address = _security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id);
+                        _nsdl_interface.set_server_address(server_address.c_str());
+                        tr_info("M2MInterfaceImpl::state_register - server_address %s", server_address.c_str());
+                        String  coap;
+                        if(server_address.compare(0,sizeof(COAP)-1,COAP) == 0) {
+                             coap = COAP;
+                        }
+                        else if(server_address.compare(0,sizeof(COAPS)-1,COAPS) == 0) {
+                            _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id) != M2MSecurity::NoSecurity ? coap = COAPS: coap = "";
+                        }
+                        if(!coap.empty()) {
+                            server_address = server_address.substr(coap.size(),
+                                                               server_address.size() - coap.size());
+                            process_address(server_address, _server_ip_address, _server_port);
+
+                            tr_info("M2MInterfaceImpl::state_register - IP address %s, Port %d", _server_ip_address.c_str(), _server_port);
+                            if(!_server_ip_address.empty()) {
+                                // Connection related errors are coming through callback
+                                if (_registration_flow_timer) {
+                                    _registration_flow_timer->stop_timer();
+                                    _registration_flow_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
+                                                                  M2MTimerObserver::RegistrationFlowTimer);
+                                }
+                                error = M2MInterface::ErrorNone;
+                                _connection_handler.resolve_server_address(_server_ip_address,_server_port,
+                                                                            M2MConnectionObserver::LWM2MServer,
+                                                                            _security);
+                            }
+                        }
+                    } else {
+                        tr_error("M2MInterfaceImpl::state_register - fail to create nsdl list structure!");
+                    }
+                }
+            }
+        }
+        if (error != M2MInterface::ErrorNone) {
+            tr_error("M2MInterfaceImpl::state_register - set error as M2MInterface::InvalidParameters");
+            internal_event(STATE_IDLE);
+            set_error_description(ERROR_REASON_13);
+            _observer.error(error);
+        }
+    } else {
+        _listen_port = 0;
+        if (event) {
+            _nsdl_interface.create_nsdl_list_structure(event->_base_list);
+        }
+        _connection_handler.bind_connection(_listen_port);
+        if (_registration_flow_timer) {
+            _registration_flow_timer->stop_timer();
+            _registration_flow_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
+                                          M2MTimerObserver::RegistrationFlowTimer);
+        }
+        tr_info("M2MInterfaceImpl::state_register (reconnect) - IP address %s, Port %d", _server_ip_address.c_str(), _server_port);
+        _connection_handler.resolve_server_address(_server_ip_address,_server_port,
+                                                    M2MConnectionObserver::LWM2MServer,
+                                                    _security);
+    }
+}
+
+void M2MInterfaceImpl::process_address(const String& server_address, String& ip_address, uint16_t& port) {
+
+    int colonFound = server_address.find_last_of(':'); //10
+    if(colonFound != -1) {
+        ip_address = server_address.substr(0,colonFound);
+        port = atoi(server_address.substr(colonFound+1,
+                                         server_address.size()-ip_address.size()).c_str());
+        colonFound = ip_address.find_last_of(']');
+        if(ip_address.compare(0,1,"[") == 0) {
+            if(colonFound == -1) {
+                ip_address.clear();
+            } else {
+                ip_address = ip_address.substr(1,colonFound-1);
+            }
+        } else if(colonFound != -1) {
+            ip_address.clear();
+        }
+    }
+}
+
+void M2MInterfaceImpl::state_register_address_resolved( EventData *data)
+{
+    tr_debug("M2MInterfaceImpl::state_register_address_resolved - reconnect status %d", _reconnection_state);
+    if(data) {
+        ResolvedAddressData *event = static_cast<ResolvedAddressData *> (data);
+
+        sn_nsdl_addr_type_e address_type = SN_NSDL_ADDRESS_TYPE_IPV6;
+
+        M2MInterface::NetworkStack stack = event->_address->_stack;
+
+        if(M2MInterface::LwIP_IPv4 == stack) {
+            tr_info("M2MInterfaceImpl::state_register_address_resolved : IPv4 address");
+            address_type = SN_NSDL_ADDRESS_TYPE_IPV4;
+        } else if((M2MInterface::LwIP_IPv6 == stack) ||
+                  (M2MInterface::Nanostack_IPv6 == stack)) {
+            tr_info("M2MInterfaceImpl::state_register_address_resolved : IPv6 address");
+            address_type = SN_NSDL_ADDRESS_TYPE_IPV6;
+        }
+        _connection_handler.start_listening_for_data();
+        _nsdl_interface.set_server_address((uint8_t*)event->_address->_address,event->_address->_length,
+                                           event->_port, address_type);
+        switch (_reconnection_state) {
+            case M2MInterfaceImpl::None:
+                if (!_nsdl_interface.send_register_message()) {
+                    // If resource creation fails then inform error to application
+                    tr_error("M2MInterfaceImpl::state_register_address_resolved : M2MInterface::MemoryFail");
+                    internal_event(STATE_IDLE);
+                    set_error_description(ERROR_REASON_25);
+                    _observer.error(M2MInterface::MemoryFail);
+                }
+                break;
+            case M2MInterfaceImpl::Unregistration:
+            case M2MInterfaceImpl::WithUpdate:
+                // Start registration update in case it is reconnection logic because of network issue.
+                internal_event(STATE_UPDATE_REGISTRATION);
+                break;
+        }
+    }
+}
+
+void M2MInterfaceImpl::state_registered( EventData */*data*/)
+{
+    tr_info("M2MInterfaceImpl::state_registered");
+    if (_registration_flow_timer) {
+        _registration_flow_timer->stop_timer();
+    }
+    _reconnection_time = _initial_reconnection_time;
+    _reconnecting = false;
+    _nsdl_interface.set_registration_status(true);
+    // Continue with the unregistration process if it has failed due to connection lost
+    if (_reconnection_state == M2MInterfaceImpl::Unregistration) {
+        internal_event(STATE_UNREGISTER);
+    } else {
+        _reconnection_state = M2MInterfaceImpl::WithUpdate;
+    }
+}
+
+void M2MInterfaceImpl::state_update_registration(EventData *data)
+{
+    tr_debug("M2MInterfaceImpl::state_update_registration");
+    uint32_t lifetime = 0;
+    // Set to false to allow reconnection to work.
+    _queue_mode_timer_ongoing = false;
+
+    if (data) {
+        M2MUpdateRegisterData *event = static_cast<M2MUpdateRegisterData *> (data);
+        // Create new resources if any
+        if (!event->_base_list.empty()) {
+            _nsdl_interface.create_nsdl_list_structure(event->_base_list);
+        }
+        lifetime = event->_lifetime;
+    }
+
+    bool success = _nsdl_interface.send_update_registration(lifetime);
+    if (!success) {
+        tr_error("M2MInterfaceImpl::state_update_registration : M2MInterface::MemoryFail");
+        internal_event(STATE_IDLE);
+        set_error_description(ERROR_REASON_25);
+        _observer.error(M2MInterface::MemoryFail);
+    }
+}
+
+void M2MInterfaceImpl::state_unregister(EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_unregister");
+    internal_event(STATE_SENDING_COAP_DATA);
+    if(!_nsdl_interface.send_unregister_message()) {
+        tr_error("M2MInterfaceImpl::state_unregister : M2MInterface::NotRegistered");
+        internal_event(STATE_IDLE);
+        set_error_description(ERROR_REASON_16);
+        _observer.error(M2MInterface::NotRegistered);
+    }
+}
+
+void M2MInterfaceImpl::state_unregistered( EventData */*data*/)
+{
+    tr_info("M2MInterfaceImpl::state_unregistered");
+    _reconnection_time = _initial_reconnection_time;
+    _connection_handler.force_close();
+    _security = NULL;
+    _observer.object_unregistered(_register_server);
+    internal_event(STATE_IDLE);
+}
+
+void M2MInterfaceImpl::state_sending_coap_data( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_sending_coap_data");
+    _nsdl_interface.start_nsdl_execution_timer();
+    internal_event(STATE_WAITING);
+}
+
+void M2MInterfaceImpl::state_coap_data_sent( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_coap_data_sent");
+    internal_event(STATE_WAITING);
+}
+
+void M2MInterfaceImpl::state_coap_data_received(EventData *data)
+{
+    tr_debug("M2MInterfaceImpl::state_coap_data_received");
+    if(data) {
+        ReceivedData *event = static_cast<ReceivedData*> (data);
+        sn_nsdl_addr_s address;
+
+        M2MInterface::NetworkStack stack = event->_address->_stack;
+
+        if(M2MInterface::LwIP_IPv4 == stack) {
+            address.type = SN_NSDL_ADDRESS_TYPE_IPV4;
+            address.addr_len = 4;
+        } else if((M2MInterface::LwIP_IPv6 == stack) ||
+                  (M2MInterface::Nanostack_IPv6 == stack)) {
+            address.type = SN_NSDL_ADDRESS_TYPE_IPV6;
+            address.addr_len = 16;
+        }
+        address.port = event->_address->_port;
+        address.addr_ptr = (uint8_t*)event->_address->_address;
+        address.addr_len = event->_address->_length;
+
+        // Process received data
+        internal_event(STATE_PROCESSING_COAP_DATA);
+        if(!_nsdl_interface.process_received_data(event->_data,
+                                                  event->_size,
+                                                  &address)) {
+           tr_error("M2MInterfaceImpl::state_coap_data_received : M2MInterface::ResponseParseFailed");
+           set_error_description(ERROR_REASON_17);
+            _observer.error(M2MInterface::ResponseParseFailed);
+        }
+    }
+}
+
+void M2MInterfaceImpl::state_processing_coap_data( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_processing_coap_data");
+    internal_event(STATE_WAITING);
+}
+
+void M2MInterfaceImpl::state_coap_data_processed( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_coap_data_processed");
+    internal_event(STATE_WAITING);
+}
+
+void M2MInterfaceImpl::state_waiting( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_waiting");
+}
+
+// generates an external event. called once per external event
+// to start the state machine executing
+void M2MInterfaceImpl::external_event(uint8_t new_state,
+                                     EventData* p_data)
+{
+    tr_debug("M2MInterfaceImpl::external_event : new state %d", new_state);
+    // if we are supposed to ignore this event
+    if (new_state == EVENT_IGNORED) {
+        tr_debug("M2MInterfaceImpl::external_event : new state is EVENT_IGNORED");
+        _event_ignored = true;
+    }
+    else {
+        tr_debug("M2MInterfaceImpl::external_event : handle new state");
+        // generate the event and execute the state engine
+        internal_event(new_state, p_data);
+    }
+}
+
+// generates an internal event. called from within a state
+// function to transition to a new state
+void M2MInterfaceImpl::internal_event(uint8_t new_state,
+                                      EventData* p_data)
+{
+    tr_debug("M2MInterfaceImpl::internal_event : new state %d", new_state);
+    _event_data = p_data;
+    _event_generated = true;
+    _current_state = new_state;
+    state_engine();
+}
+
+// the state engine executes the state machine states
+void M2MInterfaceImpl::state_engine (void)
+{
+    tr_debug("M2MInterfaceImpl::state_engine");
+    EventData* p_data_temp = NULL;
+
+    // while events are being generated keep executing states
+    while (_event_generated) {
+        p_data_temp = _event_data;  // copy of event data pointer
+        _event_data = NULL;       // event data used up, reset ptr
+        _event_generated = false;  // event used up, reset flag
+
+        assert(_current_state < _max_states);
+
+        state_function( _current_state, p_data_temp );
+    }
+}
+
+void M2MInterfaceImpl::state_function( uint8_t current_state, EventData* data )
+{
+    switch( current_state ) {
+        case STATE_IDLE:
+            M2MInterfaceImpl::state_idle(data);
+            break;
+        case STATE_BOOTSTRAP:
+        #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+            M2MInterfaceImpl::state_bootstrap(data);
+        #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+            break;
+        case STATE_BOOTSTRAP_ADDRESS_RESOLVED:
+        #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+            M2MInterfaceImpl::state_bootstrap_address_resolved(data);
+        #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+            break;
+        case STATE_BOOTSTRAP_RESOURCE_CREATED:
+        #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+            M2MInterfaceImpl::state_bootstrap_resource_created(data);
+        #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+            break;
+        case STATE_BOOTSTRAP_WAIT:
+        case STATE_BOOTSTRAP_ERROR_WAIT:
+        #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+            // Do nothing, we're just waiting for data_sent callback
+        #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+            break;
+        case STATE_BOOTSTRAPPED:
+        #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+            M2MInterfaceImpl::state_bootstrapped(data);
+        #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+            break;
+        case STATE_REGISTER:
+            M2MInterfaceImpl::state_register(data);
+            break;
+        case STATE_REGISTER_ADDRESS_RESOLVED:
+            M2MInterfaceImpl::state_register_address_resolved(data);
+            break;
+        case STATE_REGISTERED:
+            M2MInterfaceImpl::state_registered(data);
+            break;
+        case STATE_UPDATE_REGISTRATION:
+            M2MInterfaceImpl::state_update_registration(data);
+            break;
+        case STATE_UNREGISTER:
+            M2MInterfaceImpl::state_unregister(data);
+            break;
+        case STATE_UNREGISTERED:
+            M2MInterfaceImpl::state_unregistered(data);
+            break;
+        case STATE_SENDING_COAP_DATA:
+            M2MInterfaceImpl::state_sending_coap_data(data);
+            break;
+        case STATE_COAP_DATA_SENT:
+            M2MInterfaceImpl::state_coap_data_sent(data);
+            break;
+        case STATE_COAP_DATA_RECEIVED:
+            M2MInterfaceImpl::state_coap_data_received(data);
+            break;
+        case STATE_PROCESSING_COAP_DATA:
+            M2MInterfaceImpl::state_processing_coap_data(data);
+            break;
+        case STATE_COAP_DATA_PROCESSED:
+            M2MInterfaceImpl::state_coap_data_processed(data);
+            break;
+        case STATE_WAITING:
+            M2MInterfaceImpl::state_waiting(data);
+            break;
+    }
+}
+
+void M2MInterfaceImpl::start_register_update(M2MUpdateRegisterData *data) {
+    tr_debug("M2MInterfaceImpl::start_register_update()");
+    if(!data || (data->_lifetime != 0 && (data->_lifetime < MINIMUM_REGISTRATION_TIME))) {
+        set_error_description(ERROR_REASON_18);
+        _observer.error(M2MInterface::InvalidParameters);
+    }
+
+    if (_reconnecting) {
+        //If client is in reconnection mode, ignore this call, state machine will reconnect on its own.
+        return;
+    } else if (_nsdl_interface.is_update_register_ongoing()) {
+        set_error_description(ERROR_REASON_27);
+        _observer.error(M2MInterface::NotAllowed);
+        return;
+    }
+
+    _reconnection_state = M2MInterfaceImpl::WithUpdate;
+    BEGIN_TRANSITION_MAP                                    // - Current State -
+        TRANSITION_MAP_ENTRY (STATE_REGISTER)                // state_idle
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_wait
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_error_wait
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrapped
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
+        TRANSITION_MAP_ENTRY (STATE_UPDATE_REGISTRATION)    // state_registered
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
+        TRANSITION_MAP_ENTRY (STATE_UPDATE_REGISTRATION)    // state_waiting
+    END_TRANSITION_MAP(data)
+    if(_event_ignored) {
+        _event_ignored = false;
+        if (!_reconnecting) {
+            set_error_description(ERROR_REASON_19);
+            _observer.error(M2MInterface::NotAllowed);
+        }
+    }
+}
+
+bool M2MInterfaceImpl::remove_object(M2MBase *object)
+{
+    return _nsdl_interface.remove_object_from_list(object);
+}
+
+void M2MInterfaceImpl::update_endpoint(String &name) {
+    _nsdl_interface.update_endpoint(name);
+}
+
+void M2MInterfaceImpl::update_domain(String &domain)
+{
+    _nsdl_interface.update_domain(domain);
+}
+
+const String M2MInterfaceImpl::internal_endpoint_name() const
+{
+    return _nsdl_interface.internal_endpoint_name();
+}
+
+const char *M2MInterfaceImpl::error_description() const
+{
+#ifndef DISABLE_ERROR_DESCRIPTION
+    return _error_description;
+#else
+    return "";
+#endif
+}
+
+void M2MInterfaceImpl::set_error_description(const char *description)
+{
+#ifndef DISABLE_ERROR_DESCRIPTION
+    if (strncmp(_error_description, description, sizeof(_error_description)) != 0) {
+        strncpy(_error_description, description, MAX_ALLOWED_ERROR_STRING_LENGTH - 1);
+    }
+#endif
+}
+
+bool M2MInterfaceImpl::queue_mode() const
+{
+    return (_binding_mode == M2MInterface::UDP_QUEUE ||
+           _binding_mode == M2MInterface::TCP_QUEUE  ||
+           _binding_mode == M2MInterface::SMS_QUEUE  ||
+           _binding_mode == M2MInterface::UDP_SMS_QUEUE);
+}
+
+void M2MInterfaceImpl::get_data_request(const char *uri,
+                                        const size_t offset,
+                                        const bool async,
+                                        get_data_cb data_cb,
+                                        get_data_error_cb error_cb,
+                                        void *context)
+{
+    get_data_req_error_e error = FAILED_TO_SEND_MSG;
+    if (uri) {
+        _nsdl_interface.send_request(uri, COAP_MSG_CODE_REQUEST_GET, offset, async, 0, NULL, data_cb, error_cb, context);
+    } else {
+        error_cb(error, context);
+    }
+}
+
+void M2MInterfaceImpl::post_data_request(const char *uri,
+                                         const bool async,
+                                         const uint16_t payload_len,
+                                         uint8_t *payload_ptr,
+                                         get_data_cb data_cb,
+                                         get_data_error_cb error_cb,
+                                         void *context)
+{
+    get_data_req_error_e error = FAILED_TO_SEND_MSG;
+    if (uri) {
+        _nsdl_interface.send_request(uri, COAP_MSG_CODE_REQUEST_POST, 0, async, payload_len, payload_ptr, data_cb, error_cb, context);
+    } else {
+        error_cb(error, context);
+    }
+}
+
+bool M2MInterfaceImpl::set_uri_query_parameters(const char *uri_query_params)
+{
+    return _nsdl_interface.set_uri_query_parameters(uri_query_params);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mnotificationhandler.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2018 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "m2mnotificationhandler.h"
+#include "eventOS_scheduler.h"
+#include "m2mnsdlinterface.h"
+#include "mbed-trace/mbed_trace.h"
+#include <assert.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#define MBED_CLIENT_NOTIFICATION_HANDLER_TASKLET_INIT_EVENT 0 // Tasklet init occurs always when generating a tasklet
+#define MBED_CLIENT_NOTIFICATION_HANDLER_EVENT 40
+#define TRACE_GROUP "mClt"
+
+int8_t M2MNotificationHandler::_tasklet_id = -1;
+
+extern "C" void notification_tasklet_func(arm_event_s *event)
+{
+    M2MNsdlInterface *iface = (M2MNsdlInterface*)event->data_ptr;
+    if (event->event_type == MBED_CLIENT_NOTIFICATION_HANDLER_EVENT) {
+        iface->send_next_notification(false);
+        event->event_data = 0;
+    }
+}
+
+M2MNotificationHandler::M2MNotificationHandler()
+{
+    if (M2MNotificationHandler::_tasklet_id < 0) {
+        M2MNotificationHandler::_tasklet_id = eventOS_event_handler_create(notification_tasklet_func, MBED_CLIENT_NOTIFICATION_HANDLER_TASKLET_INIT_EVENT);
+        assert(M2MNotificationHandler::_tasklet_id >= 0);
+    }
+
+    initialize_event();
+}
+
+M2MNotificationHandler::~M2MNotificationHandler()
+{
+}
+
+void M2MNotificationHandler::send_notification(M2MNsdlInterface *interface)
+{
+    tr_debug("M2MNotificationHandler::send_notification");
+    if (!_event.data.event_data) {
+        _event.data.event_data = 1;
+        _event.data.event_type = MBED_CLIENT_NOTIFICATION_HANDLER_EVENT;
+        _event.data.data_ptr = interface;
+
+        eventOS_event_send_user_allocated(&_event);
+    } else {
+        tr_debug("M2MNotificationHandler::send_notification - event already in queue");
+    }
+}
+
+void M2MNotificationHandler::initialize_event()
+{
+    _event.data.data_ptr = NULL;
+    _event.data.event_data = 0;
+    _event.data.event_id = 0;
+    _event.data.sender = 0;
+    _event.data.event_type = 0;
+    _event.data.priority = ARM_LIB_MED_PRIORITY_EVENT;
+    _event.data.receiver = M2MNotificationHandler::_tasklet_id;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mnsdlinterface.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,3246 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+// Needed for PRIu64 on FreeRTOS
+#include <stdio.h>
+// Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+
+// Note: this macro is needed on armcc to get the the PRI*32 macros
+// from inttypes.h in a C++ code.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include "include/nsdlaccesshelper.h"
+#include "include/m2mnsdlobserver.h"
+#include "include/m2mtlvdeserializer.h"
+#include "include/m2mtlvserializer.h"
+#include "include/m2mnsdlinterface.h"
+#include "include/m2mreporthandler.h"
+#include "mbed-client/m2mstring.h"
+#include "mbed-client/m2msecurity.h"
+#include "mbed-client/m2mserver.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mendpoint.h"
+#include "mbed-client/m2mobjectinstance.h"
+#include "mbed-client/m2mresource.h"
+#include "mbed-client/m2mblockmessage.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/uriqueryparser.h"
+#include "mbed-trace/mbed_trace.h"
+#include "sn_grs.h"
+#include "mbed-client/m2minterfacefactory.h"
+#include "mbed-client/m2mdevice.h"
+#include "randLIB.h"
+#include "common_functions.h"
+#include "sn_nsdl_lib.h"
+#include "sn_coap_protocol.h"
+#include "m2mnotificationhandler.h"
+#include "eventOS_event_timer.h"
+#include "eventOS_scheduler.h"
+#include "ns_hal_init.h"
+
+#define MBED_CLIENT_NSDLINTERFACE_TASKLET_INIT_EVENT 0 // Tasklet init occurs always when generating a tasklet
+#define MBED_CLIENT_NSDLINTERFACE_EVENT 30
+#define MBED_CLIENT_NSDLINTERFACE_BS_EVENT 31
+#define MBED_CLIENT_NSDLINTERFACE_BS_PUT_EVENT 32
+#define MBED_CLIENT_NSDLINTERFACE_BS_FINISH_EVENT 33
+
+#ifdef MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
+#define MBED_CLIENT_EVENT_LOOP_SIZE MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
+#else
+#define MBED_CLIENT_EVENT_LOOP_SIZE 1024
+#endif
+
+
+#define BUFFER_SIZE 21
+#define TRACE_GROUP "mClt"
+#define MAX_QUERY_COUNT 10
+
+const char *MCC_VERSION = "mccv=1.4.0";
+
+int8_t M2MNsdlInterface::_tasklet_id = -1;
+
+extern "C" void nsdlinterface_tasklet_func(arm_event_s *event)
+{
+    // skip the init event as there will be a timer event after
+    if (event->event_type == MBED_CLIENT_NSDLINTERFACE_EVENT) {
+        eventOS_scheduler_mutex_wait();
+        M2MNsdlInterface::nsdl_coap_data_s *coap_data = (M2MNsdlInterface::nsdl_coap_data_s*)event->data_ptr;
+        M2MNsdlInterface *interface = (M2MNsdlInterface*)sn_nsdl_get_context(coap_data->nsdl_handle);
+        if (interface) {
+            interface->resource_callback_handle_event(coap_data->received_coap_header, &coap_data->address);
+            if (coap_data->received_coap_header->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED &&
+                coap_data->received_coap_header->payload_ptr) {
+                coap_data->nsdl_handle->grs->sn_grs_free(coap_data->received_coap_header->payload_ptr);
+                coap_data->received_coap_header->payload_ptr = 0;
+            }
+        }
+
+        M2MNsdlInterface::memory_free(coap_data->received_coap_header->payload_ptr);
+        sn_coap_parser_release_allocated_coap_msg_mem(coap_data->nsdl_handle->grs->coap, coap_data->received_coap_header);
+        M2MNsdlInterface::memory_free(coap_data->address.addr_ptr);
+        M2MNsdlInterface::memory_free(coap_data);
+        eventOS_scheduler_mutex_release();
+
+    } else if (event->event_type == MBED_CLIENT_NSDLINTERFACE_BS_EVENT) {
+        M2MNsdlInterface::nsdl_coap_data_s *coap_data = (M2MNsdlInterface::nsdl_coap_data_s*)event->data_ptr;
+        M2MNsdlInterface *interface = (M2MNsdlInterface*)sn_nsdl_get_context(coap_data->nsdl_handle);
+
+        sn_coap_hdr_s *coap_response = sn_nsdl_build_response(coap_data->nsdl_handle,
+                                                              coap_data->received_coap_header,
+                                                              coap_data->received_coap_header->msg_code);
+        if (coap_response) {
+            coap_response->msg_type = coap_data->received_coap_header->msg_type;
+
+            if (sn_nsdl_send_coap_message(coap_data->nsdl_handle, &coap_data->address, coap_response) == 0) {
+                interface->store_bs_finished_response_id(coap_response->msg_id);
+            } else {
+                tr_error("Failed to send final response for BS finished");
+            }
+
+            sn_coap_parser_release_allocated_coap_msg_mem(coap_data->nsdl_handle->grs->coap, coap_response);
+
+        } else {
+            tr_error("Failed to create final response message for BS finished");
+        }
+
+        // Release the memory
+        M2MNsdlInterface::memory_free(coap_data->received_coap_header->payload_ptr);
+        sn_coap_parser_release_allocated_coap_msg_mem(coap_data->nsdl_handle->grs->coap, coap_data->received_coap_header);
+        M2MNsdlInterface::memory_free(coap_data->address.addr_ptr);
+        M2MNsdlInterface::memory_free(coap_data);
+    } else if (event->event_type == MBED_CLIENT_NSDLINTERFACE_BS_PUT_EVENT) {
+        M2MNsdlInterface::nsdl_coap_data_s *coap_data = (M2MNsdlInterface::nsdl_coap_data_s*)event->data_ptr;
+        M2MNsdlInterface *interface = (M2MNsdlInterface*)sn_nsdl_get_context(coap_data->nsdl_handle);
+        interface->handle_bootstrap_put_message(coap_data->received_coap_header, &coap_data->address);
+
+        M2MNsdlInterface::memory_free(coap_data->received_coap_header->payload_ptr);
+        sn_coap_parser_release_allocated_coap_msg_mem(coap_data->nsdl_handle->grs->coap, coap_data->received_coap_header);
+        M2MNsdlInterface::memory_free(coap_data->address.addr_ptr);
+        M2MNsdlInterface::memory_free(coap_data);
+    } else if (event->event_type == MBED_CLIENT_NSDLINTERFACE_BS_FINISH_EVENT) {
+        nsdl_s *nsdl_handle = (nsdl_s*)event->data_ptr;
+        M2MNsdlInterface *interface = (M2MNsdlInterface*)sn_nsdl_get_context(nsdl_handle);
+        interface->handle_bootstrap_finish_ack(event->event_data);
+    }
+}
+
+M2MNsdlInterface::M2MNsdlInterface(M2MNsdlObserver &observer, M2MConnectionHandler &connection_handler)
+: _observer(observer),
+  _endpoint(NULL),
+  _nsdl_handle(NULL),
+  _security(NULL),
+  _server(NULL),
+  _nsdl_execution_timer(*this),
+  _registration_timer(*this),
+  _connection_handler(connection_handler),
+  _counter_for_nsdl(0),
+  _next_coap_ping_send_time(0),
+  _server_address(NULL),
+  _custom_uri_query_params(NULL),
+  _notification_handler(new M2MNotificationHandler()),
+  _bootstrap_id(0),
+  _binding_mode(M2MInterface::NOT_SET),
+  _identity_accepted(false),
+  _nsdl_execution_timer_running(false),
+  _notification_send_ongoing(false),
+  _registered(false),
+  _bootstrap_finish_ack_received(false)
+{
+    tr_debug("M2MNsdlInterface::M2MNsdlInterface()");
+
+    _event.data.data_ptr = NULL;
+    _event.data.event_data = 0;
+    _event.data.event_id = 0;
+    _event.data.sender = 0;
+    _event.data.event_type = 0;
+    _event.data.priority = ARM_LIB_MED_PRIORITY_EVENT;
+
+    _server = new M2MServer();
+
+    // This initializes libCoap and libNsdl
+    // Parameters are function pointers to used memory allocation
+    // and free functions in structure and used functions for sending
+    // and receiving purposes.
+    _nsdl_handle = sn_nsdl_init(&(__nsdl_c_send_to_server), &(__nsdl_c_received_from_server),
+                 &(__nsdl_c_memory_alloc), &(__nsdl_c_memory_free), &(__nsdl_c_auto_obs_token));
+
+    sn_nsdl_set_context(_nsdl_handle, this);
+
+    ns_hal_init(NULL, MBED_CLIENT_EVENT_LOOP_SIZE, NULL, NULL);
+    eventOS_scheduler_mutex_wait();
+    if (M2MNsdlInterface::_tasklet_id < 0) {
+        M2MNsdlInterface::_tasklet_id = eventOS_event_handler_create(nsdlinterface_tasklet_func, MBED_CLIENT_NSDLINTERFACE_TASKLET_INIT_EVENT);
+        assert(M2MNsdlInterface::_tasklet_id >= 0);
+    }
+    eventOS_scheduler_mutex_release();
+
+    _event.data.receiver = M2MNsdlInterface::_tasklet_id;
+
+    // Randomize the initial auto obs token. Range is in 1 - 1023
+    _auto_obs_token = randLIB_get_random_in_range(AUTO_OBS_TOKEN_MIN, AUTO_OBS_TOKEN_MAX);
+
+    initialize();
+}
+
+M2MNsdlInterface::~M2MNsdlInterface()
+{
+    tr_debug("M2MNsdlInterface::~M2MNsdlInterface() - IN");
+    if (_endpoint) {
+         memory_free(_endpoint->endpoint_name_ptr);
+         memory_free(_endpoint->domain_name_ptr);
+         memory_free(_endpoint->type_ptr);
+         memory_free(_endpoint->lifetime_ptr);
+         memory_free(_endpoint);
+    }
+
+    delete _notification_handler;
+    _base_list.clear();
+    _security = NULL;
+    delete _server;
+    sn_nsdl_destroy(_nsdl_handle);
+    _nsdl_handle = NULL;
+    memory_free(_server_address);
+    free_request_context_list();
+    memory_free(_custom_uri_query_params);
+    tr_debug("M2MNsdlInterface::~M2MNsdlInterface() - OUT");
+}
+
+bool M2MNsdlInterface::initialize()
+{
+    tr_debug("M2MNsdlInterface::initialize()");
+    bool success = false;
+
+    // Sets the packet retransmission attempts and time interval
+    sn_nsdl_set_retransmission_parameters(_nsdl_handle,
+                                          MBED_CLIENT_RECONNECTION_COUNT,
+                                          MBED_CLIENT_RECONNECTION_INTERVAL);
+
+    sn_nsdl_handle_block2_response_internally(_nsdl_handle, false);
+
+    // Allocate the memory for endpoint
+    _endpoint = (sn_nsdl_ep_parameters_s*)memory_alloc(sizeof(sn_nsdl_ep_parameters_s));
+    if (_endpoint) {
+        memset(_endpoint, 0, sizeof(sn_nsdl_ep_parameters_s));
+        success = true;
+    }
+
+    M2MResource* update_trigger = _server->get_resource(M2MServer::RegistrationUpdate);
+    if (update_trigger) {
+        update_trigger->set_execute_function(execute_callback(this,
+                                                              &M2MNsdlInterface::update_trigger_callback));
+    }
+
+    add_object_to_list(_server);
+    create_nsdl_object_structure(_server);
+    ns_list_init(&_request_context_list);
+
+    return success;
+}
+
+void M2MNsdlInterface::create_endpoint(const String &name,
+                                       const String &type,
+                                       const int32_t life_time,
+                                       const String &domain,
+                                       const uint8_t mode,
+                                       const String &/*context_address*/)
+{
+    tr_info("M2MNsdlInterface::create_endpoint( name %s type %s lifetime %" PRId32 ", domain %s, mode %d)",
+              name.c_str(), type.c_str(), life_time, domain.c_str(), mode);
+    _endpoint_name = name;
+    _binding_mode = mode;
+
+    calculate_new_coap_ping_send_time();
+
+    if (_endpoint){
+        memset(_endpoint, 0, sizeof(sn_nsdl_ep_parameters_s));
+        if (!_endpoint_name.empty()) {
+            memory_free(_endpoint->endpoint_name_ptr);
+            _endpoint->endpoint_name_ptr = alloc_string_copy((uint8_t*)_endpoint_name.c_str(), _endpoint_name.length());
+            _endpoint->endpoint_name_len = _endpoint_name.length();
+        }
+        if (!type.empty()) {
+            _endpoint->type_ptr = alloc_string_copy((uint8_t*)type.c_str(), type.length());
+            _endpoint->type_len =  type.length();
+        }
+        if (!domain.empty()) {
+            _endpoint->domain_name_ptr = alloc_string_copy((uint8_t*)domain.c_str(), domain.length());
+            _endpoint->domain_name_len = domain.length();
+        }
+
+        // nsdl binding mode is only 3 least significant bits
+        _endpoint->binding_and_mode = (sn_nsdl_oma_binding_and_mode_t)((uint8_t)mode & 0x07);
+
+        // If lifetime is less than zero then leave the field empty
+        if (life_time > 0) {
+            set_endpoint_lifetime_buffer(life_time);
+        }
+    }
+}
+
+void M2MNsdlInterface::update_endpoint(const String &name)
+{
+    _endpoint_name = name;
+    if (_endpoint){
+        if (!_endpoint_name.empty()) {
+            memory_free(_endpoint->endpoint_name_ptr);
+            _endpoint->endpoint_name_ptr = alloc_string_copy((uint8_t*)_endpoint_name.c_str(), _endpoint_name.length());
+            _endpoint->endpoint_name_len = _endpoint_name.length();
+        }
+    }
+}
+
+void M2MNsdlInterface::update_domain(const String &domain)
+{
+    if (_endpoint){
+        memory_free(_endpoint->domain_name_ptr);
+        _endpoint->domain_name_len = 0;
+        if (!domain.empty()) {
+            _endpoint->domain_name_ptr = alloc_string_copy((uint8_t*)domain.c_str(), domain.length());
+            _endpoint->domain_name_len = domain.length();
+        }
+    }
+}
+
+void M2MNsdlInterface::set_endpoint_lifetime_buffer(int lifetime)
+{
+    tr_debug("M2MNsdlInterface::set_endpoint_lifetime_buffer - %d", lifetime);
+    if (lifetime < 60) {
+        return;
+    }
+
+    _server->set_resource_value(M2MServer::Lifetime, lifetime);
+
+    if (_endpoint && _endpoint->lifetime_ptr) {
+        memory_free(_endpoint->lifetime_ptr);
+        _endpoint->lifetime_ptr = NULL;
+        _endpoint->lifetime_len = 0;
+    }
+
+    char buffer[20+1];
+    uint32_t size = m2m::itoa_c(lifetime, buffer);
+    if (_endpoint && size <= sizeof(buffer)) {
+        _endpoint->lifetime_len = 0;
+        _endpoint->lifetime_ptr = alloc_string_copy((uint8_t*)buffer, size);
+        if (_endpoint->lifetime_ptr) {
+            _endpoint->lifetime_len = size;
+        }
+    }
+
+    set_retransmission_parameters();
+}
+
+
+void M2MNsdlInterface::delete_endpoint()
+{
+    tr_debug("M2MNsdlInterface::delete_endpoint()");
+    if (_endpoint) {
+        free(_endpoint->lifetime_ptr);
+        memory_free(_endpoint);
+        _endpoint = NULL;
+    }
+}
+
+bool M2MNsdlInterface::create_nsdl_list_structure(const M2MBaseList &list)
+{
+    tr_debug("M2MNsdlInterface::create_nsdl_list_structure()");
+    bool success = false;
+    if(!list.empty()) {
+       tr_debug("M2MNsdlInterface::create_nsdl_list_structure - Object count is %d", list.size());
+        M2MBaseList::const_iterator it;
+        it = list.begin();
+        for ( ; it != list.end(); it++ ) {
+            // Create NSDL structure for all Objects inside
+            success = create_nsdl_structure(*it);
+            tr_debug("M2MNsdlInterface::create_nsdl_list_structure - create %d", success);
+            add_object_to_list(*it);
+        }
+    }
+    if (!success) {
+        tr_error("M2MNsdlInterface::create_nsdl_list_structure - fail!");
+    }
+    return success;
+}
+
+bool M2MNsdlInterface::remove_nsdl_resource(M2MBase *base)
+{
+    sn_nsdl_dynamic_resource_parameters_s* resource = base->get_nsdl_resource();
+    return sn_nsdl_pop_resource(_nsdl_handle, resource);
+}
+
+bool M2MNsdlInterface::create_bootstrap_resource(sn_nsdl_addr_s *address)
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_debug("M2MNsdlInterface::create_bootstrap_resource()");
+    _identity_accepted = false;
+    _bootstrap_finish_ack_received = false;
+    bool success = false;
+    tr_debug("M2MNsdlInterface::create_bootstrap_resource() - endpoint name: %.*s", _endpoint->endpoint_name_len,
+             _endpoint->endpoint_name_ptr);
+
+    if (_bootstrap_id == 0) {
+        // Take copy of the address, uri_query_parameters() will modify the source buffer
+        bool msg_sent = false;
+        if (_server_address) {
+            char *address_copy = M2MBase::alloc_string_copy(_server_address);
+            if (address_copy) {
+                char* query = parse_uri_query_parameters(_server_address);
+                if (query != NULL) {
+                    size_t query_len = 1 + strlen(query) + 1 + strlen(MCC_VERSION) + 1;
+                    if (query_len <= MAX_URI_QUERY_LEN) {
+                        char query_params[MAX_URI_QUERY_LEN];
+                        strcpy(query_params, "&");
+                        strcat(query_params, query);
+                        strcat(query_params, "&");
+                        strcat(query_params, MCC_VERSION);
+                        msg_sent = true;
+                        sn_nsdl_clear_coap_resending_queue(_nsdl_handle);
+                        _bootstrap_id = sn_nsdl_oma_bootstrap(_nsdl_handle,
+                                                              address,
+                                                              _endpoint,
+                                                              query_params);
+                        free(_server_address);
+                        _server_address = M2MBase::alloc_string_copy(address_copy);
+                    } else {
+                        tr_error("M2MNsdlInterface::create_bootstrap_resource() - max uri param length reached (%lu)",
+                                  (unsigned long)query_len);
+                    }
+                }
+                free(address_copy);
+            }
+        }
+        if (!msg_sent) {
+            sn_nsdl_clear_coap_resending_queue(_nsdl_handle);
+            _bootstrap_id = sn_nsdl_oma_bootstrap(_nsdl_handle,
+                                                  address,
+                                                  _endpoint,
+                                                  NULL);
+        }
+        success = _bootstrap_id != 0;
+        tr_debug("M2MNsdlInterface::create_bootstrap_resource - _bootstrap_id %d", _bootstrap_id);
+    }
+    return success;
+#else
+    (void)address;
+    (void)bootstrap_endpoint_name;
+    return false;
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+void M2MNsdlInterface::set_server_address(uint8_t* address,
+                                          uint8_t address_length,
+                                          const uint16_t port,
+                                          sn_nsdl_addr_type_e address_type)
+{
+    tr_debug("M2MNsdlInterface::set_server_address()");
+    set_NSP_address(_nsdl_handle, address, address_length, port, address_type);
+}
+
+bool M2MNsdlInterface::send_register_message()
+{
+    tr_info("M2MNsdlInterface::send_register_message()");
+    bool success = false;
+    if (_server_address) {
+        success = parse_and_send_uri_query_parameters();
+    }
+    // If URI parsing fails or there is no parameters, try again without parameters
+    if (!success) {
+        sn_nsdl_clear_coap_resending_queue(_nsdl_handle);
+        success = sn_nsdl_register_endpoint(_nsdl_handle,_endpoint, NULL) != 0;
+    }
+    return success;
+}
+
+void M2MNsdlInterface::send_request(const char *uri,
+                                    const sn_coap_msg_code_e msg_code,
+                                    const size_t offset,
+                                    const bool async,
+                                    const uint16_t payload_len,
+                                    uint8_t *payload_ptr,
+                                    request_data_cb data_cb,
+                                    request_error_cb error_cb,
+                                    void *context)
+{
+    int32_t message_id = 0;
+    uint32_t token = 0;
+    request_context_s *data_request = NULL;
+
+    // Check the duplicate items
+    request_context_s *data = (request_context_s *)ns_list_get_first(&_request_context_list);
+    while (data) {
+        if ((strcmp(uri, data->uri_path) == 0) && (offset == data->received_size)) {
+            tr_debug("M2MNsdlInterface::send_request - item already exists");
+            data_request = data;
+            break;
+        }
+        data = (request_context_s *)ns_list_get_next(&_request_context_list, data);
+    }
+
+    if (data_request == NULL) {
+        data_request = (struct request_context_s*)memory_alloc(sizeof(struct request_context_s));
+        if (data_request == NULL) {
+            error_cb(FAILED_TO_ALLOCATE_MEMORY, context);
+            return;
+        }
+
+        data_request->resend = false;
+        data_request->context = context;
+        data_request->async_req = async;
+        data_request->received_size = offset;
+        data_request->uri_path = (char*)alloc_string_copy((uint8_t*)uri, strlen(uri));
+        if (data_request->uri_path == NULL) {
+            memory_free(data_request);
+            error_cb(FAILED_TO_ALLOCATE_MEMORY, context);
+            return;
+        }
+
+        data_request->on_request_data_cb = data_cb;
+        data_request->on_request_error_cb = error_cb;
+
+        randLIB_get_n_bytes_random(&token, sizeof(token));
+
+        if (!token) {
+            token++;
+        }
+
+        data_request->msg_token = token;
+        data_request->msg_code = msg_code;
+
+        ns_list_add_to_end(&_request_context_list, data_request);
+
+    }
+
+    bool send_message = true;
+    if (data_request->msg_code == COAP_MSG_CODE_REQUEST_GET && !_registered) {
+        // CoAP download(GET) should happen only when client is registered
+        send_message = false;
+    }
+
+    if (send_message) {
+        message_id = sn_nsdl_send_request(_nsdl_handle,
+                                          data_request->msg_code,
+                                          data_request->uri_path,
+                                          data_request->msg_token,
+                                          data_request->received_size,
+                                          payload_len,
+                                          payload_ptr);
+
+        if (message_id == -4) {
+            data_request->resend = true;
+        } else if (message_id <= 0) {
+            ns_list_remove(&_request_context_list, data_request);
+            memory_free(data_request->uri_path);
+            memory_free(data_request);
+            error_cb(FAILED_TO_ALLOCATE_MEMORY, context);
+        }
+    } else {
+        tr_error("M2MNsdlInterface::send_request - not registered");
+    }
+}
+
+bool M2MNsdlInterface::send_update_registration(const uint32_t lifetime)
+{
+    tr_info("M2MNsdlInterface::send_update_registration( lifetime %" PRIu32 ")", lifetime);
+    bool success = false;
+    int32_t ret = 0;
+
+    _registration_timer.stop_timer();
+    bool lifetime_changed = true;
+
+    // If new resources have been created after registration those must be created and published to the server.
+    create_nsdl_list_structure(_base_list);
+
+    // Check if resource(1/0/1) value has been updated and update it into _endpoint struct
+    if (lifetime == 0) {
+        lifetime_changed = lifetime_value_changed();
+        if (lifetime_changed) {
+            set_endpoint_lifetime_buffer(_server->resource_value_int(M2MServer::Lifetime));
+        }
+    } else {
+        set_endpoint_lifetime_buffer(lifetime);
+    }
+
+    if (_nsdl_handle) {
+        if (!lifetime_changed) {
+            tr_debug("M2MNsdlInterface::send_update_registration - regular update");
+            ret = sn_nsdl_update_registration(_nsdl_handle, NULL, 0);
+        } else {
+            if (_endpoint && _endpoint->lifetime_ptr) {
+                tr_debug("M2MNsdlInterface::send_update_registration - new lifetime value");
+                ret = sn_nsdl_update_registration(_nsdl_handle,
+                                                      _endpoint->lifetime_ptr,
+                                                      _endpoint->lifetime_len);
+            }
+        }
+    }
+
+    if (ret >= 0) {
+        success = true;
+    }
+
+    _registration_timer.start_timer(registration_time() * 1000,
+                                     M2MTimerObserver::Registration,
+                                     false);
+
+    return success;
+}
+
+bool M2MNsdlInterface::send_unregister_message()
+{
+    tr_info("M2MNsdlInterface::send_unregister_message");
+    if (is_unregister_ongoing()) {
+        tr_debug("M2MNsdlInterface::send_unregister_message - unregistration already in progress");
+        return true;
+    }
+
+    bool success = false;
+    int32_t ret = 0;
+
+    ret = sn_nsdl_unregister_endpoint(_nsdl_handle);
+    if (ret == -4) {
+        tr_warn("Failed to send registration update. Clearing queue and retrying.");
+        sn_nsdl_clear_coap_resending_queue(_nsdl_handle);
+        ret = sn_nsdl_unregister_endpoint(_nsdl_handle);
+    }
+    if (ret >= 0) {
+        success = true;
+    }
+    return success;
+}
+
+// XXX: move these to common place, no need to copy these wrappers to multiple places:
+void *M2MNsdlInterface::memory_alloc(uint32_t size)
+{
+    if(size)
+        return malloc(size);
+    else
+        return 0;
+}
+
+void M2MNsdlInterface::memory_free(void *ptr)
+{
+    if(ptr)
+        free(ptr);
+}
+
+uint8_t* M2MNsdlInterface::alloc_string_copy(const uint8_t* source, uint16_t size)
+{
+    assert(source != NULL);
+
+    uint8_t* result = (uint8_t*)memory_alloc(size + 1);
+    if (result) {
+        memcpy(result, source, size);
+        result[size] = '\0';
+    }
+    return result;
+}
+
+uint8_t M2MNsdlInterface::send_to_server_callback(struct nsdl_s * /*nsdl_handle*/,
+                                                  sn_nsdl_capab_e /*protocol*/,
+                                                  uint8_t *data_ptr,
+                                                  uint16_t data_len,
+                                                  sn_nsdl_addr_s *address)
+{
+    tr_debug("M2MNsdlInterface::send_to_server_callback(data size %d)", data_len);
+    _observer.coap_message_ready(data_ptr,data_len,address);
+    return 1;
+}
+
+uint8_t M2MNsdlInterface::received_from_server_callback(struct nsdl_s *nsdl_handle,
+                                                        sn_coap_hdr_s *coap_header,
+                                                        sn_nsdl_addr_s *address)
+{
+    tr_debug("M2MNsdlInterface::received_from_server_callback");
+    _observer.coap_data_processed();
+    uint8_t value = 0;
+    request_context_s request_context;
+    if(nsdl_handle && coap_header) {
+        bool is_bootstrap_msg = nsdl_handle->is_bs_server;
+
+        if (coap_header->token_len == sizeof(nsdl_handle->register_token) &&
+            memcmp(coap_header->token_ptr, &nsdl_handle->register_token, sizeof(nsdl_handle->register_token)) == 0) {
+
+            handle_register_response(coap_header);
+
+        } else if (coap_header->token_len == sizeof(nsdl_handle->unregister_token) &&
+                   memcmp(coap_header->token_ptr,
+                          &nsdl_handle->unregister_token,
+                          sizeof(nsdl_handle->unregister_token)) == 0) {
+
+            handle_unregister_response(coap_header);
+
+        } else if (coap_header->token_len == sizeof(nsdl_handle->update_register_token) &&
+                   memcmp(coap_header->token_ptr,
+                          &nsdl_handle->update_register_token,
+                          sizeof(nsdl_handle->update_register_token)) == 0) {
+
+            handle_register_update_response(coap_header);
+
+        } else if (coap_header->token_ptr && is_response_to_request(coap_header, request_context)) {
+
+            handle_request_response(coap_header, &request_context);
+
+        }
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+        else if (coap_header->token_len == sizeof(nsdl_handle->bootstrap_token) &&
+                 memcmp(coap_header->token_ptr, &nsdl_handle->bootstrap_token, sizeof(nsdl_handle->bootstrap_token)) == 0) {
+
+            handle_bootstrap_response(coap_header);
+
+        }
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+        else {
+
+            sn_coap_hdr_s *coap_response = NULL;
+            bool execute_value_updated = false;
+            M2MObjectInstance *obj_instance = NULL;
+
+            if (COAP_MSG_CODE_REQUEST_PUT == coap_header->msg_code) {
+                if (is_bootstrap_msg) {
+                    send_empty_ack(coap_header, address);
+                    nsdl_coap_data_s *nsdl_coap_data = create_coap_event_data(coap_header,
+                                                                              address,
+                                                                              nsdl_handle,
+                                                                              coap_header->msg_code);
+                    if (nsdl_coap_data) {
+                        _event.data.event_type = MBED_CLIENT_NSDLINTERFACE_BS_PUT_EVENT;
+                        _event.data.data_ptr = (void*)nsdl_coap_data;
+                        eventOS_event_send_user_allocated(&_event);
+                        return 2; // freeing will be performed in MBED_CLIENT_NSDLINTERFACE_BS_PUT_EVENT event
+                    } else {
+                        tr_error("M2MNsdlInterface::received_from_server_callback() - BS PUT failed to allocate nsdl_coap_data_s!");
+                        coap_response = sn_nsdl_build_response(_nsdl_handle,
+                                                               coap_header,
+                                                               COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE);
+                    }
+
+                } else {
+                    tr_debug("M2MNsdlInterface::received_from_server_callback - Method not allowed (PUT).");
+                    coap_response = sn_nsdl_build_response(_nsdl_handle,
+                                                           coap_header,
+                                                           COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED);
+                }
+            }
+            else if (COAP_MSG_CODE_REQUEST_DELETE == coap_header->msg_code) {
+                if (is_bootstrap_msg) {
+                    handle_bootstrap_delete(coap_header, address);
+                } else {
+                    tr_debug("M2MNsdlInterface::received_from_server_callback - Method not allowed (DELETE).");
+                    coap_response = sn_nsdl_build_response(_nsdl_handle,
+                                                           coap_header,
+                                                           COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED);
+                }
+            } else if (COAP_MSG_CODE_REQUEST_POST == coap_header->msg_code) {
+
+                execute_value_updated = handle_post_response(coap_header,
+                                                             address,
+                                                             coap_response,
+                                                             obj_instance,
+                                                             is_bootstrap_msg);
+
+            } else if (COAP_STATUS_BUILDER_BLOCK_SENDING_DONE == coap_header->coap_status &&
+                       coap_header->msg_code == COAP_MSG_CODE_RESPONSE_CONTENT) {
+
+                M2MBase *base = find_resource("", coap_header->msg_id);
+                if (base) {
+                    handle_notification_delivered(base);
+                }
+
+            } else if (COAP_MSG_CODE_EMPTY == coap_header->msg_code) {
+
+                handle_empty_ack(coap_header, is_bootstrap_msg);
+
+            // Retransmission done
+            } else if (COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED == coap_header->coap_status) {
+
+                tr_info("M2MNsdlInterface::received_from_server_callback - message sending failed, id %d", coap_header->msg_id);
+
+                // Report notification status back to application
+                M2MBase *base = find_resource("", coap_header->msg_id);
+                if (base) {
+                    base->send_notification_delivery_status(*base, NOTIFICATION_STATUS_SEND_FAILED);
+                }
+
+                _observer.registration_error(M2MInterface::NetworkError, true);
+
+            // Handle Server-side expections during registration flow
+            // Client might receive error from server due to temporary connection/operability reasons,
+            // server might not recover the flow in this case, so it is better for Client to restart registration.
+            } else if (nsdl_handle->register_token &&
+                       ((coap_header->msg_code == COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR) ||
+                       (coap_header->msg_code == COAP_MSG_CODE_RESPONSE_BAD_GATEWAY) ||
+                       (coap_header->msg_code == COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE) ||
+                       (coap_header->msg_code == COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT))) {
+
+                tr_error("M2MNsdlInterface::received_from_server_callback - registration error %d", coap_header->msg_code);
+                tr_error("M2MNsdlInterface::received_from_server_callback - unexpected error received from server");
+                // Try to do clean register again
+                _observer.registration_error(M2MInterface::NetworkError, true);
+
+            } else {
+                // Add warn for any message that gets this far. We might be missing some handling in above.
+                tr_warn("M2MNsdlInterface::received_from_server_callback - msg was ignored %d", coap_header->msg_code);
+            }
+
+            // Send response to server
+            if (coap_response) {
+                tr_debug("M2MNsdlInterface::received_from_server_callback - send CoAP response");
+                (sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response) == 0) ? value = 0 : value = 1;
+                sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response);
+            }
+
+            // Tell to application that value has been updated
+            if (execute_value_updated) {
+                value_updated(obj_instance);
+            }
+
+        }
+    }
+    return value;
+}
+
+
+uint8_t M2MNsdlInterface::resource_callback(struct nsdl_s *nsdl_handle,
+                                            sn_coap_hdr_s *received_coap_header,
+                                            sn_nsdl_addr_s *address,
+                                            sn_nsdl_capab_e /*nsdl_capab*/)
+{
+    tr_debug("M2MNsdlInterface::resource_callback()");
+
+    assert(received_coap_header);
+    _observer.coap_data_processed();
+
+    // Use piggypacked response for any other types than POST
+    if (received_coap_header->msg_code != COAP_MSG_CODE_REQUEST_POST) {
+        uint8_t status = resource_callback_handle_event(received_coap_header, address);
+
+        if (received_coap_header->coap_status == COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED) {
+            memory_free(received_coap_header->payload_ptr);
+        }
+
+        sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, received_coap_header);
+        return status;
+    }
+
+    send_empty_ack(received_coap_header, address);
+
+    nsdl_coap_data_s *nsdl_coap_data = create_coap_event_data(received_coap_header,
+                                                              address,
+                                                              nsdl_handle,
+                                                              received_coap_header->msg_code);
+    if (nsdl_coap_data) {
+        _event.data.event_type = MBED_CLIENT_NSDLINTERFACE_EVENT;
+        _event.data.data_ptr = (void*)nsdl_coap_data;
+        eventOS_event_send_user_allocated(&_event);
+    } else {
+        tr_error("M2MNsdlInterface::resource_callback() - failed to allocate nsdl_coap_data_s!");
+    }
+    return 0;
+}
+
+uint8_t M2MNsdlInterface::resource_callback_handle_event(sn_coap_hdr_s *received_coap_header,
+                                                         sn_nsdl_addr_s *address)
+{
+    tr_debug("M2MNsdlInterface::resource_callback_handle_event");
+    uint8_t result = 1;
+    uint8_t *payload = NULL;
+    bool free_payload = true;
+    sn_coap_hdr_s *coap_response = NULL;
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 4.00
+    String resource_name = coap_to_string(received_coap_header->uri_path_ptr,
+                                          received_coap_header->uri_path_len);
+
+    bool execute_value_updated = false;
+    M2MBase* base = find_resource(resource_name, 0);
+    bool subscribed = false;
+    if (base) {
+        if (COAP_MSG_CODE_REQUEST_GET == received_coap_header->msg_code) {
+            coap_response = base->handle_get_request(_nsdl_handle, received_coap_header,this);
+
+            if (coap_response && coap_response->options_list_ptr && coap_response->options_list_ptr->observe != STOP_OBSERVATION) {
+                subscribed = true;
+            }
+        } else if (COAP_MSG_CODE_REQUEST_PUT == received_coap_header->msg_code) {
+            coap_response = base->handle_put_request(_nsdl_handle, received_coap_header, this, execute_value_updated);
+        } else if (COAP_MSG_CODE_REQUEST_POST == received_coap_header->msg_code) {
+            if (base->base_type() == M2MBase::ResourceInstance) {
+                msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+            } else {
+                coap_response = base->handle_post_request(_nsdl_handle,
+                                                          received_coap_header,
+                                                          this,
+                                                          execute_value_updated,
+                                                          address);
+
+                if (base->base_type() == M2MBase::Resource) {
+                    M2MResource *res = (M2MResource*) base;
+                    if (res->delayed_response()) {
+                        tr_debug("M2MNsdlInterface::resource_callback_handle_event - final response sent by application");
+                        sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response);
+                        return 0;
+                    }
+                }
+
+                // Separate response used for POST
+                if (coap_response) {
+                    coap_response->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
+                }
+            }
+        } else if (COAP_MSG_CODE_REQUEST_DELETE == received_coap_header->msg_code) {
+            // Delete the object instance
+            M2MBase::BaseType type = base->base_type();
+            if(M2MBase::ObjectInstance == type) {
+                M2MBase* base_object = find_resource(base->uri_path(), 0);
+                if(base_object) {
+                    M2MObject &object = ((M2MObjectInstance*)base_object)->get_parent_object();
+                    int slash_found = resource_name.find_last_of('/');
+                    // Object instance validty checks done in upper level, no need for error handling
+                    if (slash_found != -1) {
+                        String object_name;
+                        object_name = resource_name.substr(slash_found + 1, resource_name.length());
+                        if (object.remove_object_instance(strtoul(
+                                object_name.c_str(),
+                                NULL,
+                                10))) {
+                            msg_code = COAP_MSG_CODE_RESPONSE_DELETED;
+                        }
+                    }
+                }
+            } else {
+                msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00
+            }
+        }
+    } else  {
+        tr_error("M2MNsdlInterface::resource_callback_handle_event() - Resource NOT FOUND");
+        msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00
+    }
+
+    if (!coap_response) {
+        coap_response = sn_nsdl_build_response(_nsdl_handle,
+                                               received_coap_header,
+                                               msg_code);
+    }
+
+    // This copy will be passed to resource instance
+    if (received_coap_header->payload_len > 0 && received_coap_header->payload_ptr) {
+        payload = (uint8_t*)memory_alloc(received_coap_header->payload_len);
+        if (payload) {
+            assert(received_coap_header->payload_ptr);
+            memcpy(payload, received_coap_header->payload_ptr, received_coap_header->payload_len);
+        }
+        else {
+            if (coap_response) {
+                coap_response->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
+            }
+        }
+    }
+
+    if (coap_response &&
+        coap_response->coap_status != COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING &&
+        coap_response->msg_code != COAP_MSG_CODE_EMPTY) {
+
+        (sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response) == 0) ? result = 0 : result = 1;
+
+        if (coap_response->payload_ptr) {
+            free(coap_response->payload_ptr);
+            coap_response->payload_ptr = NULL;
+        }
+
+        // See if there any pending notification to be sent after resource is subscribed.
+        if (subscribed) {
+            _notification_handler->send_notification(this);
+        }
+    }
+
+    // If the external blockwise storing is enabled call value updated only when all blocks have been received
+    if (execute_value_updated &&
+        coap_response &&
+        coap_response->coap_status != COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING &&
+        coap_response->msg_code < COAP_MSG_CODE_RESPONSE_BAD_REQUEST) {
+        if ((COAP_MSG_CODE_REQUEST_PUT == received_coap_header->msg_code) &&
+            (base->base_type() == M2MBase::Resource ||
+             base->base_type() == M2MBase::ResourceInstance)) {
+            M2MResourceBase* res = (M2MResourceBase*)base;
+
+            // Clear the old resource value since the data is now passed to application
+            if (res->block_message() && res->block_message()->is_block_message()) {
+                res->clear_value();
+            }
+            else {
+                // Ownership of payload moved to resource, skip the freeing.
+                free_payload = false;
+                res->set_value_raw(payload, received_coap_header->payload_len);
+            }
+        }
+
+        if (coap_response->msg_code != COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE) {
+            value_updated(base);
+        }
+    }
+
+    if (free_payload) {
+        free(payload);
+    }
+
+    sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response);
+
+    return result;
+}
+
+bool M2MNsdlInterface::process_received_data(uint8_t *data,
+                                             uint16_t data_size,
+                                             sn_nsdl_addr_s *address)
+{
+    tr_debug("M2MNsdlInterface::process_received_data(data size %d)", data_size);
+    return (0 == sn_nsdl_process_coap(_nsdl_handle,
+                                      data,
+                                      data_size,
+                                      address)) ? true : false;
+}
+
+void M2MNsdlInterface::stop_timers()
+{
+    tr_debug("M2MNsdlInterface::stop_timers()");
+    _registration_timer.stop_timer();
+    _nsdl_execution_timer.stop_timer();
+    _nsdl_execution_timer_running = false;
+    _bootstrap_id = 0;
+    _nsdl_handle->update_register_token = 0;
+    _nsdl_handle->unregister_token = 0;
+}
+
+void M2MNsdlInterface::timer_expired(M2MTimerObserver::Type type)
+{
+    if(M2MTimerObserver::NsdlExecution == type) {
+        sn_nsdl_exec(_nsdl_handle, _counter_for_nsdl);
+        _counter_for_nsdl++;
+        send_coap_ping();
+    } else if((M2MTimerObserver::Registration) == type &&
+              (is_unregister_ongoing() == false) &&
+              (is_update_register_ongoing() == false)) {
+        tr_debug("M2MNsdlInterface::timer_expired - Send update registration");
+        if (lifetime_value_changed()) {
+            send_update_registration(_server->resource_value_int(M2MServer::Lifetime));
+        } else {
+            send_update_registration();
+        }
+    }
+}
+
+bool M2MNsdlInterface::observation_to_be_sent(M2MBase *object,
+                                              uint16_t obs_number,
+                                              const m2m::Vector<uint16_t> &changed_instance_ids,
+                                              bool send_object)
+{
+    claim_mutex();
+
+    if (object && _nsdl_execution_timer_running && _registered) {
+        tr_debug("M2MNsdlInterface::observation_to_be_sent() uri %s", object->uri_path());
+
+        if (!_notification_send_ongoing) {
+            _notification_send_ongoing = true;
+            object->report_handler()->set_notification_in_queue(false);
+            M2MBase::BaseType type = object->base_type();
+
+            clear_sent_blockwise_messages();
+
+            if (type == M2MBase::Object) {
+                send_object_observation(static_cast<M2MObject*> (object),
+                                        obs_number,
+                                        changed_instance_ids,
+                                        send_object);
+            } else if (type == M2MBase::ObjectInstance) {
+                send_object_instance_observation(static_cast<M2MObjectInstance*> (object), obs_number);
+            } else if (type == M2MBase::Resource) {
+                send_resource_observation(static_cast<M2MResource*> (object), obs_number);
+            }
+
+            release_mutex();
+            return true;
+        } else {
+            tr_info("M2MNsdlInterface::observation_to_be_sent() - send already in progress");
+        }
+    } else {
+        tr_info("M2MNsdlInterface::observation_to_be_sent() - object NULL, in reconnection mode or not registered");
+    }
+
+    release_mutex();
+
+    return false;
+}
+
+#ifndef DISABLE_DELAYED_RESPONSE
+void M2MNsdlInterface::send_delayed_response(M2MBase *base)
+{
+    claim_mutex();
+    tr_debug("M2MNsdlInterface::send_delayed_response()");
+    M2MResource *resource = NULL;
+    if(base) {
+        if(M2MBase::Resource == base->base_type()) {
+            resource = static_cast<M2MResource *> (base);
+        }
+        if(resource) {
+            sn_coap_hdr_s coap_response;
+
+            memset(&coap_response,0,sizeof(sn_coap_hdr_s));
+
+            coap_response.msg_type = COAP_MSG_TYPE_CONFIRMABLE;
+            coap_response.msg_code = COAP_MSG_CODE_RESPONSE_CHANGED;
+            resource->get_delayed_token(coap_response.token_ptr,coap_response.token_len);
+
+            uint32_t length = 0;
+            resource->get_value(coap_response.payload_ptr, length);
+            coap_response.payload_len = length;
+
+            sn_nsdl_send_coap_message(_nsdl_handle, &_nsdl_handle->server_address, &coap_response);
+
+            free(coap_response.payload_ptr);
+            free(coap_response.token_ptr);
+        }
+    }
+    release_mutex();
+}
+#endif
+
+void M2MNsdlInterface::resource_to_be_deleted(M2MBase *base)
+{
+    tr_debug("M2MNsdlInterface::resource_to_be_deleted() %p", base);
+    claim_mutex();
+    remove_nsdl_resource(base);
+
+    // Since the M2MObject's are stored in _base_list, they need to be removed from there also.
+    if (base && base->base_type() == M2MBase::Object) {
+        remove_object(base);
+    }
+
+    release_mutex();
+}
+
+void M2MNsdlInterface::value_updated(M2MBase *base)
+{
+    tr_debug("M2MNsdlInterface::value_updated()");
+    String name;
+    if(base) {
+        switch(base->base_type()) {
+            case M2MBase::Object:
+                create_nsdl_object_structure(static_cast<M2MObject*> (base));
+                name =  base->name();
+                break;
+            case M2MBase::ObjectInstance:
+                create_nsdl_object_instance_structure(static_cast<M2MObjectInstance*> (base));
+                name = static_cast<M2MObjectInstance*> (base)->get_parent_object().name();
+                break;
+            case M2MBase::Resource: {
+                M2MResource* resource = static_cast<M2MResource*> (base);
+                create_nsdl_resource_structure(resource, resource->supports_multiple_instances());
+                name = base->name();
+                break;
+            }
+            case M2MBase::ResourceInstance: {
+                M2MResourceInstance* instance = static_cast<M2MResourceInstance*> (base);
+                create_nsdl_resource(instance);
+                name = static_cast<M2MResourceInstance*> (base)->get_parent_resource().name();
+                break;
+            }
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+            case M2MBase::ObjectDirectory:
+                tr_error("M2MNsdlInterface::value_updated() - unsupported ObjectDirectory base type!");
+                assert(false);
+                return;
+#endif
+        }
+    }
+
+    if (base && base->is_value_updated_function_set()) {
+        base->execute_value_updated(name);
+    }
+    else {
+        _observer.value_updated(base);
+    }
+}
+
+void M2MNsdlInterface::remove_object(M2MBase *object)
+{
+    claim_mutex();
+    tr_debug("M2MNsdlInterface::remove_object() %p", object);
+    M2MObject* rem_object = static_cast<M2MObject*> (object);
+    if(rem_object && !_base_list.empty()) {
+        M2MBaseList::const_iterator it;
+        it = _base_list.begin();
+        int index = 0;
+        for ( ; it != _base_list.end(); it++, index++ ) {
+            if((*it)->base_type() == M2MBase::Object && (*it) == rem_object) {
+                _base_list.erase(index);
+                break;
+            }
+        }
+    }
+    release_mutex();
+}
+
+bool M2MNsdlInterface::create_nsdl_structure(M2MBase *base)
+{
+    tr_debug("M2MNsdlInterface::create_nsdl_structure()");
+    bool success = false;
+    if(base) {
+        switch (base->base_type()) {
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+        case M2MBase::ObjectDirectory:
+            success = create_nsdl_endpoint_structure((M2MEndpoint*)base);
+            break;
+#endif
+        case M2MBase::Object:
+            success = create_nsdl_object_structure((M2MObject*)base);
+            break;
+        default:
+            break;
+        }
+    }
+    return success;
+}
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+bool M2MNsdlInterface::create_nsdl_endpoint_structure(M2MEndpoint *endpoint)
+{
+    tr_debug("M2MNsdlInterface::create_nsdl_endpoint_structure()");
+    bool success = false;
+    if(endpoint) {
+        success = true;
+        if (endpoint->get_changed()) {
+            const M2MObjectList &object_list = endpoint->objects();
+            tr_debug("M2MNsdlInterface::create_nsdl_endpoint_structure - Object count %d", object_list.size());
+            if(!object_list.empty()) {
+                M2MObjectList::const_iterator it;
+                it = object_list.begin();
+                for ( ; it != object_list.end(); it++ ) {
+                    // Create NSDL structure for all object instances inside
+                    success = create_nsdl_object_structure(*it);
+                }
+            }
+            if (!create_nsdl_resource(endpoint)) {
+                success = false;
+            }
+            endpoint->clear_changed();
+        }
+    }
+    return success;
+}
+#endif
+
+bool M2MNsdlInterface::create_nsdl_object_structure(M2MObject *object)
+{
+    bool success = false;
+    if(object) {
+        const M2MObjectInstanceList &instance_list = object->instances();
+        if(!instance_list.empty()) {
+           M2MObjectInstanceList::const_iterator it;
+           it = instance_list.begin();
+           for ( ; it != instance_list.end(); it++ ) {
+               // Create NSDL structure for all object instances inside
+               success = create_nsdl_object_instance_structure(*it);
+           }
+        }
+    }
+    if(object && object->operation() != M2MBase::NOT_ALLOWED) {
+        success = create_nsdl_resource(object);
+    }
+
+    return success;
+}
+
+bool M2MNsdlInterface::create_nsdl_object_instance_structure(M2MObjectInstance *object_instance)
+{
+    bool success = false;
+    if( object_instance) {
+        const M2MResourceList &res_list = object_instance->resources();
+        if(!res_list.empty()) {
+            M2MResourceList::const_iterator it;
+            it = res_list.begin();
+            for ( ; it != res_list.end(); it++ ) {
+                // Create NSDL structure for all resources inside
+                success = create_nsdl_resource_structure(*it,
+                                                         (*it)->supports_multiple_instances());
+            }
+        }
+        if(object_instance->operation() != M2MBase::NOT_ALLOWED) {
+            success = create_nsdl_resource(object_instance);
+        }
+    }
+    return success;
+}
+
+bool M2MNsdlInterface::create_nsdl_resource_structure(M2MResource *res,
+                                                      bool multiple_instances)
+{
+    bool success = false;
+    if(res) {
+        // if there are multiple instances supported
+        if(multiple_instances) {
+            const M2MResourceInstanceList &res_list = res->resource_instances();
+            if(!res_list.empty()) {
+                M2MResourceInstanceList::const_iterator it;
+                it = res_list.begin();
+                for ( ; it != res_list.end(); it++ ) {
+                    success = create_nsdl_resource((*it));
+                    if(!success) {
+                        tr_error("M2MNsdlInterface::create_nsdl_resource_structure - instance creation failed");
+                        return false;
+                    }
+                }
+                // Register the main Resource as well along with ResourceInstances
+                success = create_nsdl_resource(res);
+            }
+        } else {
+            success = create_nsdl_resource(res);
+        }
+    }
+    return success;
+}
+
+bool M2MNsdlInterface::create_nsdl_resource(M2MBase *base)
+{
+    claim_mutex();
+    bool success = false;
+    if(base) {
+        int8_t result = 0;
+        sn_nsdl_dynamic_resource_parameters_s* nsdl_resource = base->get_nsdl_resource();
+
+        // needed on deletion
+        if (base->observation_handler() == NULL) {
+            base->set_observation_handler(this);
+        }
+
+        result = sn_nsdl_put_resource(_nsdl_handle, nsdl_resource);
+
+        // Put under observation if auto-obs feature is set.
+        // TODO! What if the observation is set in multiple levels?
+        if (nsdl_resource && nsdl_resource->auto_observable && result != SN_GRS_RESOURCE_ALREADY_EXISTS) {
+            base->set_under_observation(true, base->observation_handler());
+
+            // Increment auto-obs token to be unique in every object
+            _auto_obs_token++;
+            if (_auto_obs_token > AUTO_OBS_TOKEN_MAX) {
+                _auto_obs_token = 1;
+            }
+
+            // Store token in big-endian byte order
+            uint8_t token[sizeof(uint16_t)];
+            common_write_16_bit(_auto_obs_token, token);
+            base->set_observation_token(token, sizeof(uint16_t));
+
+            switch (base->base_type()) {
+                case M2MBase::Object:
+                    base->add_observation_level(M2MBase::O_Attribute);
+                    break;
+
+                case M2MBase::ObjectInstance:
+                    base->add_observation_level(M2MBase::OI_Attribute);
+                    break;
+
+                case M2MBase::Resource:
+                case M2MBase::ResourceInstance:
+                    base->add_observation_level(M2MBase::R_Attribute);
+                    break;
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+                case M2MBase::ObjectDirectory:
+                    break;
+#endif
+            }
+        }
+
+        // Either the resource is created or it already
+        // exists , then result is success.
+        if (result == 0 ||
+            result == SN_GRS_RESOURCE_ALREADY_EXISTS){
+            success = true;
+        }
+    }
+    release_mutex();
+    return success;
+}
+
+// convenience method to get the URI from its buffer field...
+String M2MNsdlInterface::coap_to_string(const uint8_t *coap_data, int coap_data_length)
+{
+    String value = "";
+    if (coap_data != NULL && coap_data_length > 0) {
+        value.append_raw((char *)coap_data,coap_data_length);
+    }
+    return value;
+}
+
+uint64_t M2MNsdlInterface::registration_time() const
+{
+    uint64_t value = 0;
+    if(_endpoint) {
+        value = _server->resource_value_int(M2MServer::Lifetime);
+    }
+    if(value < MINIMUM_REGISTRATION_TIME) {
+        tr_warn("M2MNsdlInterface::registration_time - stored value in resource (in seconds) %" PRIu64, value);
+        value = MINIMUM_REGISTRATION_TIME;
+    }
+
+    if(value >= OPTIMUM_LIFETIME) {
+        value = value - REDUCE_LIFETIME;
+    } else {
+        value = REDUCTION_FACTOR * value;
+    }
+    tr_debug("M2MNsdlInterface::registration_time - value (in seconds) %" PRIu64, value);
+    return value;
+}
+
+M2MBase* M2MNsdlInterface::find_resource(const String &object_name,
+                                         const uint16_t msg_id) const
+{
+    tr_debug("M2MNsdlInterface::find_resource(object level) - from %p name (%s) ", this, object_name.c_str());
+    M2MObject *current = NULL;
+    M2MBase *found = NULL;
+    if(!_base_list.empty()) {
+        M2MBaseList::const_iterator it;
+        it = _base_list.begin();
+        for ( ; it != _base_list.end(); it++ ) {
+            if ((*it)->base_type() == M2MBase::Object) {
+                current = (M2MObject*)*it;
+                if (!msg_id) {
+                    tr_debug("M2MNsdlInterface::find_resource(object level) - path (%s)",
+                             (char*)current->uri_path());
+                    if (strcmp((char*)current->uri_path(), object_name.c_str()) == 0) {
+                        found = current;
+                        tr_debug("M2MNsdlInterface::find_resource(%s) found", object_name.c_str());
+                        break;
+                    }
+                } else {
+                    uint16_t stored_msg_id = current->get_notification_msgid();
+                    tr_debug("M2MNsdlInterface::find_resource(object level) - stored msgid (%d)", stored_msg_id);
+                    if (stored_msg_id == msg_id) {
+                        found = current;
+                        tr_debug("M2MNsdlInterface::find_resource - msg id found");
+                        break;
+                    }
+                }
+                found = find_resource(current, object_name, msg_id);
+                if(found != NULL) {
+                    break;
+                }
+            }
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+            else if ((*it)->base_type() == M2MBase::ObjectDirectory) {
+                M2MEndpoint *ep = (M2MEndpoint*)*it;
+                if(!strcmp((char*)(*it)->uri_path(), object_name.c_str())) {
+                    found = NULL;
+                    break;
+                } else {
+                    found = find_resource(ep, object_name, msg_id);
+                }
+                if(found != NULL) {
+                    break;
+                }
+            }
+#endif
+        }
+    }
+    return found;
+}
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+M2MBase* M2MNsdlInterface::find_resource(const M2MEndpoint *endpoint,
+                                         const String &object_name,
+                                         const uint16_t msg_id) const
+{
+    tr_debug("M2MNsdlInterface::find_resource(endpoint level) - name (%s)", object_name.c_str());
+    M2MBase *object = NULL;
+    if(endpoint) {
+        const M2MObjectList &list = endpoint->objects();
+        if(!list.empty()) {
+            M2MObjectList::const_iterator it;
+            it = list.begin();
+            for ( ; it != list.end(); it++ ) {
+                if (!msg_id) {
+                    if (!strcmp((char*)(*it)->uri_path(), object_name.c_str())) {
+                        tr_debug("M2MNsdlInterface::find_resource(endpoint level) - object %p object name (%s)",
+                            object, object_name.c_str());
+                        object = (*it);
+                        break;
+                    }
+                } else {
+                    uint16_t stored_msg_id = (*it)->get_notification_msgid();
+                    tr_debug("M2MNsdlInterface::find_resource(endpoint level) - stored msgid (%d)", stored_msg_id);
+                    if (stored_msg_id == msg_id) {
+                        object = (*it);
+                        break;
+                    }
+                }
+                object = find_resource((*it),object_name, msg_id);
+                if(object != NULL){
+                    break;
+                }
+            }
+        }
+    }
+    return object;
+}
+#endif
+
+M2MBase* M2MNsdlInterface::find_resource(const M2MObject *object,
+                                         const String &object_instance,
+                                         const uint16_t msg_id) const
+{
+    M2MBase *instance = NULL;
+    if(object) {
+        const M2MObjectInstanceList &list = object->instances();
+        if(!list.empty()) {
+            M2MObjectInstanceList::const_iterator it;
+            it = list.begin();
+            for ( ; it != list.end(); it++ ) {
+                if (!msg_id) {
+                    if(!strcmp((char*)(*it)->uri_path(), object_instance.c_str())){
+                        instance = (*it);
+                        tr_debug("M2MNsdlInterface::find_resource(object instance level) - found (%s)",
+                                 (char*)(*it)->uri_path());
+                        break;
+                    }
+                } else {
+                    uint16_t stored_msg_id = (*it)->get_notification_msgid();
+                    if (stored_msg_id == msg_id) {
+                        instance = (*it);
+                        tr_debug("M2MNsdlInterface::find_resource(object instance level) - found msgid (%d)", stored_msg_id);
+                        break;
+                    }
+                }
+                instance = find_resource((*it),object_instance, msg_id);
+                if(instance != NULL){
+                    break;
+                }
+            }
+        }
+    }
+    return instance;
+}
+
+M2MBase* M2MNsdlInterface::find_resource(const M2MObjectInstance *object_instance,
+                                         const String &resource_instance,
+                                         const uint16_t msg_id) const
+{
+    M2MBase *instance = NULL;
+    if(object_instance) {
+        const M2MResourceList &list = object_instance->resources();
+        if(!list.empty()) {
+            M2MResourceList::const_iterator it;
+            it = list.begin();
+            for ( ; it != list.end(); it++ ) {
+                if (!msg_id) {
+                    if(!strcmp((char*)(*it)->uri_path(), resource_instance.c_str())) {
+                        instance = *it;
+                        break;
+                    }
+                    else if((*it)->supports_multiple_instances()) {
+                        instance = find_resource((*it), (*it)->uri_path(),
+                                                 resource_instance);
+                        if(instance != NULL){
+                            break;
+                        }
+                    }
+                } else {
+                    uint16_t stored_msg_id = (*it)->get_notification_msgid();
+                    if (stored_msg_id == msg_id) {
+                        instance = *it;
+                        tr_debug("M2MNsdlInterface::find_resource(resource level) - found msgid (%d)", stored_msg_id);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    return instance;
+}
+
+M2MBase* M2MNsdlInterface::find_resource(const M2MResource *resource,
+                                         const String &object_name,
+                                         const String &resource_instance) const
+{
+    M2MBase *res = NULL;
+    if(resource) {
+        if(resource->supports_multiple_instances()) {
+            const M2MResourceInstanceList &list = resource->resource_instances();
+            if(!list.empty()) {
+                M2MResourceInstanceList::const_iterator it;
+                it = list.begin();
+                for ( ; it != list.end(); it++ ) {
+                    if(!strcmp((char*)(*it)->uri_path(), resource_instance.c_str())){
+                        res = (*it);
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    return res;
+}
+
+bool M2MNsdlInterface::object_present(M2MBase* base) const
+{
+    bool success = false;
+    if(base && !_base_list.empty()) {
+        M2MBaseList::const_iterator it;
+        it = _base_list.begin();
+        for ( ; it != _base_list.end(); it++ ) {
+            if((*it) == base) {
+                success = true;
+                break;
+            }
+        }
+    }
+    return success;
+}
+
+int M2MNsdlInterface::object_index(M2MBase* base) const
+{
+    int found_index = -1;
+    int index;
+    if(base && !_base_list.empty()) {
+        M2MBaseList::const_iterator it;
+
+        for (it = _base_list.begin(), index = 0; it != _base_list.end(); it++, index++) {
+            if((*it) == base) {
+                found_index = index;
+                break;
+            }
+        }
+    }
+    return found_index;
+}
+
+
+bool M2MNsdlInterface::add_object_to_list(M2MBase* object)
+{
+    tr_debug("M2MNsdlInterface::add_object_to_list this=%p object=%p", this, object);
+    bool success = false;
+    if(object && !object_present(object)) {
+        _base_list.push_back(object);
+        success = true;
+    }
+    return success;
+}
+
+bool M2MNsdlInterface::remove_object_from_list(M2MBase* object)
+{
+    tr_debug("M2MNsdlInterface::remove_object_from_list this=%p object=%p", this, object);
+    bool success = false;
+    int index;
+    if(object && (-1 != (index = object_index(object)))) {
+        tr_debug("  object found at index %d", index);
+        _base_list.erase(index);
+        success = true;
+    }
+    return success;
+}
+
+M2MInterface::Error M2MNsdlInterface::interface_error(const sn_coap_hdr_s &coap_header)
+{
+    M2MInterface::Error error;
+    switch(coap_header.msg_code) {
+        case COAP_MSG_CODE_RESPONSE_BAD_REQUEST:
+        case COAP_MSG_CODE_RESPONSE_BAD_OPTION:
+        case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE:
+        case COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED:
+        case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE:
+        case COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT:
+            error = M2MInterface::InvalidParameters;
+            break;
+        case COAP_MSG_CODE_RESPONSE_UNAUTHORIZED:
+        case COAP_MSG_CODE_RESPONSE_FORBIDDEN:
+        case COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE:
+        case COAP_MSG_CODE_RESPONSE_NOT_FOUND:
+        case COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED:
+            error = M2MInterface::NotAllowed;
+            break;
+        case COAP_MSG_CODE_RESPONSE_CREATED:
+        case COAP_MSG_CODE_RESPONSE_DELETED:
+        case COAP_MSG_CODE_RESPONSE_VALID:
+        case COAP_MSG_CODE_RESPONSE_CHANGED:
+        case COAP_MSG_CODE_RESPONSE_CONTENT:
+            error = M2MInterface::ErrorNone;
+            break;
+        default:
+            error = M2MInterface::UnknownError;
+            break;
+    }
+    if(coap_header.coap_status == COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED) {
+        error = M2MInterface::NetworkError;
+    }
+    return error;
+}
+
+const char *M2MNsdlInterface::coap_error(const sn_coap_hdr_s &coap_header)
+{
+    if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_BAD_REQUEST) {
+        return COAP_ERROR_REASON_1;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_BAD_OPTION) {
+        return COAP_ERROR_REASON_2;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE) {
+        return COAP_ERROR_REASON_3;
+    }else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED) {
+        return COAP_ERROR_REASON_4;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE) {
+        return COAP_ERROR_REASON_5;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT) {
+        return COAP_ERROR_REASON_6;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_UNAUTHORIZED) {
+        return COAP_ERROR_REASON_7;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_FORBIDDEN) {
+        return COAP_ERROR_REASON_8;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE) {
+        return COAP_ERROR_REASON_9;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_NOT_FOUND) {
+        return COAP_ERROR_REASON_10;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED) {
+        return COAP_ERROR_REASON_11;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE) {
+        return COAP_ERROR_REASON_13;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR) {
+        return COAP_ERROR_REASON_14;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_BAD_GATEWAY) {
+        return COAP_ERROR_REASON_15;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT) {
+        return COAP_ERROR_REASON_16;
+    } else if (coap_header.msg_code == COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED) {
+        return COAP_ERROR_REASON_17;
+    } else if (coap_header.coap_status == COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED) {
+        return COAP_ERROR_REASON_12;
+    }
+    return COAP_NO_ERROR;
+}
+
+void M2MNsdlInterface::send_object_observation(M2MObject *object,
+                                               uint16_t obs_number,
+                                               const m2m::Vector<uint16_t> &changed_instance_ids,
+                                               bool send_object)
+{
+    tr_info("M2MNsdlInterface::send_object_observation");
+    if(object) {
+        uint8_t *value = 0;
+        uint32_t length = 0;
+        uint8_t token[MAX_TOKEN_SIZE];
+        uint8_t token_length = 0;
+
+        // Send whole object structure
+        if (send_object) {
+            value = M2MTLVSerializer::serialize(object->instances(), length);
+        }
+        // Send only changed object instances
+        else {
+            M2MObjectInstanceList list;
+            Vector<uint16_t>::const_iterator it;
+            it = changed_instance_ids.begin();
+            for (; it != changed_instance_ids.end(); it++){
+                M2MObjectInstance* obj_instance = object->object_instance(*it);
+                if (obj_instance){
+                    list.push_back(obj_instance);
+                }
+            }
+            if (!list.empty()) {
+                value = M2MTLVSerializer::serialize(list, length);
+                list.clear();
+            }
+        }
+
+        object->get_observation_token((uint8_t*)&token,token_length);
+
+        object->report_handler()->set_blockwise_notify(is_blockwise_needed(length));
+
+        int32_t msgid = sn_nsdl_send_observation_notification(_nsdl_handle, token, token_length, value, length,
+                                                              sn_coap_observe_e(obs_number), COAP_MSG_TYPE_CONFIRMABLE,
+                                                              sn_coap_content_format_e(object->coap_content_type()), -1);
+        execute_notification_delivery_status_cb(object, msgid);
+
+        memory_free(value);
+    }
+}
+
+void M2MNsdlInterface::send_object_instance_observation(M2MObjectInstance *object_instance,
+                                                        uint16_t obs_number)
+{
+    tr_info("M2MNsdlInterface::send_object_instance_observation");
+    if(object_instance) {
+        uint8_t *value = 0;
+        uint32_t length = 0;
+        uint8_t token[MAX_TOKEN_SIZE];
+        uint8_t token_length = 0;
+
+        value = M2MTLVSerializer::serialize(object_instance->resources(), length);
+
+        object_instance->get_observation_token((uint8_t*)&token,token_length);
+
+        object_instance->report_handler()->set_blockwise_notify(is_blockwise_needed(length));
+
+        int32_t msgid = sn_nsdl_send_observation_notification(_nsdl_handle, token, token_length, value, length,
+                                                               sn_coap_observe_e(obs_number), COAP_MSG_TYPE_CONFIRMABLE,
+                                                               sn_coap_content_format_e(object_instance->coap_content_type()), -1);
+
+        execute_notification_delivery_status_cb(object_instance, msgid);
+
+
+        memory_free(value);
+    }
+}
+
+void M2MNsdlInterface::send_resource_observation(M2MResource *resource,
+                                                 uint16_t obs_number)
+{
+    if(resource) {
+        tr_info("M2MNsdlInterface::send_resource_observation - uri %s", resource->uri_path());
+        uint8_t *value = 0;
+        uint32_t length = 0;
+        uint8_t token[MAX_TOKEN_SIZE];
+        uint8_t token_length = 0;
+
+        resource->get_observation_token((uint8_t*)token,token_length);
+        uint16_t content_type = resource->coap_content_type();
+        if (M2MResourceBase::OPAQUE == resource->resource_instance_type()) {
+            content_type = COAP_CONTENT_OMA_OPAQUE_TYPE;
+        }
+
+        if (resource->resource_instance_count() > 0 || content_type == COAP_CONTENT_OMA_TLV_TYPE) {
+            value = M2MTLVSerializer::serialize(resource, length);
+        } else {
+            resource->get_value(value,length);
+        }
+
+        resource->report_handler()->set_blockwise_notify(is_blockwise_needed(length));
+
+        int32_t msgid = sn_nsdl_send_observation_notification(_nsdl_handle, token, token_length, value, length,
+                                                                   sn_coap_observe_e(obs_number),
+                                                                   COAP_MSG_TYPE_CONFIRMABLE,
+                                                                   sn_coap_content_format_e(content_type), -1);
+        execute_notification_delivery_status_cb(resource, msgid);
+
+        memory_free(value);
+    }
+}
+nsdl_s * M2MNsdlInterface::get_nsdl_handle() const
+{
+    return _nsdl_handle;
+}
+
+void M2MNsdlInterface::handle_bootstrap_put_message(sn_coap_hdr_s *coap_header,
+                                                sn_nsdl_addr_s *address) {
+#ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_info("M2MNsdlInterface::handle_bootstrap_put_message");
+    uint8_t response_code = COAP_MSG_CODE_RESPONSE_CHANGED;
+    sn_coap_hdr_s *coap_response = NULL;
+    bool success = false;
+    uint16_t content_type = 0;
+    char buffer[MAX_ALLOWED_ERROR_STRING_LENGTH];
+    buffer[0] = '\0';
+    M2MNsdlInterface::ObjectType object_type = M2MNsdlInterface::SECURITY;
+
+    if (!_security) {
+        _security = M2MSecurity::get_instance();
+    }
+
+    String resource_name = coap_to_string(coap_header->uri_path_ptr,
+                                          coap_header->uri_path_len);
+    tr_debug("M2MNsdlInterface::handle_bootstrap_put_message - object path %s", resource_name.c_str());
+
+    // Security object
+    if (resource_name.compare(0,1,"0") == 0) {
+        object_type = M2MNsdlInterface::SECURITY;
+        success = true;
+    }
+    // Server object
+    else if (resource_name.compare(0,1,"1") == 0) {
+        object_type = M2MNsdlInterface::SERVER;
+        success = true;
+    }
+    // Device object
+    else if (resource_name.compare(0,1,"3") == 0) {
+        M2MDevice* dev = M2MInterfaceFactory::create_device();
+        // Not mandatory resource, that's why it must be created first
+        dev->create_resource(M2MDevice::CurrentTime, 0);
+        object_type = M2MNsdlInterface::DEVICE;
+        success = true;
+    }
+
+    if (success) {
+        if(coap_header->content_format != COAP_CT_NONE) {
+            content_type = coap_header->content_format;
+        }
+
+        if (content_type != COAP_CONTENT_OMA_TLV_TYPE &&
+            content_type != COAP_CONTENT_OMA_TLV_TYPE_OLD) {
+            tr_error("M2MNsdlInterface::handle_bootstrap_put_message - content_type %d", content_type);
+            success = false;
+        }
+        // Parse TLV message and check is the object valid
+        if (success) {
+            change_operation_mode(_security, M2MBase::PUT_ALLOWED);
+            success = parse_bootstrap_message(coap_header, object_type);
+            if (success && object_type == M2MNsdlInterface::SECURITY) {
+                success = validate_security_object();
+                if (!success) {
+                    const char *desc = "Invalid security object";
+                    if (strlen(ERROR_REASON_22) + strlen(desc) <= MAX_ALLOWED_ERROR_STRING_LENGTH) {
+                        snprintf(buffer, sizeof(buffer), ERROR_REASON_22, desc);
+                    }
+                    response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+                }
+            }
+            // Set operation back to default ones
+            if (_security) {
+                change_operation_mode(_security, M2MBase::NOT_ALLOWED);
+            }
+        }
+    }
+
+    if (!success) {
+        response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+    }
+
+    coap_response = sn_nsdl_build_response(_nsdl_handle,
+                                           coap_header,
+                                           response_code);
+
+    if (coap_response) {
+        sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response);
+        sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response);
+    }
+
+    if (!success) {
+        // Do not overwrite ERROR_REASON_22
+        if (strlen(buffer) == 0) {
+            if (strlen(ERROR_REASON_20) + resource_name.size() <= MAX_ALLOWED_ERROR_STRING_LENGTH) {
+                snprintf(buffer, sizeof(buffer), ERROR_REASON_20, resource_name.c_str());
+            }
+        }
+        handle_bootstrap_error(buffer, true);
+    }
+#else
+    (void) coap_header;
+    (void) address;
+#endif
+}
+
+bool M2MNsdlInterface::parse_bootstrap_message(sn_coap_hdr_s *coap_header,
+                                               M2MNsdlInterface::ObjectType lwm2m_object_type)
+{
+#ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_info("M2MNsdlInterface::parse_bootstrap_message");
+    bool ret = false;
+    bool is_obj_instance = false;
+    uint16_t instance_id = 0;
+    if (_security) {
+        ret = is_obj_instance = M2MTLVDeserializer::is_object_instance(coap_header->payload_ptr);
+        if (!is_obj_instance) {
+            ret = M2MTLVDeserializer::is_resource(coap_header->payload_ptr);
+        }
+        if (ret) {
+            M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
+            if (is_obj_instance) {
+                M2MObject* dev_object = static_cast<M2MObject*> (M2MInterfaceFactory::create_device());
+
+                switch (lwm2m_object_type) {
+                    case M2MNsdlInterface::SECURITY:
+                        instance_id = M2MTLVDeserializer::instance_id(coap_header->payload_ptr);
+                        if (_security->object_instance(instance_id) == NULL) {
+                            tr_debug("M2MNsdlInterface::parse_bootstrap_message - create instance %d", instance_id);
+                            _security->create_object_instance(M2MSecurity::M2MServer);
+                            change_operation_mode(_security, M2MBase::PUT_ALLOWED);
+                        }
+
+                        error = M2MTLVDeserializer::deserialise_object_instances(coap_header->payload_ptr,
+                                                                   coap_header->payload_len,
+                                                                   *_security,
+                                                                   M2MTLVDeserializer::Put);
+                        break;
+                    case M2MNsdlInterface::SERVER:
+                        error = M2MTLVDeserializer::deserialise_object_instances(coap_header->payload_ptr,
+                                                                   coap_header->payload_len,
+                                                                   *_server,
+                                                                   M2MTLVDeserializer::Put);
+                        break;
+                    case M2MNsdlInterface::DEVICE:
+                        error = M2MTLVDeserializer::deserialise_object_instances(coap_header->payload_ptr,
+                                                                   coap_header->payload_len,
+                                                                   *dev_object,
+                                                                   M2MTLVDeserializer::Put);
+                        break;
+                    default:
+                        break;
+                }
+            }
+            else {
+                instance_id = M2MTLVDeserializer::instance_id(coap_header->payload_ptr);
+                M2MObjectInstance* instance = NULL;
+                switch (lwm2m_object_type) {
+                    case M2MNsdlInterface::SECURITY:
+                        instance = _security->object_instance(instance_id);
+                        if (instance) {
+                            error = M2MTLVDeserializer::deserialize_resources(coap_header->payload_ptr,
+                                                                       coap_header->payload_len,
+                                                                       *instance,
+                                                                       M2MTLVDeserializer::Put);
+                        } else {
+                            error = M2MTLVDeserializer::NotValid;
+                        }
+
+                        break;
+                    case M2MNsdlInterface::SERVER:
+                        instance = _server->object_instance(instance_id);
+                        if (instance) {
+                            error = M2MTLVDeserializer::deserialize_resources(coap_header->payload_ptr,
+                                                                       coap_header->payload_len,
+                                                                       *instance,
+                                                                       M2MTLVDeserializer::Post);
+                        } else {
+                            error = M2MTLVDeserializer::NotValid;
+                        }
+
+                        break;
+                    case M2MNsdlInterface::DEVICE:
+                    default:
+                        break;
+                }
+            }
+
+            if (error != M2MTLVDeserializer::None) {
+                tr_error("M2MNsdlInterface::parse_bootstrap_message - error %d", error);
+                ret = false;
+            }
+        }
+    } else {
+        tr_error("M2MNsdlInterface::parse_bootstrap_message -- no security object!");
+    }
+    return ret;
+#else
+    (void) coap_header;
+    (void) is_security_object;
+    return false;
+#endif
+}
+
+void M2MNsdlInterface::handle_bootstrap_finished(sn_coap_hdr_s *coap_header,sn_nsdl_addr_s *address)
+{
+#ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    char buffer[MAX_ALLOWED_ERROR_STRING_LENGTH];
+
+    String object_name = coap_to_string(coap_header->uri_path_ptr,
+                                        coap_header->uri_path_len);
+
+    int32_t m2m_id = -1;
+    // Security object can be null in case messages are coming in wrong order, for example
+    // BS POST is received before BS PUT.
+    if (_security) {
+        m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
+    }
+
+    tr_info("M2MNsdlInterface::handle_bootstrap_finished - path: %s, m2mid: %d", object_name.c_str(), m2m_id);
+
+#ifndef MBED_CLIENT_DISABLE_EST_FEATURE
+    // In EST mode we must receive iep in uri-query
+    bool est_iep_ok = false;
+    if (m2m_id >= 0 &&
+        _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id) == M2MSecurity::EST) {
+        if (coap_header->options_list_ptr && coap_header->options_list_ptr->uri_query_ptr) {
+            String uri_query = coap_to_string(coap_header->options_list_ptr->uri_query_ptr,
+                                              coap_header->options_list_ptr->uri_query_len);
+            tr_info("M2MNsdlInterface::handle_bootstrap_finished - query: %s", uri_query.c_str());
+            const char *iep_ptr = NULL;
+            const int iep_len = parse_query_parameter_value_from_query(uri_query.c_str(), QUERY_PARAM_IEP, &iep_ptr);
+            if (iep_ptr && iep_len > 0) {
+                est_iep_ok = true;
+                _internal_endpoint_name.clear();
+                _internal_endpoint_name.append_raw(iep_ptr, iep_len);
+                tr_info("M2MNsdlInterface::handle_bootstrap_finished - iep: %s", _internal_endpoint_name.c_str());
+            }
+        }
+    }
+#endif
+
+    sn_coap_hdr_s *coap_response = NULL;
+    uint8_t msg_code = COAP_MSG_CODE_RESPONSE_CHANGED;
+    // Accept only '/bs' path and check that needed data is in security object
+    if (object_name.size() != 2 ||
+        object_name.compare(0, 2, BOOTSTRAP_URI) != 0) {
+        if (strlen(ERROR_REASON_22) + object_name.size() <= MAX_ALLOWED_ERROR_STRING_LENGTH) {
+            snprintf(buffer, sizeof(buffer), ERROR_REASON_22, object_name.c_str());
+        }
+        msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+    }
+#ifndef MBED_CLIENT_DISABLE_EST_FEATURE
+    else if (!est_iep_ok &&
+             m2m_id >= 0 &&
+             _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id) == M2MSecurity::EST) {
+        tr_error("M2MNsdlInterface::handle_bootstrap_finished - EST mode but missing iep parameter!");
+        snprintf(buffer, sizeof(buffer), ERROR_REASON_26);
+        msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+    }
+#endif
+    else {
+        // Add short server id to server object
+        if (m2m_id == -1) {
+            snprintf(buffer,sizeof(buffer), ERROR_REASON_4);
+            msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+        }
+        else {
+            _server->set_resource_value(M2MServer::ShortServerID,
+                                        _security->resource_value_int(M2MSecurity::ShortServerID, m2m_id));
+        }
+    }
+
+    // In ok case send response as a separate response
+    if (msg_code == COAP_MSG_CODE_RESPONSE_CHANGED) {
+        send_empty_ack(coap_header, address);
+    // In error case use piggybacked response
+    } else {
+        coap_response = sn_nsdl_build_response(_nsdl_handle, coap_header, msg_code);
+        if (coap_response) {
+            sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response);
+            sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response);
+        }
+
+        handle_bootstrap_error(buffer, true);
+    }
+
+    // Send a event which is responsible of sending the final response
+    if (COAP_MSG_CODE_RESPONSE_CHANGED == msg_code) {
+        sn_coap_hdr_s *coap_message = sn_nsdl_build_response(_nsdl_handle, coap_header, (sn_coap_msg_code_e)msg_code);
+        nsdl_coap_data_s *nsdl_coap_data = create_coap_event_data(coap_message,
+                                                                  address,
+                                                                  _nsdl_handle,
+                                                                  (sn_coap_msg_code_e)msg_code);
+
+        if (nsdl_coap_data) {
+            _event.data.event_type = MBED_CLIENT_NSDLINTERFACE_BS_EVENT;
+            _event.data.data_ptr = (void*)nsdl_coap_data;
+            eventOS_event_send_user_allocated(&_event);
+
+            // Switch back to original ep name
+            if (_endpoint->endpoint_name_ptr) {
+                memory_free(_endpoint->endpoint_name_ptr);
+            }
+
+            _endpoint->endpoint_name_ptr = alloc_string_copy((uint8_t*)_endpoint_name.c_str(), _endpoint_name.length());
+            _endpoint->endpoint_name_len = _endpoint_name.length();
+        } else {
+            const char *desc = "memory allocation failed";
+            if (strlen(ERROR_REASON_22) + strlen(desc) <= MAX_ALLOWED_ERROR_STRING_LENGTH) {
+                snprintf(buffer, sizeof(buffer), ERROR_REASON_22, desc);
+            }
+
+            handle_bootstrap_error(buffer, true);
+        }
+    }
+#else
+    (void) coap_header;
+    (void) address;
+#endif
+}
+
+void M2MNsdlInterface::handle_bootstrap_delete(sn_coap_hdr_s *coap_header,sn_nsdl_addr_s *address)
+{
+
+#ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    char buffer[MAX_ALLOWED_ERROR_STRING_LENGTH];
+    memset(buffer,0,sizeof(buffer));
+    sn_coap_hdr_s *coap_response = NULL;
+    uint8_t msg_code = COAP_MSG_CODE_RESPONSE_DELETED;
+    String object_name = coap_to_string(coap_header->uri_path_ptr,
+                                          coap_header->uri_path_len);
+    tr_info("M2MNsdlInterface::handle_bootstrap_delete - obj %s", object_name.c_str());
+    if(!_identity_accepted) {
+        tr_warn("M2MNsdlInterface::handle_bootstrap_delete - Message received out-of-order - IGNORE");
+        return;
+    }
+    // Only following paths are accepted, 0, 0/0
+    else if (object_name.size() == 2 || object_name.size() > 3) {
+        if (strlen(ERROR_REASON_21) + object_name.size() <= MAX_ALLOWED_ERROR_STRING_LENGTH) {
+            snprintf(buffer, sizeof(buffer), ERROR_REASON_21,object_name.c_str());
+        }
+        msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+    }
+    else if ((object_name.size() == 1 && object_name.compare(0,1,"0") != 0) ||
+            (object_name.size() == 3 && object_name.compare(0,3,"0/0") != 0)) {
+        if (strlen(ERROR_REASON_21) + object_name.size() <= MAX_ALLOWED_ERROR_STRING_LENGTH) {
+            snprintf(buffer, sizeof(buffer), ERROR_REASON_21, object_name.c_str());
+        }
+        msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+    }
+
+    coap_response = sn_nsdl_build_response(_nsdl_handle,
+                                           coap_header,
+                                           msg_code);
+
+    if(coap_response) {
+        sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response);
+        sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response);
+        if(_security) {
+            _security->clear_resources();
+        }
+    }
+    if (!coap_response || COAP_MSG_CODE_RESPONSE_DELETED != msg_code) {
+        handle_bootstrap_error(buffer, true);
+    }
+#else
+    (void) coap_header;
+    (void) address;
+#endif
+}
+
+bool M2MNsdlInterface::validate_security_object()
+{
+    bool valid = false;
+#ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    const M2MObjectInstanceList &instances = _security->instances();
+    M2MObjectInstanceList::const_iterator it;
+    it = instances.begin();
+    uint16_t instance_id = 0;
+    for ( ; it != instances.end(); it++ ) {
+        valid = true;
+        instance_id = (*it)->instance_id();
+        tr_debug("M2MNsdlInterface::validate_security_object - instance %d", instance_id);
+        String address = _security->resource_value_string(M2MSecurity::M2MServerUri, instance_id);
+        uint32_t sec_mode = _security->resource_value_int(M2MSecurity::SecurityMode, instance_id);
+        uint32_t is_bs_server = _security->resource_value_int(M2MSecurity::BootstrapServer, instance_id);
+
+        uint32_t chain_size = 0;
+        uint32_t server_key_size = 0;
+        uint32_t pkey_size = 0;
+
+        size_t buffer_size = MAX_CERTIFICATE_SIZE;
+        uint8_t certificate[MAX_CERTIFICATE_SIZE];
+        uint8_t *certificate_ptr = (uint8_t *)&certificate;
+
+        // Read through callback if set
+        M2MResource *res = _security->get_resource(M2MSecurity::OpenCertificateChain, instance_id);
+        M2MBase::lwm2m_parameters_s *param = res->get_lwm2m_parameters();
+        if (param->read_write_callback_set) {
+            // Read the chain size
+            if (_security->resource_value_buffer(M2MSecurity::OpenCertificateChain, certificate_ptr, instance_id, &buffer_size) == 0) {
+                // Only set size if no error when reading
+                chain_size = buffer_size;
+            }
+            _security->resource_value_buffer(M2MSecurity::CloseCertificateChain, certificate_ptr, instance_id, &buffer_size);
+        } else {
+            // Read directly from the resource
+            if (_security->resource_value_buffer(M2MSecurity::PublicKey, certificate_ptr, instance_id, &buffer_size) == 0) {
+                // Only set size if no error when reading
+                chain_size = buffer_size;
+            }
+        }
+
+        buffer_size = MAX_CERTIFICATE_SIZE;
+
+        if (_security->resource_value_buffer(M2MSecurity::ServerPublicKey, certificate_ptr, instance_id, &buffer_size) == 0) {
+            // Only set size if no error when reading
+            server_key_size = buffer_size;
+        }
+
+        buffer_size = MAX_CERTIFICATE_SIZE;
+        if (_security->resource_value_buffer(M2MSecurity::Secretkey, certificate_ptr, instance_id, &buffer_size) == 0) {
+            // Only set size if no error when reading
+            pkey_size = buffer_size;
+        }
+
+        tr_info("M2MNsdlInterface::validate_security_object - Server URI /0/0: %s", address.c_str());
+        tr_info("M2MNsdlInterface::validate_security_object - is bs server /0/1: %" PRIu32, is_bs_server);
+        tr_info("M2MNsdlInterface::validate_security_object - Security Mode /0/2: %" PRIu32, sec_mode);
+        tr_info("M2MNsdlInterface::validate_security_object - Public chain size /0/3: %" PRIu32, chain_size);
+        tr_info("M2MNsdlInterface::validate_security_object - Server Public key size /0/4: %" PRIu32, server_key_size);
+        tr_info("M2MNsdlInterface::validate_security_object - Secret key size /0/5: %" PRIu32, pkey_size);
+        if (address.empty()) {
+            return false;
+        }
+
+        switch (sec_mode) {
+        case M2MSecurity::Certificate:
+            // Server public key and client private and public keys should be populated
+            if (!chain_size || !server_key_size || !pkey_size) {
+                return false;
+            }
+            break;
+#ifndef MBED_CLIENT_DISABLE_EST_FEATURE
+        case M2MSecurity::EST:
+            // Only server public key should be populated for lwm2m, client keys will be generated
+            if (!is_bs_server && (!server_key_size || chain_size || pkey_size)) {
+                return false;
+            }
+            break;
+#endif
+        case M2MSecurity::NoSecurity:
+            // Nothing to check for no security
+            break;
+        default:
+            // Security mode not supported
+            return false;
+        }
+    }
+#endif
+    return valid;
+}
+
+
+void M2MNsdlInterface::handle_bootstrap_error(const char *reason, bool wait)
+{
+    tr_error("M2MNsdlInterface::handle_bootstrap_error(%s)",reason);
+    _identity_accepted = false;
+    if (_security) {
+        int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
+        if (m2m_id >= 0) {
+            _security->remove_object_instance(m2m_id);
+        }
+    }
+
+    if (wait) {
+        _observer.bootstrap_error_wait(reason);
+    } else {
+        _observer.bootstrap_error(reason);
+    }
+}
+
+const String& M2MNsdlInterface::endpoint_name() const
+{
+    return _endpoint_name;
+}
+
+const String M2MNsdlInterface::internal_endpoint_name() const
+{
+    String iep("");
+    if (_internal_endpoint_name.length() > 0) {
+        iep = _internal_endpoint_name;
+    }
+    else if (_nsdl_handle->ep_information_ptr->location_ptr) {
+        // If internal_endpoint_name not set yet, parse it from location path
+        String temp((const char*)_nsdl_handle->ep_information_ptr->location_ptr,
+                   _nsdl_handle->ep_information_ptr->location_len);
+        // Get last part of the location path.
+        // In mbed Cloud environment full path is /rd/accountid/internal_endpoint
+        int location = temp.find_last_of('/') + 1;
+        iep.append_raw((const char*)_nsdl_handle->ep_information_ptr->location_ptr + location,
+                   _nsdl_handle->ep_information_ptr->location_len - location);
+    }
+    return iep;
+}
+
+void M2MNsdlInterface::change_operation_mode(M2MObject *object, M2MBase::Operation operation)
+{
+    const M2MObjectInstanceList &instances = object->instances();
+    M2MObjectInstanceList::const_iterator inst = instances.begin();
+    for (; inst != instances.end(); inst++ ) {
+        (*inst)->set_operation(operation);
+        const M2MResourceList &list = (*inst)->resources();
+        if(!list.empty()) {
+            M2MResourceList::const_iterator it;
+            it = list.begin();
+            for ( ; it != list.end(); it++ ) {
+                (*it)->set_operation(operation);
+            }
+        }
+    }
+}
+
+void M2MNsdlInterface::set_server_address(const char* server_address)
+{
+    free(_server_address);
+    _server_address = M2MBase::alloc_string_copy(server_address);
+}
+
+M2MTimer &M2MNsdlInterface::get_nsdl_execution_timer()
+{
+    return _nsdl_execution_timer;
+}
+
+bool M2MNsdlInterface::is_unregister_ongoing() const
+{
+    return _nsdl_handle->unregister_token == 0 ? false : true;
+}
+
+bool M2MNsdlInterface::parse_and_send_uri_query_parameters()
+{
+    bool msg_sent = false;
+    char *address_copy = M2MBase::alloc_string_copy(_server_address);
+    if (address_copy) {
+        char* query = parse_uri_query_parameters(_server_address);
+        if (query != NULL) {
+            size_t query_len = 1 + strlen(query) + 1 + strlen(MCC_VERSION) + 1;
+            if (_custom_uri_query_params) {
+                query_len += 1 + strlen(_custom_uri_query_params);
+            }
+
+            if (query_len <= MAX_URI_QUERY_LEN) {
+                char query_params[MAX_URI_QUERY_LEN];
+                strcpy(query_params, "&");
+                strcat(query_params, query);
+                strcat(query_params, "&");
+                strcat(query_params, MCC_VERSION);
+                if (_custom_uri_query_params) {
+                    strcat(query_params, "&");
+                    strcat(query_params, _custom_uri_query_params);
+                }
+
+                tr_debug("M2MNsdlInterface::parse_and_send_uri_query_parameters - uri params: %s", query_params);
+                sn_nsdl_clear_coap_resending_queue(_nsdl_handle);
+                msg_sent = sn_nsdl_register_endpoint(_nsdl_handle,_endpoint,query_params) != 0;
+            } else {
+                tr_error("M2MNsdlInterface::parse_and_send_uri_query_parameters - max uri param length reached (%lu)",
+                          (unsigned long)query_len);
+            }
+        }
+        free(address_copy);
+    }
+    return msg_sent;
+}
+
+void M2MNsdlInterface::claim_mutex()
+{
+    _connection_handler.claim_mutex();
+}
+
+void M2MNsdlInterface::release_mutex()
+{
+    _connection_handler.release_mutex();
+}
+
+void M2MNsdlInterface::start_nsdl_execution_timer()
+{
+    tr_debug("M2MNsdlInterface::start_nsdl_execution_timer");
+    _nsdl_execution_timer_running = true;
+    _nsdl_execution_timer.stop_timer();
+    _nsdl_execution_timer.start_timer(ONE_SECOND_TIMER * 1000,
+                                      M2MTimerObserver::NsdlExecution,
+                                      false);
+}
+
+M2MSecurity* M2MNsdlInterface::get_security_object()
+{
+    return _security;
+}
+
+void M2MNsdlInterface::update_trigger_callback(void */*argument*/)
+{
+    if (lifetime_value_changed()) {
+        send_update_registration(_server->resource_value_int(M2MServer::Lifetime));
+    } else {
+        send_update_registration();
+    }
+}
+
+bool M2MNsdlInterface::lifetime_value_changed() const
+{
+    uint64_t value = 0;
+    if (_endpoint && _endpoint->lifetime_ptr) {
+        value = atol((const char*)_endpoint->lifetime_ptr);
+    }
+    if (_server->resource_value_int(M2MServer::Lifetime) != value) {
+        return true;
+    }
+    return false;
+}
+
+void M2MNsdlInterface::execute_notification_delivery_status_cb(M2MBase* object, int32_t msgid)
+{
+    if (msgid > 0) {
+        object->send_notification_delivery_status(*object, NOTIFICATION_STATUS_SENT);
+        object->set_notification_msgid(msgid);
+    } else {
+        object->send_notification_delivery_status(*object, NOTIFICATION_STATUS_BUILD_ERROR);
+        _notification_send_ongoing = false;
+    }
+}
+
+uint8_t M2MNsdlInterface::find_auto_obs_token(const char *path, uint8_t *token) const
+{
+    uint8_t token_len = 0;
+    const String name(path);
+    M2MBase *object = find_resource(name, 0);
+    if (object) {
+        object->get_observation_token(token, token_len);
+    }
+    return token_len;
+}
+
+bool M2MNsdlInterface::is_response_to_request(const sn_coap_hdr_s *coap_header, request_context_s &get_data)
+{
+    // ns_list_foreach() replacement since it does not compile with IAR 7.x versions.
+    request_context_s *data = (request_context_s *)ns_list_get_first(&_request_context_list);
+    while (data) {
+        if (memcmp(coap_header->token_ptr, &data->msg_token, sizeof(data->msg_token)) == 0) {
+            get_data = *data;
+            return true;
+        }
+        data = (request_context_s *)ns_list_get_next(&_request_context_list, data);
+    }
+
+    return false;
+}
+
+void M2MNsdlInterface::free_request_context_list(const sn_coap_hdr_s *coap_header)
+{
+    // Clean up whole list
+    if (coap_header == NULL) {
+        // ns_list_foreach() replacement since it does not compile with IAR 7.x versions.
+        while (!ns_list_is_empty(&_request_context_list)) {
+            request_context_s* data = (request_context_s*)ns_list_get_first(&_request_context_list);
+            ns_list_remove(&_request_context_list, data);
+            memory_free(data->uri_path);
+            memory_free(data);
+        }
+
+    // Clean just one item from the list
+    } else {
+        // ns_list_foreach() replacement since it does not compile with IAR 7.x versions.
+        request_context_s *data = (request_context_s *)ns_list_get_first(&_request_context_list);
+        while (data) {
+            if (memcmp(coap_header->token_ptr, &data->msg_token, sizeof(data->msg_token)) == 0) {
+                ns_list_remove(&_request_context_list, data);
+                memory_free(data->uri_path);
+                memory_free(data);
+                return;
+            }
+            data = (request_context_s *)ns_list_get_next(&_request_context_list, data);
+        }
+    }
+}
+
+void M2MNsdlInterface::set_request_context_to_be_resend()
+{
+    // ns_list_foreach() replacement since it does not compile with IAR 7.x versions.
+    request_context_s *data = (request_context_s *)ns_list_get_first(&_request_context_list);
+    while (data) {
+        data->resend = true;
+        data = (request_context_s *)ns_list_get_next(&_request_context_list, data);
+    }
+}
+
+char* M2MNsdlInterface::parse_uri_query_parameters(char* uri)
+{
+    char* query = strchr((char*)uri, '?');
+    if (query != NULL) {
+        query++;
+        if (*query == '\0') {
+            return NULL;
+        } else {
+            return query;
+        }
+    } else {
+        return NULL;
+    }
+}
+
+bool M2MNsdlInterface::set_uri_query_parameters(const char *uri_query_params)
+{
+    tr_debug("M2MNsdlInterface::set_uri_query_parameters");
+    size_t query_len = uri_query_params == NULL ? 0:strlen(uri_query_params);
+    size_t current_len = _custom_uri_query_params == NULL ? 0:strlen(_custom_uri_query_params);
+    size_t new_size = query_len + current_len;
+
+    if (query_len == 0 ||
+        query_len > MAX_ALLOWED_STRING_LENGTH ||
+        new_size > MAX_ALLOWED_STRING_LENGTH) {
+        tr_error("M2MNsdlInterface::set_uri_query_parameters - invalid params!");
+        return false;
+    }
+
+    // Append into existing string
+    if (_custom_uri_query_params) {
+        // Reserve space for "&" and null marks
+        _custom_uri_query_params = (char*)realloc(_custom_uri_query_params, 1 + new_size + 1);
+        if (_custom_uri_query_params == NULL) {
+            return false;
+        }
+
+        memcpy(_custom_uri_query_params + current_len, "&", 1);
+        memcpy(_custom_uri_query_params + current_len + 1, uri_query_params, query_len);
+        _custom_uri_query_params[1 + new_size] = '\0';
+    } else {
+        _custom_uri_query_params = (char*)alloc_string_copy((uint8_t*)uri_query_params, query_len + 1);
+        if (_custom_uri_query_params == NULL) {
+            return false;
+        }
+    }
+
+    tr_info("M2MNsdlInterface::set_uri_query_parameters - query %s", _custom_uri_query_params);
+    return true;
+}
+
+void M2MNsdlInterface::clear_sent_blockwise_messages()
+{
+    sn_nsdl_clear_coap_sent_blockwise_messages(_nsdl_handle);
+}
+
+void M2MNsdlInterface::send_coap_ping()
+{
+    if (_binding_mode != M2MInterface::TCP) {
+        return;
+    }
+
+    if (MBED_CLIENT_TCP_KEEPALIVE_INTERVAL > 0 && _counter_for_nsdl == _next_coap_ping_send_time) {
+        tr_info("M2MNsdlInterface::send_coap_ping()");
+        calculate_new_coap_ping_send_time();
+
+        // Build the CoAP here as the CoAP builder would add the message to re-sending queue.
+        uint8_t packet_ptr[4];
+
+        /* Add CoAP version and message type */
+        packet_ptr[0] = COAP_VERSION_1;
+        packet_ptr[0] |= COAP_MSG_TYPE_CONFIRMABLE;
+
+        /* Add message code */
+        packet_ptr[1] = COAP_MSG_CODE_EMPTY;
+
+        /* Add message ID */
+        packet_ptr[2] = 0;
+        packet_ptr[3] = 0;
+
+        /* Send ping */
+        _nsdl_handle->sn_nsdl_tx_callback(_nsdl_handle, SN_NSDL_PROTOCOL_COAP, packet_ptr, 4, &_nsdl_handle->server_address);
+    }
+}
+
+void M2MNsdlInterface::calculate_new_coap_ping_send_time()
+{
+    if (_binding_mode != M2MInterface::TCP) {
+        return;
+    }
+
+    _next_coap_ping_send_time = _counter_for_nsdl + MBED_CLIENT_TCP_KEEPALIVE_INTERVAL;
+}
+
+void M2MNsdlInterface::send_next_notification(bool clear_token)
+{
+    tr_debug("M2MNsdlInterface::send_next_notification");
+    claim_mutex();
+    if (!_base_list.empty()) {
+        M2MBaseList::const_iterator base_iterator;
+        base_iterator = _base_list.begin();
+        for ( ; base_iterator != _base_list.end(); base_iterator++ ) {
+            if ((*base_iterator)->base_type() == M2MBase::Object) {
+                if (send_next_notification_for_object(*(M2MObject*)*base_iterator, clear_token)) {
+                    release_mutex();
+                    return;
+                }
+            }
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+            else if ((*base_iterator)->base_type() == M2MBase::ObjectDirectory) {
+                M2MEndpoint* endpoint = static_cast<M2MEndpoint*> (*base_iterator);
+                const M2MObjectList& object_list = endpoint->objects();
+                if (!object_list.empty()) {
+                    M2MObjectList::const_iterator object_iterator;
+                    object_iterator = object_list.begin();
+                    // Object level
+                    for ( ; object_iterator != object_list.end(); object_iterator++ ) {
+                        if (send_next_notification_for_object(**object_iterator, clear_token)) {
+                            release_mutex();
+                            return;
+                        }
+                    }
+                }
+            }
+#endif
+        }
+    }
+
+    _notification_send_ongoing = false;
+    release_mutex();
+    tr_debug("M2MNsdlInterface::send_next_notification - nothing to send");
+}
+
+bool M2MNsdlInterface::send_next_notification_for_object(M2MObject& object, bool clear_token) {
+    const M2MObjectInstanceList &object_instance_list = object.instances();
+    M2MReportHandler* reporter = object.report_handler();
+    if (reporter) {
+        if (clear_token && !object.get_nsdl_resource()->auto_observable) {
+            reporter->set_observation_token(NULL, 0);
+        } else if (reporter->is_under_observation() &&
+                   (reporter->notification_in_queue() || reporter->notification_send_in_progress())) {
+            reporter->schedule_report(true);
+            return true;
+        }
+    }
+
+    // Object instance level
+    if (!object_instance_list.empty()) {
+        M2MObjectInstanceList::const_iterator object_instance_iterator;
+        object_instance_iterator = object_instance_list.begin();
+        for ( ; object_instance_iterator != object_instance_list.end(); object_instance_iterator++ ) {
+            M2MReportHandler* reporter = (*object_instance_iterator)->report_handler();
+            if (reporter) {
+                if (clear_token && !(*object_instance_iterator)->get_nsdl_resource()->auto_observable) {
+                    reporter->set_observation_token(NULL, 0);
+                } else if (reporter->is_under_observation() &&
+                           (reporter->notification_in_queue() || reporter->notification_send_in_progress())) {
+                    reporter->schedule_report(true);
+                    return true;
+                }
+            }
+
+            // Resource level
+            const M2MResourceList &resource_list = (*object_instance_iterator)->resources();
+            if (!resource_list.empty()) {
+                M2MResourceList::const_iterator resource_iterator;
+                resource_iterator = resource_list.begin();
+                for ( ; resource_iterator != resource_list.end(); resource_iterator++) {
+                    M2MReportHandler* reporter = (*resource_iterator)->report_handler();
+                    if (reporter) {
+                        // Auto obs token can't be cleared
+                        if (clear_token && !(*resource_iterator)->get_nsdl_resource()->auto_observable) {
+                            reporter->set_observation_token(NULL, 0);
+                        } else if (reporter->is_under_observation() &&
+                                   (reporter->notification_in_queue() || reporter->notification_send_in_progress())) {
+                            reporter->schedule_report(true);
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+void M2MNsdlInterface::send_empty_ack(const sn_coap_hdr_s *header, sn_nsdl_addr_s *address)
+{
+    tr_debug("M2MNsdlInterface::send_empty_ack()");
+    sn_coap_hdr_s *empty_coap_ack = (sn_coap_hdr_s *) memory_alloc(sizeof(sn_coap_hdr_s));
+    if (empty_coap_ack) {
+        memset(empty_coap_ack, 0, sizeof(sn_coap_hdr_s));
+        empty_coap_ack->msg_code = COAP_MSG_CODE_EMPTY;
+        empty_coap_ack->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
+        empty_coap_ack->msg_id = header->msg_id;
+        sn_nsdl_send_coap_message(_nsdl_handle, address, empty_coap_ack);
+        memory_free(empty_coap_ack);
+    }
+}
+
+void M2MNsdlInterface::store_bs_finished_response_id(uint16_t msg_id)
+{
+    tr_debug("M2MNsdlInterface::store_bs_finished_response_id - id %d", msg_id);
+    _bootstrap_id = msg_id;
+}
+
+struct M2MNsdlInterface::nsdl_coap_data_s* M2MNsdlInterface::create_coap_event_data(
+        sn_coap_hdr_s *received_coap_header,
+        sn_nsdl_addr_s *address,
+        struct nsdl_s *nsdl_handle,
+        uint8_t coap_msg_code)
+{
+    nsdl_coap_data_s *nsdl_coap_data = (nsdl_coap_data_s*)memory_alloc(sizeof(nsdl_coap_data_s));
+
+    if (nsdl_coap_data) {
+        nsdl_coap_data->nsdl_handle = nsdl_handle;
+        nsdl_coap_data->address.addr_len = address->addr_len;
+        nsdl_coap_data->address.type = address->type;
+        nsdl_coap_data->address.port = address->port;
+
+        // Needs to copy all the dynamic data since it resides on stack and this wil turn into an event based call.
+        nsdl_coap_data->address.addr_ptr = (uint8_t*) memory_alloc(address->addr_len);
+
+        if (nsdl_coap_data->address.addr_ptr) {
+            memcpy(nsdl_coap_data->address.addr_ptr, address->addr_ptr, address->addr_len);
+            nsdl_coap_data->received_coap_header = received_coap_header;
+            nsdl_coap_data->received_coap_header->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
+            nsdl_coap_data->received_coap_header->msg_code = (sn_coap_msg_code_e)coap_msg_code;
+
+            // Copy payload
+            if ((received_coap_header->payload_len > 0) &&
+                (received_coap_header->coap_status != COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED)) {
+                assert(received_coap_header->payload_ptr);
+
+                uint8_t *temp_ptr = (uint8_t*) memory_alloc(received_coap_header->payload_len);
+                if (temp_ptr) {
+                    memcpy(temp_ptr, received_coap_header->payload_ptr, received_coap_header->payload_len);
+                    nsdl_coap_data->received_coap_header->payload_ptr = temp_ptr;
+                    nsdl_coap_data->received_coap_header->payload_len = received_coap_header->payload_len;
+                } else {
+                    memory_free(nsdl_coap_data->received_coap_header->payload_ptr);
+                    sn_coap_parser_release_allocated_coap_msg_mem(nsdl_handle->grs->coap, nsdl_coap_data->received_coap_header);
+                    memory_free(nsdl_coap_data->address.addr_ptr);
+                    memory_free(nsdl_coap_data);
+                    return NULL;
+                }
+            }
+        } else {
+            memory_free(nsdl_coap_data);
+            return NULL;
+        }
+    } else {
+        return NULL;
+    }
+
+    return nsdl_coap_data;
+}
+
+void M2MNsdlInterface::set_registration_status(bool registered)
+{
+    _registered = registered;
+}
+
+void M2MNsdlInterface::handle_register_response(const sn_coap_hdr_s *coap_header)
+{
+    if(coap_header->msg_code == COAP_MSG_CODE_RESPONSE_CREATED) {
+        tr_info("M2MNsdlInterface::handle_register_response - registered");
+        // If lifetime is less than zero then leave the field empty
+        if(coap_header->options_list_ptr) {
+            uint32_t max_time = coap_header->options_list_ptr->max_age;
+
+            // If a sufficiently-large Max-Age option is present, we interpret it as registration lifetime;
+            // mbed server (mDS) reports lifetime this way as a non-standard extension. Other servers
+            // would likely not include an explicit Max-Age option, in which case we'd see the default 60 seconds.
+            if( max_time >= MINIMUM_REGISTRATION_TIME) {
+                set_endpoint_lifetime_buffer(max_time);
+            }
+            if(coap_header->options_list_ptr->location_path_ptr) {
+                sn_nsdl_set_endpoint_location(_nsdl_handle,
+                                              coap_header->options_list_ptr->location_path_ptr,
+                                              coap_header->options_list_ptr->location_path_len);
+            }
+
+        }
+        if (_endpoint->lifetime_ptr) {
+            _registration_timer.stop_timer();
+            _registration_timer.start_timer(registration_time() * 1000,
+                                             M2MTimerObserver::Registration,
+                                             false);
+        }
+
+        _observer.client_registered(_server);
+
+        calculate_new_coap_ping_send_time();
+
+        _notification_send_ongoing = false;
+
+        // Clear the observation tokens
+        send_next_notification(true);
+
+        // Check if there are any pending download requests
+        send_pending_request();
+
+    } else {
+        tr_error("M2MNsdlInterface::handle_register_response - registration error %d", coap_header->msg_code);
+        if(coap_header->coap_status == COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED) {
+            tr_error("M2MNsdlInterface::handle_register_response - message sending failed !!!!");
+        }
+        // Try to do clean register again
+        if(COAP_MSG_CODE_RESPONSE_BAD_REQUEST == coap_header->msg_code ||
+           COAP_MSG_CODE_RESPONSE_FORBIDDEN == coap_header->msg_code) {
+            _observer.registration_error(M2MInterface::InvalidParameters, false);
+        } else {
+            _observer.registration_error(M2MInterface::NetworkError, true);
+        }
+
+    }
+}
+
+void M2MNsdlInterface::handle_unregister_response(const sn_coap_hdr_s *coap_header)
+{
+    tr_info("M2MNsdlInterface::handle_unregister_response - unregistered");
+    if(coap_header->msg_code == COAP_MSG_CODE_RESPONSE_DELETED) {
+        _registration_timer.stop_timer();
+        _observer.client_unregistered();
+    } else {
+        tr_error("M2MNsdlInterface::handle_unregister_response - unregistration error %d", coap_header->msg_code);
+        M2MInterface::Error error = M2MInterface::UnregistrationFailed;
+        if (coap_header->msg_code == COAP_MSG_CODE_RESPONSE_NOT_FOUND) {
+            _observer.registration_error(error, false);
+        } else {
+            _observer.registration_error(error, true);
+        }
+    }
+}
+
+void M2MNsdlInterface::handle_register_update_response(const sn_coap_hdr_s *coap_header)
+{
+    if (coap_header->msg_code == COAP_MSG_CODE_RESPONSE_CHANGED) {
+        tr_info("M2MNsdlInterface::handle_register_update_response - registration_updated");
+        _observer.registration_updated(*_server);
+
+        _notification_send_ongoing = false;
+        // Check if there are any pending notifications in queue
+        _notification_handler->send_notification(this);
+
+        // Check if there are any pending download requests
+        send_pending_request();
+
+        calculate_new_coap_ping_send_time();
+    } else {
+        tr_error("M2MNsdlInterface::handle_register_update_response - registration_updated failed %d, %d", coap_header->msg_code, coap_header->coap_status);
+        _nsdl_handle->update_register_token = 0;
+        _registration_timer.stop_timer();
+
+        if (coap_header->coap_status == COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED) {
+            // Inform interfaceimpl to do a reconnection and registration update
+            // till we get CoAP level response for the request
+            _observer.registration_error(M2MInterface::NetworkError, true);
+        } else {
+            // Do a full registration
+            bool msg_sent = false;
+            if (_server_address) {
+                msg_sent = parse_and_send_uri_query_parameters();
+            }
+            if (!msg_sent) {
+                sn_nsdl_clear_coap_resending_queue(_nsdl_handle);
+                sn_nsdl_register_endpoint(_nsdl_handle, _endpoint, NULL);
+            }
+        }
+    }
+}
+
+void M2MNsdlInterface::handle_request_response(const sn_coap_hdr_s *coap_header, request_context_s *request_context)
+{
+    tr_info("M2MNsdlInterface::handle_request_response");
+    size_t total_size = 0;
+
+    if (coap_header->options_list_ptr) {
+        if (coap_header->options_list_ptr->use_size2) {
+            total_size = coap_header->options_list_ptr->size2;
+        }
+    } else {
+        total_size = coap_header->payload_len;
+    }
+
+    if (coap_header->msg_code >= COAP_MSG_CODE_RESPONSE_CREATED &&
+        coap_header->msg_code <= COAP_MSG_CODE_RESPONSE_CONTENT) {
+
+        // Take copy of uri_path in case of sync mode
+        // Pointer is freed already by "free_request_context_list" and then used again in send_request() call
+        char *temp = NULL;
+        if (!request_context->async_req) {
+            temp = (char*)alloc_string_copy((uint8_t*)request_context->uri_path, strlen(request_context->uri_path));
+            if (temp == NULL) {
+                request_context->on_request_error_cb(FAILED_TO_ALLOCATE_MEMORY, request_context->context);
+                free_request_context_list(coap_header);
+                return;
+            }
+        }
+
+        // Remove the request before calling the "on_request_data_cb" callback
+        free_request_context_list(coap_header);
+
+        request_context->received_size += coap_header->payload_len;
+        request_context->on_request_data_cb(coap_header->payload_ptr,
+                                            coap_header->payload_len,
+                                            total_size,
+                                            request_context->context);
+
+        // In sync mode, call next request automatically until all blocks have been received
+        if (!request_context->async_req) {
+            if (coap_header->options_list_ptr && coap_header->options_list_ptr->block2 & 0x08) {
+                // Note that payload will be empty here as it should have already been sent
+                // when the initial request was sent!
+                send_request(temp,
+                             request_context->msg_code,
+                             request_context->received_size,
+                             request_context->async_req,
+                             0,
+                             NULL,
+                             request_context->on_request_data_cb,
+                             request_context->on_request_error_cb,
+                             request_context->context);
+            } else {
+                tr_info("M2MNsdlInterface::handle_request_response - all blocks received");
+            }
+
+            memory_free(temp);
+        }
+
+    } else {
+        if (coap_header->coap_status == COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED) {
+            _observer.registration_error(M2MInterface::NetworkError, true);
+        } else {
+            // TODO! Convert coap error code
+            request_error_e error = FAILED_TO_SEND_MSG;
+            request_context->on_request_error_cb(error, request_context->context);
+            free_request_context_list(coap_header);
+        }
+    }
+}
+
+void M2MNsdlInterface::handle_bootstrap_response(const sn_coap_hdr_s *coap_header)
+{
+#ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+    tr_info("M2MNsdlInterface::handle_bootstrap_response");
+    _bootstrap_id = 0;
+    M2MInterface::Error error = interface_error(*coap_header);
+    if (error != M2MInterface::ErrorNone) {
+
+#ifdef DISABLE_ERROR_DESCRIPTION
+        // this ifdef is saving +800B on ARMCC as it gets rid of the COAP_ERROR_* -strings from binary
+        const char *buffer = "";
+#else
+        char buffer[MAX_ALLOWED_ERROR_STRING_LENGTH];
+
+        const char* error = coap_error(*coap_header);
+        strncpy(buffer, error, MAX_ALLOWED_ERROR_STRING_LENGTH);
+        size_t free_space = MAX_ALLOWED_ERROR_STRING_LENGTH - strlen(buffer) + 1;
+        if(coap_header->payload_ptr && free_space > coap_header->payload_len) {
+            strncat(buffer, ":" , 1);
+            strncat(buffer, (char*)coap_header->payload_ptr, coap_header->payload_len);
+        }
+#endif
+        handle_bootstrap_error(buffer, false);
+    } else {
+        _identity_accepted = true;
+    }
+#else
+    (void)coap_header;
+#endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+}
+
+bool M2MNsdlInterface::handle_post_response(sn_coap_hdr_s* coap_header,
+                                            sn_nsdl_addr_s* address,
+                                            sn_coap_hdr_s *&coap_response,
+                                            M2MObjectInstance *&obj_instance,
+                                            bool is_bootstrap_msg)
+{
+    bool execute_value_updated = false;
+
+    if (is_bootstrap_msg) {
+        handle_bootstrap_finished(coap_header, address);
+    } else if (coap_header->uri_path_ptr) {
+
+        String resource_name = coap_to_string(coap_header->uri_path_ptr,
+                                       coap_header->uri_path_len);
+
+        String object_name;
+        int slash_found = resource_name.find_last_of('/');
+        //The POST operation here is only allowed for non-existing object instances
+        if (slash_found != -1) {
+            object_name = resource_name.substr(0,slash_found);
+            if (object_name.find_last_of('/') != -1){
+                coap_response = sn_nsdl_build_response(_nsdl_handle,
+                                                       coap_header,
+                                                       COAP_MSG_CODE_RESPONSE_NOT_FOUND);
+            } else {
+                int32_t instance_id = atoi(resource_name.substr(slash_found+1,
+                                         resource_name.size()-object_name.size()).c_str());
+                M2MBase* base = find_resource(object_name, 0);
+                if(base) {
+                    if((instance_id >= 0) && (instance_id < UINT16_MAX)) {
+                        if(coap_header->payload_ptr) {
+                            M2MObject* object = static_cast<M2MObject*> (base);
+                            obj_instance = object->create_object_instance(instance_id);
+                            if(obj_instance) {
+                                obj_instance->set_operation(M2MBase::GET_PUT_POST_ALLOWED);
+                                coap_response = obj_instance->handle_post_request(_nsdl_handle,
+                                                                                  coap_header,
+                                                                                  this,
+                                                                                  execute_value_updated);
+                            }
+                            if (coap_response && coap_response->msg_code != COAP_MSG_CODE_RESPONSE_CREATED) {
+                                //Invalid request so remove created ObjectInstance
+                                object->remove_object_instance(instance_id);
+                            } else  {
+                                tr_debug("M2MNsdlInterface::handle_post_response - Send Update registration for Create");
+                                if (lifetime_value_changed()) {
+                                    send_update_registration(_server->resource_value_int(M2MServer::Lifetime));
+                                } else {
+                                    send_update_registration();
+                                }
+                            }
+                        } else {
+                            tr_error("M2MNsdlInterface::handle_post_response - Missing Payload - Cannot create");
+                            coap_response = sn_nsdl_build_response(_nsdl_handle,
+                                                                   coap_header,
+                                                                   COAP_MSG_CODE_RESPONSE_BAD_REQUEST);
+                        }
+                    } else { // instance id out of range
+                        tr_error("M2MNsdlInterface::handle_post_response - instance id out of range - Cannot create");
+                        coap_response = sn_nsdl_build_response(_nsdl_handle,
+                                                               coap_header,
+                                                               COAP_MSG_CODE_RESPONSE_BAD_REQUEST);
+                    }
+                } else { // if(base)
+                    tr_error("M2MNsdlInterface::handle_post_response - Missing BASE - Cannot create");
+                    coap_response = sn_nsdl_build_response(_nsdl_handle,
+                                                           coap_header,
+                                                           COAP_MSG_CODE_RESPONSE_NOT_FOUND);
+                }
+            }
+        } else { // if(slash_found != -1)
+            tr_error("M2MNsdlInterface::handle_post_response - slash_found - Cannot create");
+            coap_response = sn_nsdl_build_response(_nsdl_handle,
+                                                   coap_header,
+                                                   COAP_MSG_CODE_RESPONSE_NOT_FOUND);
+        }
+
+    }
+    return execute_value_updated;
+}
+
+void M2MNsdlInterface::handle_empty_ack(const sn_coap_hdr_s *coap_header, bool is_bootstrap_msg)
+{
+    // Cancel ongoing observation
+    if (COAP_MSG_TYPE_RESET == coap_header->msg_type) {
+        M2MBase *base = find_resource("", coap_header->msg_id);
+        if (base) {
+            M2MBase::BaseType type = base->base_type();
+            switch (type) {
+                case M2MBase::Object:
+                    base->remove_observation_level(M2MBase::O_Attribute);
+                    break;
+                case M2MBase::Resource:
+                    base->remove_observation_level(M2MBase::R_Attribute);
+                    break;
+                case M2MBase::ObjectInstance:
+                    base->remove_observation_level(M2MBase::OI_Attribute);
+                    break;
+                default:
+                    break;
+            }
+            base->set_under_observation(false, this);
+            _notification_send_ongoing = false;
+            base->send_notification_delivery_status(*base, NOTIFICATION_STATUS_UNSUBSCRIBED);
+            _notification_handler->send_notification(this);
+        }
+    } else if (is_bootstrap_msg) {
+        if (!_bootstrap_finish_ack_received) {
+            // The _bootstrap_finish_ack_received flag is used to avoid sending the finish event
+            // twice incase we get the same ack before the event loop has handled the event.
+            _observer.bootstrap_wait();
+            tr_debug("M2MNsdlInterface::handle_empty_ack - sending finish event");
+            _event.data.event_type = MBED_CLIENT_NSDLINTERFACE_BS_FINISH_EVENT;
+            _event.data.event_data = coap_header->msg_id;
+            _event.data.data_ptr = _nsdl_handle;
+            _bootstrap_finish_ack_received = true;
+            eventOS_event_send_user_allocated(&_event);
+        }
+        else {
+            tr_debug("M2MNsdlInterface::handle_empty_ack - finish event already in progress");
+        }
+    } else {
+        // Notification delivered
+        M2MBase *base = find_resource("", coap_header->msg_id);
+        if (base && !base->report_handler()->blockwise_notify()) {
+            handle_notification_delivered(base);
+        }
+    }
+}
+
+void M2MNsdlInterface::handle_bootstrap_finish_ack(uint16_t msg_id)
+{
+    // EMPTY ACK for BS finished
+    tr_debug("M2MNsdlInterface::handle_bootstrap_finish_ack - id: %d", msg_id);
+    if (_bootstrap_id == msg_id) {
+        _observer.bootstrap_finish();
+        _bootstrap_id = 0;
+    } else {
+        tr_error("M2MNsdlInterface::handle_empty_ack - empty ACK id does not match to BS finished response id!");
+        char buffer[MAX_ALLOWED_ERROR_STRING_LENGTH];
+        const char *desc = "message id does not match";
+        snprintf(buffer, sizeof(buffer), ERROR_REASON_22, desc);
+        handle_bootstrap_error(buffer, false);
+    }
+}
+
+void M2MNsdlInterface::handle_notification_delivered(M2MBase *base)
+{
+    base->report_handler()->set_notification_send_in_progress(false);
+    _notification_send_ongoing = false;
+    base->send_notification_delivery_status(*base, NOTIFICATION_STATUS_DELIVERED);
+    _notification_handler->send_notification(this);
+
+    // Supported only in Resource level
+    // TODO! remove below code once old API is removed
+    if (M2MBase::Resource == base->base_type()) {
+        M2MResource *resource = static_cast<M2MResource *> (base);
+        resource->notification_sent();
+    }
+}
+
+bool M2MNsdlInterface::is_blockwise_needed(uint32_t length) const
+{
+    uint16_t block_size = sn_nsdl_get_block_size(_nsdl_handle);
+
+    if (length > block_size && block_size > 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+void M2MNsdlInterface::set_retransmission_parameters()
+{
+    // in UDP mode, reconnection attempts must be scaled down so that last attempt does not slip
+    // past the client lifetime.
+    uint64_t lifetime = registration_time();
+    uint32_t resend_count = MBED_CLIENT_RECONNECTION_COUNT;
+
+    uint32_t reconnection_total_time = total_retransmission_time(resend_count);
+    tr_debug("M2MNsdlInterface::set_retransmission_parameters() - total resend time %" PRIu32, reconnection_total_time);
+
+    while (resend_count > 1 && reconnection_total_time > lifetime) {
+        reconnection_total_time = total_retransmission_time(--resend_count);
+    }
+
+    tr_info("M2MNsdlInterface::set_retransmission_parameters() - setting max resend count to %" PRIu32 " with total time: %" PRIu32, resend_count, reconnection_total_time);
+    sn_nsdl_set_retransmission_parameters(_nsdl_handle, resend_count, MBED_CLIENT_RECONNECTION_INTERVAL);
+}
+
+uint32_t M2MNsdlInterface::total_retransmission_time(int resend_count)
+{
+    uint32_t reconnection_total_time = 1;
+
+    for (int i = 0; i <= resend_count; i++)
+        reconnection_total_time *= 2;
+
+    reconnection_total_time--;
+    reconnection_total_time *= MBED_CLIENT_RECONNECTION_INTERVAL;
+
+    // We need to take into account that CoAP specification mentions that each retransmission
+    // has to have a random multiplying factor between 1 - 1.5 , max of which can be 1.5
+    reconnection_total_time *= RESPONSE_RANDOM_FACTOR;
+
+    return reconnection_total_time;
+}
+
+bool M2MNsdlInterface::is_update_register_ongoing() const
+{
+    return _nsdl_handle->update_register_token == 0 ? false : true;
+}
+
+uint8_t M2MNsdlInterface::get_resend_count()
+{
+    return sn_nsdl_get_retransmission_count(_nsdl_handle);
+}
+
+void M2MNsdlInterface::send_pending_request()
+{
+    // ns_list_foreach() replacement since it does not compile with IAR 7.x versions.
+    request_context_s *data = (request_context_s *)ns_list_get_first(&_request_context_list);
+    while (data) {
+        if (data->resend && data->msg_code == COAP_MSG_CODE_REQUEST_GET) {
+            send_request(data->uri_path,
+                         data->msg_code,
+                         data->received_size,
+                         data->async_req,
+                         0,
+                         NULL,
+                         data->on_request_data_cb,
+                         data->on_request_error_cb,
+                         data->context);
+        }
+
+        data = (request_context_s *)ns_list_get_next(&_request_context_list, data);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mobject.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,566 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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 macro is needed on armcc to get the the PRI*32 macros
+// from inttypes.h in a C++ code.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+#include <inttypes.h>
+
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mendpoint.h"
+#include "mbed-client/m2mconstants.h"
+#include "include/m2mtlvserializer.h"
+#include "include/m2mtlvdeserializer.h"
+#include "include/m2mreporthandler.h"
+#include "mbed-trace/mbed_trace.h"
+#include "mbed-client/m2mstringbuffer.h"
+#include "include/m2mcallbackstorage.h"
+
+#include <stdlib.h>
+
+#define BUFFER_SIZE 10
+#define TRACE_GROUP "mClt"
+
+M2MObject::M2MObject(const String &object_name, char *path, bool external_blockwise_store)
+: M2MBase(object_name,
+          M2MBase::Dynamic,
+#ifndef DISABLE_RESOURCE_TYPE
+          "",
+#endif
+          path,
+          external_blockwise_store,
+          false),
+    _observation_handler(NULL)
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+    ,_endpoint(NULL)
+#endif
+{
+    M2MBase::set_base_type(M2MBase::Object);
+    M2MBase::set_operation(M2MBase::GET_ALLOWED);
+    if(M2MBase::name_id() != -1) {
+        M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
+    }
+}
+
+M2MObject::M2MObject(const M2MBase::lwm2m_parameters_s* static_res)
+: M2MBase(static_res),
+    _observation_handler(NULL)
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+    ,_endpoint(NULL)
+#endif
+{
+    M2MBase::set_operation(M2MBase::GET_ALLOWED);
+    if(M2MBase::name_id() != -1) {
+        M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
+    }
+}
+
+M2MObject::~M2MObject()
+{
+    if(!_instance_list.empty()) {
+
+        M2MObjectInstanceList::const_iterator it;
+        it = _instance_list.begin();
+        M2MObjectInstance* obj = NULL;
+        uint16_t index = 0;
+        for (; it!=_instance_list.end(); it++, index++ ) {
+            //Free allocated memory for object instances.
+            obj = *it;
+            delete obj;
+        }
+
+        _instance_list.clear();
+    }
+
+    free_resources();
+}
+
+M2MObjectInstance* M2MObject::create_object_instance(uint16_t instance_id)
+{
+    tr_debug("M2MObject::create_object_instance - id: %d", instance_id);
+    M2MObjectInstance *instance = NULL;
+    if(!object_instance(instance_id)) {
+        char* path = create_path(*this, instance_id);
+        if (path) {
+            // Note: the object instance's name contains actually object's name.
+            instance = new M2MObjectInstance(*this, "", path);
+            if(instance) {
+                instance->add_observation_level(observation_level());
+                instance->set_instance_id(instance_id);
+                if(M2MBase::name_id() != -1) {
+                    instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
+                }
+                _instance_list.push_back(instance);
+                set_changed();
+            }
+        }
+    }
+    return instance;
+}
+
+
+M2MObjectInstance* M2MObject::create_object_instance(const lwm2m_parameters_s* s)
+{
+    tr_debug("M2MObject::create_object_instance - id: %d", s->identifier.instance_id);
+    M2MObjectInstance *instance = NULL;
+    if(!object_instance(s->identifier.instance_id)) {
+
+        instance = new M2MObjectInstance(*this, s);
+        if(instance) {
+            instance->add_observation_level(observation_level());
+            //instance->set_instance_id(instance_id);
+            //if(M2MBase::name_id() != -1) {
+              //  instance->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
+            //}
+            _instance_list.push_back(instance);
+            set_changed();
+        }
+    }
+    return instance;
+}
+
+bool M2MObject::remove_object_instance(uint16_t inst_id)
+{
+    tr_debug("M2MObject::remove_object_instance(inst_id %d)", inst_id);
+    bool success = false;
+    if(!_instance_list.empty()) {
+        M2MObjectInstance* obj = NULL;
+        M2MObjectInstanceList::const_iterator it;
+        it = _instance_list.begin();
+        int pos = 0;
+        for ( ; it != _instance_list.end(); it++, pos++ ) {
+            if((*it)->instance_id() == inst_id) {
+                // Instance found and deleted.
+                obj = *it;
+
+                _instance_list.erase(pos);
+                delete obj;
+                success = true;
+                set_changed();
+                break;
+            }
+        }
+    }
+    return success;
+}
+
+M2MObjectInstance* M2MObject::object_instance(uint16_t inst_id) const
+{
+    tr_debug("M2MObject::object_instance(inst_id %d)", inst_id);
+    M2MObjectInstance *obj = NULL;
+    if(!_instance_list.empty()) {
+        M2MObjectInstanceList::const_iterator it;
+        it = _instance_list.begin();
+        for ( ; it != _instance_list.end(); it++ ) {
+            if((*it)->instance_id() == inst_id) {
+                // Instance found.
+                obj = *it;
+                break;
+            }
+        }
+    }
+    return obj;
+}
+
+const M2MObjectInstanceList& M2MObject::instances() const
+{
+    return _instance_list;
+}
+
+uint16_t M2MObject::instance_count() const
+{
+    return (uint16_t)_instance_list.size();
+}
+
+M2MObservationHandler* M2MObject::observation_handler() const
+{
+    // XXX: need to check the flag too
+    return _observation_handler;
+}
+
+void M2MObject::set_observation_handler(M2MObservationHandler *handler)
+{
+    tr_debug("M2MObject::set_observation_handler - handler: 0x%p", (void*)handler);
+    _observation_handler = handler;
+}
+
+void M2MObject::add_observation_level(M2MBase::Observation observation_level)
+{
+    M2MBase::add_observation_level(observation_level);
+    if(!_instance_list.empty()) {
+         M2MObjectInstanceList::const_iterator it;
+         it = _instance_list.begin();
+         for ( ; it != _instance_list.end(); it++ ) {
+             (*it)->add_observation_level(observation_level);
+         }
+    }
+}
+
+void M2MObject::remove_observation_level(M2MBase::Observation observation_level)
+{
+    M2MBase::remove_observation_level(observation_level);
+    if(!_instance_list.empty()) {
+        M2MObjectInstanceList::const_iterator it;
+        it = _instance_list.begin();
+        for ( ; it != _instance_list.end(); it++ ) {
+            (*it)->remove_observation_level(observation_level);
+        }
+    }
+}
+
+sn_coap_hdr_s* M2MObject::handle_get_request(nsdl_s *nsdl,
+                                             sn_coap_hdr_s *received_coap_header,
+                                             M2MObservationHandler *observation_handler)
+{
+    tr_info("M2MObject::handle_get_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
+    sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
+                                                           received_coap_header,
+                                                           msg_code);
+    uint8_t *data = NULL;
+    uint32_t data_length = 0;
+    if(received_coap_header) {
+        // process the GET if we have registered a callback for it
+        if ((operation() & SN_GRS_GET_ALLOWED) != 0) {
+            if(coap_response) {
+                bool content_type_present = false;
+                bool is_content_type_supported = true;
+
+                if (received_coap_header->options_list_ptr &&
+                        received_coap_header->options_list_ptr->accept != COAP_CT_NONE) {
+                    content_type_present = true;
+                    coap_response->content_format = received_coap_header->options_list_ptr->accept;
+
+                }
+
+                // Check if preferred content type is supported
+                if (content_type_present) {
+                    if (coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE_OLD &&
+                        coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE) {
+                        is_content_type_supported = false;
+                    }
+                }
+
+                if (is_content_type_supported) {
+                    if(!content_type_present &&
+                       (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
+                        M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
+                        coap_response->content_format = sn_coap_content_format_e(M2MBase::coap_content_type());
+                    }
+
+                    // fill in the CoAP response payload
+                    if(COAP_CONTENT_OMA_TLV_TYPE == coap_response->content_format ||
+                       COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_response->content_format) {
+                        set_coap_content_type(coap_response->content_format);
+                        data = M2MTLVSerializer::serialize(_instance_list, data_length);
+                    }
+
+                    coap_response->payload_len = data_length;
+                    coap_response->payload_ptr = data;
+                    if(data){
+                        coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
+                        if(coap_response->options_list_ptr){
+                            coap_response->options_list_ptr->max_age = max_age();
+                        }
+                        if(received_coap_header->options_list_ptr) {
+                            if(received_coap_header->options_list_ptr->observe != -1) {
+                                if (is_observable()) {
+                                    uint32_t number = 0;
+                                    uint8_t observe_option = 0;
+                                    observe_option = received_coap_header->options_list_ptr->observe;
+
+                                    if(START_OBSERVATION == observe_option) {
+                                        // If the observe length is 0 means register for observation.
+                                        if(received_coap_header->options_list_ptr->observe != -1) {
+                                            number = received_coap_header->options_list_ptr->observe;
+                                        }
+
+                                        // If the observe value is 0 means register for observation.
+                                        if(number == 0) {
+                                            tr_info("M2MObject::handle_get_request - put resource under observation");
+                                            set_under_observation(true,observation_handler);
+                                            add_observation_level(M2MBase::O_Attribute);
+                                            send_notification_delivery_status(*this, NOTIFICATION_STATUS_SUBSCRIBED);
+                                            if(coap_response->options_list_ptr){
+                                                coap_response->options_list_ptr->observe = observation_number();
+                                            }
+                                        }
+
+                                        if(received_coap_header->token_ptr) {
+                                            set_observation_token(received_coap_header->token_ptr,
+                                                                  received_coap_header->token_len);
+                                        }
+                                    } else if (STOP_OBSERVATION == observe_option) {
+                                        tr_info("M2MObject::handle_get_request - stops observation");
+                                        // If the observe options_list_ptr->observe value is 1 means de-register from observation.
+                                        set_under_observation(false, NULL);
+                                        remove_observation_level(M2MBase::O_Attribute);
+                                        send_notification_delivery_status(*this, NOTIFICATION_STATUS_UNSUBSCRIBED);
+                                    }
+                                    msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
+                                }
+                                else {
+                                    msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+                                }
+                            }
+                        }
+                    } else {
+                        msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; // Content format not supported
+                    }
+                } else {
+                    tr_error("M2MObject::handle_get_request() - Content-Type %d not supported", coap_response->content_format);
+                    msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE;
+                }
+            }
+        }else {
+            tr_error("M2MResource::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
+            // Operation is not allowed.
+            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+        }
+    } else {
+        msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+    }
+    if(coap_response) {
+        coap_response->msg_code = msg_code;
+    }
+    return coap_response;
+}
+
+sn_coap_hdr_s* M2MObject::handle_put_request(nsdl_s *nsdl,
+                                             sn_coap_hdr_s *received_coap_header,
+                                             M2MObservationHandler */*observation_handler*/,
+                                             bool &/*execute_value_updated*/)
+{
+    tr_info("M2MObject::handle_put_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
+    sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl,
+                                                          received_coap_header,
+                                                          msg_code);
+    if(received_coap_header) {
+        if(received_coap_header->content_format != COAP_CT_NONE) {
+            set_coap_content_type(received_coap_header->content_format);
+        }
+        if(received_coap_header->options_list_ptr &&
+           received_coap_header->options_list_ptr->uri_query_ptr) {
+            char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr,
+                                                    received_coap_header->options_list_ptr->uri_query_len);
+
+            if (query){
+                tr_info("M2MObject::handle_put_request() - query %s", query);
+                // if anything was updated, re-initialize the stored notification attributes
+                if (!handle_observation_attribute(query)){
+                    tr_debug("M2MObject::handle_put_request() - Invalid query");
+                    msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00
+                }
+                free(query);
+            }
+        } else {
+            tr_error("M2MObject::handle_put_request() - COAP_MSG_CODE_RESPONSE_BAD_REQUEST - Empty URI_QUERY");
+            msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+        }
+    } else {
+        msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+    }
+    if(coap_response) {
+        coap_response->msg_code = msg_code;
+    }
+    return coap_response;
+}
+
+
+sn_coap_hdr_s* M2MObject::handle_post_request(nsdl_s *nsdl,
+                                              sn_coap_hdr_s *received_coap_header,
+                                              M2MObservationHandler *observation_handler,
+                                              bool &execute_value_updated,
+                                              sn_nsdl_addr_s *)
+{
+    tr_info("M2MObject::handle_post_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
+    // process the POST if we have registered a callback for it
+    sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl,
+                                      received_coap_header,
+                                      msg_code);
+
+    if (received_coap_header) {
+        if ((operation() & SN_GRS_POST_ALLOWED) != 0) {
+            if (received_coap_header->content_format != COAP_CT_NONE) {
+                set_coap_content_type(received_coap_header->content_format);
+            }
+            if(received_coap_header->payload_ptr) {
+                tr_debug("M2MObject::handle_post_request() - Update Object with new values");
+                uint16_t coap_content_type = 0;
+                bool content_type_present = false;
+                if(received_coap_header->content_format != COAP_CT_NONE) {
+                    content_type_present = true;
+                    if(coap_response) {
+                        coap_content_type = received_coap_header->content_format;
+                    }
+                } // if(received_coap_header->content_format)
+                if(!content_type_present &&
+                   (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
+                    M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
+                    coap_content_type = M2MBase::coap_content_type();
+                }
+
+                tr_debug("M2MObject::handle_post_request() - Request Content-type: %d", coap_content_type);
+
+                if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type ||
+                   COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type) {
+                    set_coap_content_type(coap_content_type);
+                    uint32_t instance_id = 0;
+                    // Check next free instance id
+                    for(instance_id = 0; instance_id <= MAX_UNINT_16_COUNT; instance_id++) {
+                        if(NULL == object_instance(instance_id)) {
+                            break;
+                        }
+                        if(instance_id == MAX_UNINT_16_COUNT) {
+                            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+                            break;
+                        }
+                    }
+                    if(COAP_MSG_CODE_RESPONSE_CHANGED == msg_code) {
+                        bool is_obj_instance = false;
+                        bool obj_instance_exists = false;
+                        is_obj_instance = M2MTLVDeserializer::is_object_instance(received_coap_header->payload_ptr);
+                        if (is_obj_instance) {
+                            instance_id = M2MTLVDeserializer::instance_id(received_coap_header->payload_ptr);
+                            tr_debug("M2MObject::handle_post_request() - instance id in TLV: %" PRIu32, instance_id);
+                            // Check if instance id already exists
+                            if (object_instance(instance_id)){
+                                obj_instance_exists = true;
+                            }
+                        }
+                        if (!obj_instance_exists && coap_response) {
+                            M2MObjectInstance *obj_instance = create_object_instance(instance_id);
+                            if (obj_instance) {
+                                obj_instance->set_operation(M2MBase::GET_PUT_ALLOWED);
+                            }
+
+                            M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
+                            if(is_obj_instance) {
+                                tr_debug("M2MObject::handle_post_request() - TLV data contains ObjectInstance");
+                                error = M2MTLVDeserializer::deserialise_object_instances(received_coap_header->payload_ptr,
+                                                                           received_coap_header->payload_len,
+                                                                           *this,
+                                                                           M2MTLVDeserializer::Post);
+                            } else if(obj_instance &&
+                                        (M2MTLVDeserializer::is_resource(received_coap_header->payload_ptr) ||
+                                         M2MTLVDeserializer::is_multiple_resource(received_coap_header->payload_ptr))) {
+                                tr_debug("M2MObject::handle_post_request() - TLV data contains Resources");
+                                error = M2MTLVDeserializer::deserialize_resources(received_coap_header->payload_ptr,
+                                                                            received_coap_header->payload_len,
+                                                                            *obj_instance,
+                                                                            M2MTLVDeserializer::Post);
+                            } else {
+                                error = M2MTLVDeserializer::NotValid;
+                            }
+                            switch(error) {
+                                case M2MTLVDeserializer::None:
+                                    if(observation_handler) {
+                                        execute_value_updated = true;
+                                    }
+                                    coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
+
+                                    if (coap_response->options_list_ptr) {
+
+                                        StringBuffer<MAX_OBJECT_PATH_NAME> obj_name;
+
+                                        if (obj_name.ensure_space(M2MBase::resource_name_length() + (1 + 5 + 1))) {
+                                            obj_name.append(M2MBase::name());
+                                            obj_name.append('/');
+                                            obj_name.append_int(instance_id);
+
+                                            coap_response->options_list_ptr->location_path_len = obj_name.get_size();
+                                            coap_response->options_list_ptr->location_path_ptr =
+                                                    alloc_copy((uint8_t*)obj_name.c_str(), obj_name.get_size());
+                                            // todo: else return error
+                                        }
+                                    }
+                                    // todo: else return error
+                                    msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
+                                    break;
+                                case M2MTLVDeserializer::NotAllowed:
+                                    msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+                                    break;
+                                case M2MTLVDeserializer::NotValid:
+                                    msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+                                    break;
+                                case M2MTLVDeserializer::NotFound:
+                                    msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
+                                    break;
+                                case M2MTLVDeserializer::OutOfMemory:
+                                    msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
+                                    break;
+                            }
+
+                        } else {
+                            tr_error("M2MObject::handle_post_request() - COAP_MSG_CODE_RESPONSE_BAD_REQUEST");
+                            msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+                        }
+                    }
+                } else {
+                    msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
+                } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type)
+            } else {
+                tr_error("M2MObject::handle_post_request - COAP_MSG_CODE_RESPONSE_BAD_REQUEST - Missing Payload");
+                msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; //
+            }
+        } else { // if ((object->operation() & SN_GRS_POST_ALLOWED) != 0)
+            tr_error("M2MObject::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
+            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.05
+        }
+    } else { //if(received_coap_header)
+        tr_error("M2MObject::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
+        msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.05
+    }
+
+    if(coap_response) {
+        coap_response->msg_code = msg_code;
+    }
+    return coap_response;
+}
+
+void M2MObject::notification_update(uint16_t obj_instance_id)
+{
+    tr_debug("M2MObject::notification_update - id: %d", obj_instance_id);
+    M2MReportHandler *report_handler = M2MBase::report_handler();
+    if(report_handler && is_under_observation()) {
+        report_handler->set_notification_trigger(obj_instance_id);
+    }
+}
+
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+void M2MObject::set_endpoint(M2MEndpoint *endpoint)
+{
+    _endpoint = endpoint;
+}
+
+M2MEndpoint* M2MObject::get_endpoint() const
+{
+    return _endpoint;
+}
+#endif
+
+M2MBase *M2MObject::get_parent() const
+{
+#ifdef MBED_CLOUD_CLIENT_EDGE_EXTENSION
+    return (M2MBase *) get_endpoint();
+#else
+    return NULL;
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mobjectinstance.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,796 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "mbed-client/m2mobjectinstance.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2mresource.h"
+#include "mbed-client/m2mresource.h"
+#include "mbed-client/m2mobservationhandler.h"
+#include "mbed-client/m2mstring.h"
+#include "mbed-client/m2mstringbuffer.h"
+#include "include/m2mtlvserializer.h"
+#include "include/m2mtlvdeserializer.h"
+#include "include/m2mreporthandler.h"
+#include "mbed-trace/mbed_trace.h"
+#include "include/m2mcallbackstorage.h"
+#include <stdlib.h>
+
+#define BUFFER_SIZE 10
+#define TRACE_GROUP "mClt"
+
+M2MObjectInstance::M2MObjectInstance(M2MObject& parent,
+                                     const String &resource_type,
+                                     char *path,
+                                     bool external_blockwise_store)
+: M2MBase("",
+          M2MBase::Dynamic,
+#ifndef DISABLE_RESOURCE_TYPE
+          resource_type,
+#endif
+          path,
+          external_blockwise_store,
+          false),
+  _parent(parent)
+{
+    M2MBase::set_base_type(M2MBase::ObjectInstance);
+    M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
+    M2MBase::set_operation(M2MBase::GET_ALLOWED);
+}
+
+M2MObjectInstance::M2MObjectInstance(M2MObject& parent, const lwm2m_parameters_s* static_res)
+: M2MBase(static_res), _parent(parent)
+{
+    M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
+    M2MBase::set_operation(M2MBase::GET_ALLOWED);
+}
+
+M2MObjectInstance::~M2MObjectInstance()
+{
+    if(!_resource_list.empty()) {
+        M2MResource* res = NULL;
+        M2MResourceList::const_iterator it;
+        it = _resource_list.begin();
+        for (; it!=_resource_list.end(); it++ ) {
+            //Free allocated memory for resources.
+            res = *it;
+            delete res;
+        }
+        _resource_list.clear();
+    }
+
+    free_resources();
+}
+
+// TBD, ResourceType to the base class struct?? TODO!
+M2MResource* M2MObjectInstance::create_static_resource(const lwm2m_parameters_s* static_res,
+                                                       M2MResourceInstance::ResourceType type)
+{
+    tr_debug("M2MObjectInstance::create_static_resource(lwm2m_parameters_s resource_name %s)", static_res->identifier.name);
+    M2MResource *res = NULL;
+    if (validate_string_length(static_res->identifier.name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
+        return res;
+    }
+    if(!resource(static_res->identifier.name)) {
+        res = new M2MResource(*this, static_res, convert_resource_type(type));
+        if(res) {
+            res->add_observation_level(observation_level());
+            //if (multiple_instance) {
+                //res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
+            //}
+            _resource_list.push_back(res);
+            set_changed();
+        }
+    }
+    return res;
+}
+
+M2MResource* M2MObjectInstance::create_static_resource(const String &resource_name,
+                                                       const String &resource_type,
+                                                       M2MResourceInstance::ResourceType type,
+                                                       const uint8_t *value,
+                                                       const uint8_t value_length,
+                                                       bool multiple_instance,
+                                                       bool external_blockwise_store)
+{
+    tr_debug("M2MObjectInstance::create_static_resource(resource_name %s)",resource_name.c_str());
+    M2MResource *res = NULL;
+    if (validate_string_length(resource_name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
+        return res;
+    }
+    if(!resource(resource_name)) {
+        char *path = create_path(*this, resource_name.c_str());
+
+        if (path) {
+            res = new M2MResource(*this, resource_name, M2MBase::Static, resource_type, convert_resource_type(type),
+                                  value, value_length, path,
+                                  multiple_instance, external_blockwise_store);
+            if(res) {
+                res->add_observation_level(observation_level());
+                if (multiple_instance) {
+                    res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
+                }
+                _resource_list.push_back(res);
+                set_changed();
+            }
+        }
+    }
+    return res;
+}
+
+M2MResource* M2MObjectInstance::create_dynamic_resource(const lwm2m_parameters_s* static_res,
+                                                        M2MResourceInstance::ResourceType type,
+                                                        bool observable)
+{
+    tr_debug("M2MObjectInstance::create_dynamic_resource(resource_name %s)", static_res->identifier.name);
+    M2MResource *res = NULL;
+
+    if (validate_string_length(static_res->identifier.name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
+        return res;
+    }
+    if(!resource(static_res->identifier.name)) {
+        res = new M2MResource(*this, static_res, convert_resource_type(type));
+        if(res) {
+            //if (multiple_instance) { // TODO!
+              //  res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE);
+            //}
+            res->add_observation_level(observation_level());
+            _resource_list.push_back(res);
+            set_changed();
+        }
+    }
+    return res;
+}
+
+M2MResource* M2MObjectInstance::create_dynamic_resource(const String &resource_name,
+                                                const String &resource_type,
+                                                M2MResourceInstance::ResourceType type,
+                                                bool observable,
+                                                bool multiple_instance,
+                                                bool external_blockwise_store)
+{
+    tr_debug("M2MObjectInstance::create_dynamic_resource(resource_name %s)",resource_name.c_str());
+    M2MResource *res = NULL;
+    if (validate_string_length(resource_name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
+        return res;
+    }
+    if(!resource(resource_name)) {
+        char *path = create_path(*this, resource_name.c_str());
+        if (path) {
+            res = new M2MResource(*this, resource_name, M2MBase::Dynamic, resource_type, convert_resource_type(type),
+                                  observable, path,
+                                  multiple_instance, external_blockwise_store);
+            if(res) {
+                if (multiple_instance) {
+                    res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
+                }
+                res->add_observation_level(observation_level());
+                _resource_list.push_back(res);
+                set_changed();
+            }
+        }
+    }
+    return res;
+}
+
+M2MResourceInstance* M2MObjectInstance::create_static_resource_instance(const String &resource_name,
+                                                                        const String &resource_type,
+                                                                        M2MResourceInstance::ResourceType type,
+                                                                        const uint8_t *value,
+                                                                        const uint8_t value_length,
+                                                                        uint16_t instance_id,
+                                                                        bool external_blockwise_store)
+{
+    tr_debug("M2MObjectInstance::create_static_resource_instance(resource_name %s)",resource_name.c_str());
+    M2MResourceInstance *instance = NULL;
+    if (validate_string_length(resource_name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
+
+        return instance;
+    }
+    M2MResource *res = resource(resource_name);
+    if(!res) {
+        char *path = create_path(*this, resource_name.c_str());
+        if (path) {
+            res = new M2MResource(*this, resource_name, M2MBase::Static, resource_type, convert_resource_type(type),
+                                  value, value_length, path,
+                                  true, external_blockwise_store);
+            _resource_list.push_back(res);
+            set_changed();
+            res->set_operation(M2MBase::GET_ALLOWED);
+            res->set_observable(false);
+            res->set_register_uri(false);
+        }
+    }
+    if(res && res->supports_multiple_instances()&& (res->resource_instance(instance_id) == NULL)) {
+        char *path = M2MBase::create_path(*res, instance_id);
+        if (path) {
+            instance = new M2MResourceInstance(*res, "", M2MBase::Static, resource_type, convert_resource_type(type),
+                                               value, value_length,
+                                               path, external_blockwise_store,true);
+            if(instance) {
+                instance->set_operation(M2MBase::GET_ALLOWED);
+                instance->set_instance_id(instance_id);
+                res->add_resource_instance(instance);
+            }
+        }
+    }
+    return instance;
+}
+
+M2MResourceInstance* M2MObjectInstance::create_dynamic_resource_instance(const String &resource_name,
+                                                                         const String &resource_type,
+                                                                         M2MResourceInstance::ResourceType type,
+                                                                         bool observable,
+                                                                         uint16_t instance_id,
+                                                                         bool external_blockwise_store)
+{
+    tr_debug("M2MObjectInstance::create_dynamic_resource_instance(resource_name %s)",resource_name.c_str());
+    M2MResourceInstance *instance = NULL;
+    if (validate_string_length(resource_name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
+        return instance;
+    }
+    M2MResource *res = resource(resource_name);
+    if(!res) {
+        char *path = create_path(*this, resource_name.c_str());
+        if (path) {
+            res = new M2MResource(*this, resource_name, M2MBase::Dynamic, resource_type, convert_resource_type(type),
+                                  false, path, true, external_blockwise_store);
+            _resource_list.push_back(res);
+            res->set_register_uri(false);
+            res->set_operation(M2MBase::GET_ALLOWED);
+        }
+    }
+    if (res && res->supports_multiple_instances() && (res->resource_instance(instance_id) == NULL)) {
+        char *path = create_path(*res, instance_id);
+        if (path) {
+            instance = new M2MResourceInstance(*res, "", M2MBase::Dynamic, resource_type, convert_resource_type(type),
+                                               path, external_blockwise_store,true);
+            if(instance) {
+                instance->set_operation(M2MBase::GET_ALLOWED);
+                instance->set_observable(observable);
+                instance->set_instance_id(instance_id);
+                res->add_resource_instance(instance);
+                set_changed();
+            }
+        }
+    }
+    return instance;
+}
+
+bool M2MObjectInstance::remove_resource(const String &resource_name)
+{
+    return remove_resource(resource_name.c_str());
+}
+
+bool M2MObjectInstance::remove_resource(const char *resource_name)
+{
+    tr_debug("M2MObjectInstance::remove_resource(resource_name %s)", resource_name);
+
+    bool success = false;
+    if(!_resource_list.empty()) {
+         M2MResource* res = NULL;
+         M2MResourceList::const_iterator it;
+         it = _resource_list.begin();
+         int pos = 0;
+         for ( ; it != _resource_list.end(); it++, pos++ ) {
+             if(strcmp((*it)->name(), resource_name) == 0) {
+                // Resource found and deleted.
+                res = *it;
+                delete res;
+                _resource_list.erase(pos);
+                set_changed();
+                success = true;
+                break;
+             }
+         }
+    }
+    return success;
+}
+
+bool M2MObjectInstance::remove_resource_instance(const String &resource_name,
+                                                 uint16_t inst_id)
+{
+    tr_debug("M2MObjectInstance::remove_resource_instance(resource_name %s inst_id %d)",
+             resource_name.c_str(), inst_id);
+    bool success = false;
+    M2MResource *res = resource(resource_name);
+    if(res) {
+        const M2MResourceInstanceList &list = res->resource_instances();
+        M2MResourceInstanceList::const_iterator it;
+        it = list.begin();
+        for ( ; it != list.end(); it++) {
+            if((*it)->instance_id() == inst_id) {
+                success = res->remove_resource_instance(inst_id);
+                if(res->resource_instance_count() == 0) {
+                    M2MResourceList::const_iterator itr;
+                    itr = _resource_list.begin();
+                    int pos = 0;
+                    for ( ; itr != _resource_list.end(); itr++, pos++ ) {
+                        if(strcmp((*itr)->name(),resource_name.c_str()) == 0) {
+                            delete res;
+                            _resource_list.erase(pos);
+                            set_changed();
+                            break;
+                        }
+                    }
+                }
+                break;
+            }
+        }
+    }
+    return success;
+}
+
+M2MResource* M2MObjectInstance::resource(const String &resource_name) const
+{
+    return resource(resource_name.c_str());
+}
+
+M2MResource* M2MObjectInstance::resource(const char *resource_name) const
+{
+    M2MResource *res = NULL;
+    if(!_resource_list.empty()) {
+        M2MResourceList::const_iterator it;
+        it = _resource_list.begin();
+        for (; it!=_resource_list.end(); it++ ) {
+            if(strcmp((*it)->name(), resource_name) == 0) {
+                res = *it;
+                break;
+            }
+        }
+    }
+    return res;
+}
+
+const M2MResourceList& M2MObjectInstance::resources() const
+{
+    return _resource_list;
+}
+
+uint16_t M2MObjectInstance::resource_count() const
+{
+    uint16_t count = 0;
+    if(!_resource_list.empty()) {
+        M2MResourceList::const_iterator it;
+        it = _resource_list.begin();
+        for ( ; it != _resource_list.end(); it++ ) {
+            if((*it)->supports_multiple_instances()) {
+                count += (*it)->resource_instance_count();
+            } else {
+                count++;
+            }
+        }
+    }
+    return count;
+}
+
+uint16_t M2MObjectInstance::resource_count(const String& resource) const
+{
+
+    return resource_count(resource.c_str());
+}
+
+uint16_t M2MObjectInstance::resource_count(const char *resource) const
+{
+    uint16_t count = 0;
+    if(!_resource_list.empty()) {
+        M2MResourceList::const_iterator it;
+        it = _resource_list.begin();
+        for ( ; it != _resource_list.end(); it++ ) {
+            if(strcmp((*it)->name(), resource) == 0) {
+                if((*it)->supports_multiple_instances()) {
+                    count += (*it)->resource_instance_count();
+                } else {
+                    count++;
+                }
+            }
+        }
+    }
+    return count;
+}
+
+M2MObservationHandler* M2MObjectInstance::observation_handler() const
+{
+    // XXX: need to check the flag too
+    return _parent.observation_handler();
+}
+
+void M2MObjectInstance::set_observation_handler(M2MObservationHandler *handler)
+{
+    // XXX: need to set the flag too
+    _parent.set_observation_handler(handler);
+}
+
+void M2MObjectInstance::add_observation_level(M2MBase::Observation observation_level)
+{
+    M2MBase::add_observation_level(observation_level);
+    if(!_resource_list.empty()) {
+        M2MResourceList::const_iterator it;
+        it = _resource_list.begin();
+        for ( ; it != _resource_list.end(); it++ ) {
+            (*it)->add_observation_level(observation_level);
+        }
+    }
+}
+
+void M2MObjectInstance::remove_observation_level(M2MBase::Observation observation_level)
+{
+    M2MBase::remove_observation_level(observation_level);
+    if(!_resource_list.empty()) {
+        M2MResourceList::const_iterator it;
+        it = _resource_list.begin();
+        for ( ; it != _resource_list.end(); it++ ) {
+           (*it)->remove_observation_level(observation_level);
+        }
+    }
+}
+
+sn_coap_hdr_s* M2MObjectInstance::handle_get_request(nsdl_s *nsdl,
+                                                     sn_coap_hdr_s *received_coap_header,
+                                                     M2MObservationHandler *observation_handler)
+{
+    tr_info("M2MObjectInstance::handle_get_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
+    sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
+                                                           received_coap_header,
+                                                           msg_code);
+    uint8_t * data = NULL;
+    uint32_t  data_length = 0;
+
+    if (received_coap_header) {
+        // process the GET if we have registered a callback for it
+        if ((operation() & SN_GRS_GET_ALLOWED) != 0) {
+            if (coap_response) {
+                bool content_type_present = false;
+                bool is_content_type_supported = true;
+
+                if (received_coap_header->options_list_ptr &&
+                        received_coap_header->options_list_ptr->accept != COAP_CT_NONE) {
+                    content_type_present = true;
+                    coap_response->content_format = received_coap_header->options_list_ptr->accept;
+
+                }
+
+                // Check if preferred content type is supported
+                if (content_type_present) {
+                    if (coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE_OLD &&
+                        coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE) {
+                        is_content_type_supported = false;
+                    }
+                }
+
+                if (is_content_type_supported) {
+                    if (!content_type_present &&
+                       (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
+                        M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
+                        coap_response->content_format = sn_coap_content_format_e(M2MBase::coap_content_type());
+                    }
+
+                    // fill in the CoAP response payload
+                    if (COAP_CONTENT_OMA_TLV_TYPE == coap_response->content_format  ||
+                        COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_response->content_format) {
+                        set_coap_content_type(coap_response->content_format);
+                        data = M2MTLVSerializer::serialize(_resource_list, data_length);
+                    }
+
+                    coap_response->payload_len = data_length;
+                    coap_response->payload_ptr = data;
+
+                    if (data) {
+                        coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
+                        if (coap_response->options_list_ptr) {
+                            coap_response->options_list_ptr->max_age = max_age();
+                        }
+
+                        if (received_coap_header->options_list_ptr) {
+                            if (received_coap_header->options_list_ptr->observe != -1) {
+                                if (is_observable()) {
+                                    uint32_t number = 0;
+                                    uint8_t observe_option = 0;
+                                    observe_option = received_coap_header->options_list_ptr->observe;
+                                    if (START_OBSERVATION == observe_option) {
+                                        // If the observe length is 0 means register for observation.
+                                        if (received_coap_header->options_list_ptr->observe != -1) {
+                                            number = received_coap_header->options_list_ptr->observe;
+                                        }
+
+                                        // If the observe value is 0 means register for observation.
+                                        if (number == 0) {
+                                            tr_info("M2MObjectInstance::handle_get_request - put resource under observation");
+                                            set_under_observation(true,observation_handler);
+                                            add_observation_level(M2MBase::OI_Attribute);
+                                            send_notification_delivery_status(*this, NOTIFICATION_STATUS_SUBSCRIBED);
+                                            if (coap_response->options_list_ptr) {
+                                                coap_response->options_list_ptr->observe = observation_number();
+                                            }
+                                        }
+
+                                        if (received_coap_header->token_ptr) {
+                                            set_observation_token(received_coap_header->token_ptr,
+                                                                  received_coap_header->token_len);
+                                        }
+
+                                    } else if (STOP_OBSERVATION == observe_option) {
+                                        tr_info("M2MObjectInstance::handle_get_request - stops observation");
+                                        set_under_observation(false,NULL);
+                                        remove_observation_level(M2MBase::OI_Attribute);
+                                        send_notification_delivery_status(*this, NOTIFICATION_STATUS_UNSUBSCRIBED);
+                                    }
+                                    msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
+                                }
+                                else {
+                                    msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+                                }
+                            }
+                        }
+                    } else {
+                        msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; // Content format not supported
+                    }
+                } else {
+                    tr_error("M2MObjectInstance::handle_get_request() - Content-type: %d not supported", coap_response->content_format);
+                    msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE;
+                }
+            }
+        } else {
+            tr_error("M2MObjectInstance::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
+            // Operation is not allowed.
+            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+        }
+    } else {
+        msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+    }
+    if(coap_response) {
+        coap_response->msg_code = msg_code;
+    }
+    return coap_response;
+}
+
+sn_coap_hdr_s* M2MObjectInstance::handle_put_request(nsdl_s *nsdl,
+                                                     sn_coap_hdr_s *received_coap_header,
+                                                     M2MObservationHandler *observation_handler,
+                                                     bool &/*execute_value_updated*/)
+{
+    tr_info("M2MObjectInstance::handle_put_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
+    sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
+                                                           received_coap_header,
+                                                           msg_code);;
+    if(received_coap_header) {
+        uint16_t coap_content_type = 0;
+        bool content_type_present = false;
+
+        if(received_coap_header->content_format != COAP_CT_NONE) {
+            content_type_present = true;
+            set_coap_content_type(received_coap_header->content_format);
+            if(coap_response) {
+                coap_content_type = received_coap_header->content_format;
+            }
+        }
+        if(received_coap_header->options_list_ptr &&
+           received_coap_header->options_list_ptr->uri_query_ptr) {
+            char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr,
+                                                    received_coap_header->options_list_ptr->uri_query_len);
+            if (query){
+                tr_info("M2MObjectInstance::handle_put_request() - query %s", query);
+                // if anything was updated, re-initialize the stored notification attributes
+                if (!handle_observation_attribute(query)){
+                    tr_debug("M2MObjectInstance::handle_put_request() - Invalid query");
+                    msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00
+                } else {
+                    msg_code =COAP_MSG_CODE_RESPONSE_CHANGED;
+                }
+                free(query);
+            }
+        } else if ((operation() & SN_GRS_PUT_ALLOWED) != 0) {
+            if(!content_type_present &&
+               (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
+                M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
+                coap_content_type = M2MBase::coap_content_type();
+            }
+
+            tr_debug("M2MObjectInstance::handle_put_request() - Request Content-type: %d", coap_content_type);
+
+            if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type ||
+               COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type ) {
+                set_coap_content_type(coap_content_type);
+                M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
+                if(received_coap_header->payload_ptr) {
+                    error = M2MTLVDeserializer::deserialize_resources(
+                                received_coap_header->payload_ptr,
+                                received_coap_header->payload_len, *this,
+                                M2MTLVDeserializer::Put);
+                    switch(error) {
+                        case M2MTLVDeserializer::None:
+                            if(observation_handler) {
+                                observation_handler->value_updated(this);
+                            }
+                            msg_code = COAP_MSG_CODE_RESPONSE_CHANGED;
+                            break;
+                        case M2MTLVDeserializer::NotFound:
+                            msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
+                            break;
+                        case M2MTLVDeserializer::NotAllowed:
+                            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+                            break;
+                        case M2MTLVDeserializer::NotValid:
+                            msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+                            break;
+                        case M2MTLVDeserializer::OutOfMemory:
+                            msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
+                            break;
+                    }
+                }
+            } else {
+                msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
+            } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type)
+        } else {
+            // Operation is not allowed.
+            tr_error("M2MObjectInstance::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
+            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+        }
+    } else {
+       msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+    }
+    if(coap_response) {
+        coap_response->msg_code = msg_code;
+    }
+    return coap_response;
+}
+
+sn_coap_hdr_s* M2MObjectInstance::handle_post_request(nsdl_s *nsdl,
+                                                      sn_coap_hdr_s *received_coap_header,
+                                                      M2MObservationHandler *observation_handler,
+                                                      bool &execute_value_updated,
+                                                      sn_nsdl_addr_s *)
+{
+    tr_info("M2MObjectInstance::handle_post_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
+    sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
+                                                           received_coap_header,
+                                                           msg_code);
+    if(received_coap_header) {
+        if ((operation() & SN_GRS_POST_ALLOWED) != 0) {
+            uint16_t coap_content_type = 0;
+            bool content_type_present = false;
+            if(received_coap_header->content_format != COAP_CT_NONE) {
+                set_coap_content_type(received_coap_header->content_format);
+                content_type_present = true;
+                if(coap_response) {
+                    coap_content_type = received_coap_header->content_format;
+                }
+            }
+            if(!content_type_present &&
+               (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
+                M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
+                coap_content_type = M2MBase::coap_content_type();
+            }
+
+            tr_debug("M2MObjectInstance::handle_post_request() - Request Content-type: %d", coap_content_type);
+
+            if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type ||
+               COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type) {
+                set_coap_content_type(coap_content_type);
+                M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
+                error = M2MTLVDeserializer::deserialize_resources(
+                            received_coap_header->payload_ptr,
+                            received_coap_header->payload_len, *this,
+                            M2MTLVDeserializer::Post);
+
+                uint16_t instance_id = M2MTLVDeserializer::instance_id(received_coap_header->payload_ptr);
+                switch(error) {
+                    case M2MTLVDeserializer::None:
+                        if(observation_handler) {
+                            execute_value_updated = true;
+                        }
+                        coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
+
+                        if (coap_response->options_list_ptr) {
+
+                            StringBuffer<MAX_PATH_SIZE_3> obj_name;
+                            if(!build_path(obj_name, _parent.name(), M2MBase::instance_id(), instance_id)) {
+                                msg_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
+                                break;
+                            }
+
+                            coap_response->options_list_ptr->location_path_len = obj_name.get_size();
+                            coap_response->options_list_ptr->location_path_ptr =
+                              alloc_string_copy((uint8_t*)obj_name.c_str(),
+                                                coap_response->options_list_ptr->location_path_len);
+                            // todo: handle allocation error
+                        }
+                        msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
+                        break;
+                    case M2MTLVDeserializer::NotAllowed:
+                        msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+                        break;
+                    case M2MTLVDeserializer::NotValid:
+                        msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+                        break;
+                    case M2MTLVDeserializer::NotFound:
+                        msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
+                        break;
+                    case M2MTLVDeserializer::OutOfMemory:
+                        msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
+                        break;
+                    default:
+                        break;
+                }
+            } else {
+                msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
+            } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type)
+        } else {
+            // Operation is not allowed.
+            tr_error("M2MObjectInstance::handle_post_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
+            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+        }
+    } else {
+        msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+    }
+    if(coap_response) {
+        coap_response->msg_code = msg_code;
+    }
+    return coap_response;
+}
+
+void M2MObjectInstance::notification_update(M2MBase::Observation observation_level)
+{
+    tr_debug("M2MObjectInstance::notification_update() - level(%d)", observation_level);
+    if((M2MBase::O_Attribute & observation_level) == M2MBase::O_Attribute) {
+        tr_debug("M2MObjectInstance::notification_update() - object callback");
+        _parent.notification_update(instance_id());
+    }
+    if((M2MBase::OI_Attribute & observation_level) == M2MBase::OI_Attribute) {
+        tr_debug("M2MObjectInstance::notification_update() - object instance callback");
+        M2MReportHandler *report_handler = M2MBase::report_handler();
+        if(report_handler && is_under_observation()) {
+            report_handler->set_notification_trigger();
+        }
+
+    }
+}
+
+M2MBase *M2MObjectInstance::get_parent() const
+{
+    return (M2MBase *) &get_parent_object();
+}
+
+M2MBase::DataType M2MObjectInstance::convert_resource_type(M2MResourceInstance::ResourceType type)
+{
+    M2MBase::DataType data_type = M2MBase::OBJLINK;
+    switch(type) {
+        case M2MResourceInstance::STRING:
+            data_type = M2MBase::STRING;
+            break;
+        case M2MResourceInstance::INTEGER:
+            data_type = M2MBase::INTEGER;
+            break;
+        case M2MResourceInstance::FLOAT:
+            data_type = M2MBase::FLOAT;
+            break;
+        case M2MResourceInstance::OPAQUE:
+            data_type = M2MBase::OPAQUE;
+            break;
+        case M2MResourceInstance::BOOLEAN:
+            data_type = M2MBase::BOOLEAN;
+            break;
+        case M2MResourceInstance::TIME:
+            data_type = M2MBase::TIME;
+            break;
+        case M2MResourceInstance::OBJLINK:
+            data_type = M2MBase::OBJLINK;
+            break;
+    }
+    return data_type;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mreporthandler.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,604 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+// fixup the compilation on ARMCC for PRId32
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include "mbed-client/m2mreportobserver.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2mtimer.h"
+#include "include/m2mreporthandler.h"
+#include "mbed-trace/mbed_trace.h"
+#include <string.h>
+#include <stdlib.h>
+
+#define TRACE_GROUP "mClt"
+
+M2MReportHandler::M2MReportHandler(M2MReportObserver &observer)
+: _observer(observer),
+  _is_under_observation(false),
+  _observation_level(M2MBase::None),
+  _attribute_state(0),
+  _token_length(0),
+  _notify(false),
+  _pmin_exceeded(false),
+  _pmax_exceeded(false),
+  _observation_number(0),
+  _pmin_timer(*this),
+  _pmax_timer(*this),
+  _token(NULL),
+  _pmax(-1.0f),
+  _pmin(1.0f),
+  _current_value(0.0f),
+  _gt(0.0f),
+  _lt(0.0f),
+  _st(0.0f),
+  _high_step(0.0f),
+  _low_step(0.0f),
+  _last_value(-1.0f),
+  _notification_send_in_progress(false),
+  _notification_in_queue(false),
+  _blockwise_notify(false),
+  _pmin_quiet_period(false)
+{
+    tr_debug("M2MReportHandler::M2MReportHandler()");
+}
+
+M2MReportHandler::~M2MReportHandler()
+{
+    tr_debug("M2MReportHandler::~M2MReportHandler()");
+    free(_token);
+}
+
+void M2MReportHandler::set_under_observation(bool observed)
+{
+    tr_debug("M2MReportHandler::set_under_observation(observed %d)", (int)observed);
+
+    _is_under_observation = observed;
+
+    stop_timers();
+    if (observed) {
+        handle_timers();
+    }
+    else {
+        set_default_values();
+    }
+}
+
+void M2MReportHandler::set_value(float value)
+{
+    tr_debug("M2MReportHandler::set_value() - current %f, last %f", value, _last_value);
+    _current_value = value;
+
+    if (_current_value != _last_value) {
+        tr_debug("M2MReportHandler::set_value() - new value");
+        set_notification_in_queue(true);
+        if (check_threshold_values()) {
+            schedule_report();
+        } else {
+            tr_debug("M2MReportHandler::set_value - value not in range");
+            _notify = false;
+            if ((_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt ||
+                (_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt ||
+                (_attribute_state & M2MReportHandler::St) == M2MReportHandler::St) {
+                tr_debug("M2MReportHandler::set_value - stop pmin timer");
+                _pmin_timer.stop_timer();
+                _pmin_exceeded = true;
+            }
+        }
+        _high_step = _last_value + _st;
+        _low_step = _last_value - _st;
+    }
+}
+
+void M2MReportHandler::set_notification_trigger(uint16_t obj_instance_id)
+{
+    tr_debug("M2MReportHandler::set_notification_trigger(): %d", obj_instance_id);
+    // Add to array if not there yet
+    m2m::Vector<uint16_t>::const_iterator it;
+    it = _changed_instance_ids.begin();
+    bool found = false;
+    for ( ; it != _changed_instance_ids.end(); it++) {
+        if ((*it) == obj_instance_id) {
+            found = true;
+            break;
+        }
+    }
+    if (!found) {
+        _changed_instance_ids.push_back(obj_instance_id);
+    }
+
+    _current_value = 0.0f;
+    _last_value = 1.0f;
+    set_notification_in_queue(true);
+    schedule_report();
+}
+
+bool M2MReportHandler::parse_notification_attribute(const char *query,
+                                                    M2MBase::BaseType type,
+                                                    M2MResourceInstance::ResourceType resource_type)
+{
+    tr_debug("M2MReportHandler::parse_notification_attribute(Query %s, Base type %d)", query, (int)type);
+    bool success = false;
+    const char* sep_pos = strchr(query, '&');
+    const char* rest = query;
+    if( sep_pos != NULL ){
+        char query_options[5][20];
+        float pmin = _pmin;
+        float pmax = _pmax;
+        float lt = _lt;
+        float gt = _gt;
+        float st = _st;
+        float high = _high_step;
+        float low = _low_step;
+        uint8_t attr = _attribute_state;
+
+        memset(query_options, 0, sizeof(query_options[0][0]) * 5 * 20);
+        uint8_t num_options = 0;
+        while( sep_pos != NULL && num_options < 5){
+            size_t len = (size_t)(sep_pos-rest);
+            if( len > 19 ){
+                len = 19;
+            }
+            memcpy(query_options[num_options], rest, len);
+            sep_pos++;
+            rest = sep_pos;
+            sep_pos = strchr(rest, '&');
+            num_options++;
+        }
+        if( num_options < 5 && strlen(rest) > 0){
+            size_t len = (size_t)strlen(rest);
+            if( len > 19 ){
+                len = 19;
+            }
+            memcpy(query_options[num_options++], rest, len);
+        }
+
+        for (int option = 0; option < num_options; option++) {
+            success = set_notification_attribute(query_options[option],type, resource_type);
+            if (!success) {
+                tr_debug("M2MReportHandler::parse_notification_attribute - break");
+                break;
+            }
+        }
+
+        if(success) {
+             success = check_attribute_validity();
+        }
+        else {
+            tr_debug("M2MReportHandler::parse_notification_attribute - not valid query");
+            _pmin = pmin;
+            _pmax = pmax;
+            _st = st;
+            _lt = lt;
+            _gt = gt;
+            _high_step = high;
+            _low_step = low;
+            _attribute_state = attr;
+        }
+    }
+    else {
+        if(set_notification_attribute(query, type, resource_type)) {
+            success = check_attribute_validity();
+        }
+    }
+
+    return success;
+}
+
+void M2MReportHandler::timer_expired(M2MTimerObserver::Type type)
+{
+    switch(type) {
+        case M2MTimerObserver::PMinTimer: {
+            tr_debug("M2MReportHandler::timer_expired - PMIN");
+
+            _pmin_exceeded = true;
+            if (_notify ||
+                (_pmin > 0 && (_attribute_state & M2MReportHandler::Pmax) != M2MReportHandler::Pmax)){
+                report();
+            }
+
+            // If value hasn't changed since last expiration, next value change should send notification immediately
+            if (_current_value == _last_value) {
+                _pmin_quiet_period = true;
+            }
+        }
+        break;
+        case M2MTimerObserver::PMaxTimer: {
+            tr_debug("M2MReportHandler::timer_expired - PMAX");
+            _pmax_exceeded = true;
+            if (_pmin_exceeded ||
+                    (_attribute_state & M2MReportHandler::Pmin) != M2MReportHandler::Pmin ) {
+                report();
+            }
+        }
+        break;
+        default:
+            break;
+    }
+}
+
+bool M2MReportHandler::set_notification_attribute(const char* option,
+                                                  M2MBase::BaseType type,
+                                                  M2MResourceInstance::ResourceType resource_type)
+{
+    tr_debug("M2MReportHandler::set_notification_attribute()");
+    bool success = false;
+    char attribute[20];
+    char value[20];
+    memset(&attribute, 0, 20);
+    memset(&value, 0, 20);
+
+    const char* pos = strstr(option, EQUAL);
+    if( pos != NULL ){
+        memcpy(attribute, option, (size_t)(pos-option));
+        pos++;
+        memcpy(value, pos, strlen(pos));
+    }else{
+        memcpy(attribute, option, (size_t)strlen(option) + 1);
+    }
+
+    if (strlen(value)) {
+        if (strcmp(attribute, PMIN) == 0) {
+           _pmin = atoi(value);
+            success = true;
+            _attribute_state |= M2MReportHandler::Pmin;
+            tr_info("M2MReportHandler::set_notification_attribute %s to %" PRId32, attribute, _pmin);
+        }
+        else if(strcmp(attribute, PMAX) == 0) {
+            _pmax = atoi(value);
+            success = true;
+            _attribute_state |= M2MReportHandler::Pmax;
+            tr_info("M2MReportHandler::set_notification_attribute %s to %" PRId32, attribute, _pmax);
+        }
+        else if(strcmp(attribute, GT) == 0 &&
+                (M2MBase::Resource == type)){
+            _gt = atof(value);
+            success = true;
+            _attribute_state |= M2MReportHandler::Gt;
+            tr_info("M2MReportHandler::set_notification_attribute %s to %f", attribute, _gt);
+        }
+        else if(strcmp(attribute, LT) == 0 &&
+                (M2MBase::Resource == type)){
+            _lt = atof(value);
+            success = true;
+            _attribute_state |= M2MReportHandler::Lt;
+            tr_info("M2MReportHandler::set_notification_attribute %s to %f", attribute, _lt);
+        }
+        else if((strcmp(attribute, ST_SIZE) == 0 || (strcmp(attribute, STP) == 0))
+                && (M2MBase::Resource == type)){
+            _st = atof(value);
+            success = true;
+            _high_step = _current_value + _st;
+            _low_step = _current_value - _st;
+            _attribute_state |= M2MReportHandler::St;
+            tr_info("M2MReportHandler::set_notification_attribute %s to %f", attribute, _st);
+        }
+        // Return false if try to set gt,lt or st when the resource type is something else than numerical
+        if ((resource_type != M2MResourceInstance::INTEGER &&
+                resource_type != M2MResourceInstance::FLOAT) &&
+                ((_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt ||
+                (_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt ||
+                (_attribute_state & M2MReportHandler::St) == M2MReportHandler::St)) {
+            tr_debug("M2MReportHandler::set_notification_attribute - not numerical resource");
+            success = false;
+        }
+    }
+    return success;
+}
+
+void M2MReportHandler::schedule_report(bool in_queue)
+{
+    tr_debug("M2MReportHandler::schedule_report()");
+    _notify = true;
+
+    if ((_attribute_state & M2MReportHandler::Pmin) != M2MReportHandler::Pmin ||
+         _pmin_exceeded ||
+         _pmin_quiet_period) {
+        report(in_queue);
+    }
+}
+
+void M2MReportHandler::report(bool in_queue)
+{
+    tr_debug("M2MReportHandler::report() - current %2f, last %2f, notify %d, queued %d", _current_value, _last_value, _notify, in_queue);
+
+    if((_current_value != _last_value && _notify) || in_queue) {
+        if (_pmin_exceeded) {
+            tr_debug("M2MReportHandler::report()- send with PMIN expiration");
+        } else {
+            tr_debug("M2MReportHandler::report()- send with VALUE change");
+        }
+
+        _pmin_exceeded = false;
+        _pmax_exceeded = false;
+        _notify = false;
+        _pmin_quiet_period = false;
+        _observation_number++;
+
+        if (_observation_number == 1) {
+            // Increment the observation number by 1 if it is already 1 because CoAP specification has reserved 1 for DEREGISTER notification
+            _observation_number++;
+        }
+
+        if (_observer.observation_to_be_sent(_changed_instance_ids, observation_number())) {
+            _changed_instance_ids.clear();
+            set_notification_send_in_progress(true);
+        }
+
+        _pmax_timer.stop_timer();
+    }
+    else {
+        if (_pmax_exceeded) {
+            tr_debug("M2MReportHandler::report()- send with PMAX expiration");
+            _observation_number++;
+
+            if (_observation_number == 1) {
+                // Increment the observation number by 1 if it is already 1 because CoAP specification has reserved 1 for DEREGISTER notification
+                _observation_number++;
+            }
+
+            if (_observer.observation_to_be_sent(_changed_instance_ids, observation_number(), true)) {
+                _changed_instance_ids.clear();
+                set_notification_send_in_progress(true);
+            } else {
+                set_notification_in_queue(true);
+            }
+        }
+        else {
+            tr_debug("M2MReportHandler::report()- no need to send");
+        }
+    }
+    handle_timers();
+    _last_value = _current_value;
+}
+
+void M2MReportHandler::handle_timers()
+{
+    tr_debug("M2MReportHandler::handle_timers()");
+    uint64_t time_interval = 0;
+    if ((_attribute_state & M2MReportHandler::Pmin) == M2MReportHandler::Pmin) {
+        if (_pmin == _pmax) {
+            _pmin_exceeded = true;
+        } else {
+            _pmin_exceeded = false;
+            time_interval = (uint64_t) ((uint64_t)_pmin * 1000);
+            tr_debug("M2MReportHandler::handle_timers() - Start PMIN interval: %d", (int)time_interval);
+            _pmin_timer.start_timer(time_interval,
+                                     M2MTimerObserver::PMinTimer,
+                                     true);
+        }
+    }
+    if ((_attribute_state & M2MReportHandler::Pmax) == M2MReportHandler::Pmax) {
+        if (_pmax > 0) {
+            time_interval = (uint64_t) ((uint64_t)_pmax * 1000);
+            tr_debug("M2MReportHandler::handle_timers() - Start PMAX interval: %d", (int)time_interval);
+            _pmax_timer.start_timer(time_interval,
+                                     M2MTimerObserver::PMaxTimer,
+                                     true);
+        }
+    }
+}
+
+bool M2MReportHandler::check_attribute_validity() const
+{
+    bool success = true;
+    if ((_attribute_state & M2MReportHandler::Pmax) == M2MReportHandler::Pmax &&
+            ((_pmax >= -1.0) && (_pmin > _pmax))) {
+        success = false;
+    }
+    float low = _lt + 2 * _st;
+    if ((_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt &&
+            (low >= _gt)) {
+        success = false;
+    }
+    return success;
+}
+
+void M2MReportHandler::stop_timers()
+{
+    tr_debug("M2MReportHandler::stop_timers()");
+
+    _pmin_exceeded = false;
+    _pmin_timer.stop_timer();
+
+    _pmax_exceeded = false;
+    _pmax_timer.stop_timer();
+
+    tr_debug("M2MReportHandler::stop_timers() - out");
+}
+
+void M2MReportHandler::set_default_values()
+{
+    tr_debug("M2MReportHandler::set_default_values");
+    _pmax = -1.0;
+    _pmin = 1.0;
+    _gt = 0.0f;
+    _lt = 0.0f;
+    _st = 0.0f;
+    _high_step = 0.0f;
+    _low_step = 0.0f;
+    _pmin_exceeded = false;
+    _pmax_exceeded = false;
+    _last_value = -1.0f;
+    _attribute_state = 0;
+    _changed_instance_ids.clear();
+    _notification_in_queue = false;
+    _notification_send_in_progress = false;
+    _pmin_quiet_period = false;
+}
+
+bool M2MReportHandler::check_threshold_values() const
+{
+    tr_debug("M2MReportHandler::check_threshold_values");
+    tr_debug("Current value: %f", _current_value);
+    tr_debug("Last value: %f", _last_value);
+    tr_debug("High step: %f", _high_step);
+    tr_debug("Low step: %f", _low_step);
+    tr_debug("Less than: %f", _lt);
+    tr_debug("Greater than: %f", _gt);
+    tr_debug("Step: %f", _st);
+
+    bool can_send = check_gt_lt_params();
+    if (can_send) {
+        if ((_attribute_state & M2MReportHandler::St) == M2MReportHandler::St) {
+            if ((_current_value >= _high_step ||
+                _current_value <= _low_step)) {
+                can_send = true;
+            } else {
+                can_send = false;
+            }
+        }
+    }
+
+    tr_debug("M2MReportHandler::check_threshold_values - value can be sent = %d", (int)can_send);
+    return can_send;
+}
+
+bool M2MReportHandler::check_gt_lt_params() const
+{
+    tr_debug("M2MReportHandler::check_gt_lt_params");
+    bool can_send = false;
+    // GT & LT set.
+    if ((_attribute_state & (M2MReportHandler::Lt | M2MReportHandler::Gt)) ==
+        (M2MReportHandler::Lt | M2MReportHandler::Gt)) {
+        if (_current_value > _gt || _current_value < _lt) {
+            can_send = true;
+        }
+        else {
+            can_send = false;
+        }
+    }
+    // Only LT
+    else if ((_attribute_state & M2MReportHandler::Lt) == M2MReportHandler::Lt &&
+           (_attribute_state & M2MReportHandler::Gt) == 0 ) {
+        if (_current_value < _lt) {
+            can_send = true;
+        }
+        else {
+            can_send = false;
+        }
+    }
+    // Only GT
+    else if ((_attribute_state & M2MReportHandler::Gt) == M2MReportHandler::Gt &&
+           (_attribute_state & M2MReportHandler::Lt) == 0 ) {
+        if (_current_value > _gt) {
+            can_send = true;
+        }
+        else {
+            can_send = false;
+        }
+    }
+    // GT & LT not set.
+    else {
+        can_send = true;
+    }
+    tr_debug("M2MReportHandler::check_gt_lt_params - value in range = %d", (int)can_send);
+    return can_send;
+}
+
+uint8_t M2MReportHandler::attribute_flags() const
+{
+    return _attribute_state;
+}
+
+void M2MReportHandler::set_observation_token(const uint8_t *token, const uint8_t length)
+{
+     free(_token);
+     _token = NULL;
+     _token_length = 0;
+
+    if( token != NULL && length > 0 ) {
+        _token = alloc_string_copy((uint8_t *)token, length);
+        if(_token) {
+            _token_length = length;
+        }
+    }
+}
+
+void M2MReportHandler::get_observation_token(uint8_t *token, uint8_t &token_length) const
+{
+    memcpy(token, _token, _token_length);
+    token_length = _token_length;
+}
+
+uint16_t M2MReportHandler::observation_number() const
+{
+    return _observation_number;
+}
+
+void M2MReportHandler::add_observation_level(M2MBase::Observation obs_level)
+{
+    _observation_level = (M2MBase::Observation)(_observation_level | obs_level);
+}
+
+void M2MReportHandler::remove_observation_level(M2MBase::Observation obs_level)
+{
+    _observation_level = (M2MBase::Observation)(_observation_level & ~obs_level);
+}
+
+M2MBase::Observation M2MReportHandler::observation_level() const
+{
+    return _observation_level;
+}
+
+bool M2MReportHandler::is_under_observation() const
+{
+    return _is_under_observation;
+}
+
+uint8_t* M2MReportHandler::alloc_string_copy(const uint8_t* source, uint32_t size)
+{
+    assert(source != NULL);
+
+    uint8_t* result = (uint8_t*)malloc(size + 1);
+    if (result) {
+        memcpy(result, source, size);
+        result[size] = '\0';
+    }
+    return result;
+}
+
+void M2MReportHandler::set_notification_in_queue(bool to_queue)
+{
+    _notification_in_queue = to_queue;
+}
+
+bool M2MReportHandler::notification_in_queue() const
+{
+    return _notification_in_queue;
+}
+
+void M2MReportHandler::set_notification_send_in_progress(bool progress)
+{
+    _notification_send_in_progress = progress;
+}
+
+bool M2MReportHandler::notification_send_in_progress() const
+{
+    return _notification_send_in_progress;
+}
+
+void M2MReportHandler::set_blockwise_notify(bool blockwise_notify)
+{
+    _blockwise_notify = blockwise_notify;
+}
+
+bool M2MReportHandler::blockwise_notify() const
+{
+    return _blockwise_notify;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mresource.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,699 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2mresource.h"
+#include "mbed-client/m2mobservationhandler.h"
+#include "include/m2mreporthandler.h"
+#include "include/m2mtlvserializer.h"
+#include "include/m2mtlvdeserializer.h"
+#include "mbed-trace/mbed_trace.h"
+
+#include <stdlib.h>
+
+#define TRACE_GROUP "mClt"
+
+M2MResource::M2MResource(M2MObjectInstance &parent,
+                         const String &resource_name,
+                         M2MBase::Mode resource_mode,
+                         const String &resource_type,
+                         M2MBase::DataType type,
+                         const uint8_t *value,
+                         const uint8_t value_length,
+                         char *path,
+                         bool multiple_instance,
+                         bool external_blockwise_store)
+: M2MResourceBase(resource_name, resource_mode, resource_type, type, value, value_length,
+                      path, external_blockwise_store, multiple_instance),
+  _parent(parent)
+#ifndef DISABLE_DELAYED_RESPONSE
+  ,_delayed_token(NULL),
+  _delayed_token_len(0),
+  _delayed_response(false)
+#endif
+{
+    M2MBase::set_base_type(M2MBase::Resource);
+    M2MBase::set_operation(M2MBase::GET_ALLOWED);
+    M2MBase::set_observable(false);
+    if (multiple_instance) {
+        M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
+    }
+
+}
+
+M2MResource::M2MResource(M2MObjectInstance &parent,
+                         const lwm2m_parameters_s* s,
+                          M2MBase::DataType type)
+: M2MResourceBase(s, type),
+  _parent(parent)
+#ifndef DISABLE_DELAYED_RESPONSE
+  ,_delayed_token(NULL),
+  _delayed_token_len(0),
+  _delayed_response(false)
+#endif
+{
+    // verify, that the client has hardcoded proper type to the structure
+    assert(base_type() == M2MBase::Resource);
+}
+
+M2MResource::M2MResource(M2MObjectInstance &parent,
+                         const String &resource_name,
+                         M2MBase::Mode resource_mode,
+                         const String &resource_type,
+                         M2MBase::DataType type,
+                         bool observable,
+                         char *path,
+                         bool multiple_instance,
+                         bool external_blockwise_store)
+: M2MResourceBase(resource_name, resource_mode, resource_type, type,
+                      path,
+                      external_blockwise_store,multiple_instance),
+  _parent(parent)
+#ifndef DISABLE_DELAYED_RESPONSE
+  ,_delayed_token(NULL),
+  _delayed_token_len(0),
+  _delayed_response(false)
+#endif
+{
+    M2MBase::set_base_type(M2MBase::Resource);
+    M2MBase::set_operation(M2MBase::GET_PUT_ALLOWED);
+    M2MBase::set_observable(observable);
+    if (multiple_instance) {
+        M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
+    }
+}
+
+
+M2MResource::~M2MResource()
+{
+    if(!_resource_instance_list.empty()) {
+        M2MResourceInstance* res = NULL;
+        M2MResourceInstanceList::const_iterator it;
+        it = _resource_instance_list.begin();
+        for (; it!=_resource_instance_list.end(); it++ ) {
+            //Free allocated memory for resources.
+            res = *it;
+            delete res;
+        }
+        _resource_instance_list.clear();
+    }
+#ifndef DISABLE_DELAYED_RESPONSE
+    free(_delayed_token);
+#endif
+
+    free_resources();
+}
+
+bool M2MResource::supports_multiple_instances() const
+{
+    M2MBase::lwm2m_parameters_s* param = M2MBase::get_lwm2m_parameters();
+    return param->multiple_instance;
+}
+
+#ifndef DISABLE_DELAYED_RESPONSE
+void M2MResource::set_delayed_response(bool delayed_response)
+{
+    _delayed_response = delayed_response;
+}
+
+bool M2MResource::send_delayed_post_response()
+{
+    bool success = false;
+    if(_delayed_response) {
+        success = true;
+        // At least on some unit tests the resource object is not fully constructed, which would
+        // cause issues if the observation_handler is NULL. So do the check before dereferencing pointer.
+        M2MObservationHandler* obs = observation_handler();
+        if (obs) {
+            obs->send_delayed_response(this);
+        }
+    }
+    return success;
+}
+
+void M2MResource::get_delayed_token(uint8_t *&token, uint8_t &token_length)
+{
+    token_length = 0;
+    if(token) {
+        free(token);
+        token = NULL;
+    }
+    if(_delayed_token && _delayed_token_len > 0) {
+        token = alloc_copy(_delayed_token, _delayed_token_len);
+        if(token) {
+            token_length = _delayed_token_len;
+        }
+    }
+}
+#endif
+
+bool M2MResource::remove_resource_instance(uint16_t inst_id)
+{
+    tr_debug("M2MResource::remove_resource(inst_id %d)", inst_id);
+    bool success = false;
+    if(!_resource_instance_list.empty()) {
+        M2MResourceInstance* res = NULL;
+        M2MResourceInstanceList::const_iterator it;
+        it = _resource_instance_list.begin();
+        int pos = 0;
+        for ( ; it != _resource_instance_list.end(); it++, pos++ ) {
+            if(((*it)->instance_id() == inst_id)) {
+                // Resource found and deleted.
+                res = *it;
+                delete res;
+                _resource_instance_list.erase(pos);
+                set_changed();
+                success = true;
+                break;
+            }
+        }
+    }
+    return success;
+}
+
+M2MResourceInstance* M2MResource::resource_instance(uint16_t inst_id) const
+{
+    tr_debug("M2MResource::resource(resource_name inst_id %d)", inst_id);
+    M2MResourceInstance *res = NULL;
+    if(!_resource_instance_list.empty()) {
+        M2MResourceInstanceList::const_iterator it;
+        it = _resource_instance_list.begin();
+        for ( ; it != _resource_instance_list.end(); it++ ) {
+            if(((*it)->instance_id() == inst_id)) {
+                // Resource found.
+                res = *it;
+                break;
+            }
+        }
+    }
+    return res;
+}
+
+const M2MResourceInstanceList& M2MResource::resource_instances() const
+{
+    return _resource_instance_list;
+}
+
+uint16_t M2MResource::resource_instance_count() const
+{
+    return (uint16_t)_resource_instance_list.size();
+}
+
+#ifndef DISABLE_DELAYED_RESPONSE
+bool M2MResource::delayed_response() const
+{
+    return _delayed_response;
+}
+#endif
+
+M2MObservationHandler* M2MResource::observation_handler() const
+{
+    const M2MObjectInstance& parent_object_instance = get_parent_object_instance();
+
+    // XXX: need to check the flag too
+    return parent_object_instance.observation_handler();
+}
+
+void M2MResource::set_observation_handler(M2MObservationHandler *handler)
+{
+    M2MObjectInstance& parent_object_instance = get_parent_object_instance();
+
+    // XXX: need to set the flag too
+    parent_object_instance.set_observation_handler(handler);
+}
+
+bool M2MResource::handle_observation_attribute(const char *query)
+{
+    tr_debug("M2MResource::handle_observation_attribute - is_under_observation(%d)", is_under_observation());
+    bool success = false;
+    M2MReportHandler *handler = M2MBase::report_handler();
+    if (!handler) {
+        handler = M2MBase::create_report_handler();
+    }
+
+    if (handler) {
+        success = handler->parse_notification_attribute(query,
+                M2MBase::base_type(), resource_instance_type());
+        if (success) {
+            if (is_under_observation()) {
+                handler->set_under_observation(true);
+            }
+        }
+        else {
+            handler->set_default_values();
+        }
+
+        if (success) {
+            if(!_resource_instance_list.empty()) {
+                M2MResourceInstanceList::const_iterator it;
+                it = _resource_instance_list.begin();
+                for ( ; it != _resource_instance_list.end(); it++ ) {
+                    M2MReportHandler *report_handler = (*it)->report_handler();
+                    if(report_handler && is_under_observation()) {
+                        report_handler->set_notification_trigger();
+                    }
+                }
+            }
+        }
+    }
+    return success;
+}
+
+void M2MResource::add_observation_level(M2MBase::Observation observation_level)
+{
+    M2MBase::add_observation_level(observation_level);
+    if(!_resource_instance_list.empty()) {
+        M2MResourceInstanceList::const_iterator inst;
+        inst = _resource_instance_list.begin();
+        for ( ; inst != _resource_instance_list.end(); inst++ ) {
+            (*inst)->add_observation_level(observation_level);
+        }
+    }
+}
+
+void M2MResource::remove_observation_level(M2MBase::Observation observation_level)
+{
+    M2MBase::remove_observation_level(observation_level);
+    if(!_resource_instance_list.empty()) {
+        M2MResourceInstanceList::const_iterator inst;
+        inst = _resource_instance_list.begin();
+        for ( ; inst != _resource_instance_list.end(); inst++ ) {
+            (*inst)->remove_observation_level(observation_level);
+        }
+    }
+}
+
+void M2MResource::add_resource_instance(M2MResourceInstance *res)
+{
+    tr_debug("M2MResource::add_resource_instance()");
+    if(res) {
+        _resource_instance_list.push_back(res);
+        set_changed();
+    }
+}
+
+sn_coap_hdr_s* M2MResource::handle_get_request(nsdl_s *nsdl,
+                                               sn_coap_hdr_s *received_coap_header,
+                                               M2MObservationHandler *observation_handler)
+{
+    tr_info("M2MResource::handle_get_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
+    sn_coap_hdr_s * coap_response = NULL;
+    if(supports_multiple_instances()) {
+        coap_response = sn_nsdl_build_response(nsdl,
+                                               received_coap_header,
+                                               msg_code);
+        if(received_coap_header) {
+            // process the GET if we have registered a callback for it
+            if ((operation() & SN_GRS_GET_ALLOWED) != 0) {
+                if(coap_response) {
+                    bool content_type_present = false;
+                    bool is_content_type_supported = true;
+
+                    if (received_coap_header->options_list_ptr &&
+                            received_coap_header->options_list_ptr->accept != COAP_CT_NONE) {
+                        content_type_present = true;
+                        coap_response->content_format = received_coap_header->options_list_ptr->accept;
+                    }
+
+                    // Check if preferred content type is supported
+                    if (content_type_present) {
+                        if (coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE_OLD &&
+                            coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE) {
+                            is_content_type_supported = false;
+                        }
+                    }
+
+                    if (is_content_type_supported) {
+                        if(!content_type_present &&
+                           (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
+                            M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
+                            coap_response->content_format = sn_coap_content_format_e(M2MBase::coap_content_type());
+                        }
+
+                        tr_debug("M2MResource::handle_get_request() - Request Content-type: %d", coap_response->content_format);
+
+                        uint8_t *data = NULL;
+                        uint32_t data_length = 0;
+                        // fill in the CoAP response payload
+                        if(COAP_CONTENT_OMA_TLV_TYPE == coap_response->content_format ||
+                           COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_response->content_format) {
+                            set_coap_content_type(coap_response->content_format);
+                            data = M2MTLVSerializer::serialize(this, data_length);
+                        }
+
+                        coap_response->payload_len = data_length;
+                        coap_response->payload_ptr = data;
+
+                        coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
+                        if (coap_response->options_list_ptr) {
+                            coap_response->options_list_ptr->max_age = max_age();
+                        }
+
+                        if(received_coap_header->options_list_ptr) {
+                            if(received_coap_header->options_list_ptr->observe != -1) {
+                                if (is_observable()) {
+                                    uint32_t number = 0;
+                                    uint8_t observe_option = 0;
+                                    observe_option = received_coap_header->options_list_ptr->observe;
+                                    if(START_OBSERVATION == observe_option) {
+                                        // If the observe length is 0 means register for observation.
+                                        if(received_coap_header->options_list_ptr->observe != -1) {
+                                            number = received_coap_header->options_list_ptr->observe;
+                                        }
+
+                                        // If the observe value is 0 means register for observation.
+                                        if(number == 0) {
+                                            tr_info("M2MResource::handle_get_request - put resource under observation");
+                                            M2MResourceInstanceList::const_iterator it;
+                                            it = _resource_instance_list.begin();
+                                            for (; it!=_resource_instance_list.end(); it++ ) {
+                                                (*it)->add_observation_level(M2MBase::R_Attribute);
+                                            }
+                                            set_under_observation(true,observation_handler);
+                                            M2MBase::add_observation_level(M2MBase::R_Attribute);
+                                            send_notification_delivery_status(*this, NOTIFICATION_STATUS_SUBSCRIBED);
+                                            if (coap_response->options_list_ptr) {
+                                                coap_response->options_list_ptr->observe = observation_number();
+                                            }
+                                        }
+
+                                        if(received_coap_header->token_ptr) {
+                                            set_observation_token(received_coap_header->token_ptr,
+                                                                  received_coap_header->token_len);
+                                        }
+
+                                    } else if (STOP_OBSERVATION == observe_option) {
+                                        tr_info("M2MResource::handle_get_request - stops observation");
+                                        set_under_observation(false,NULL);
+                                        M2MBase::remove_observation_level(M2MBase::R_Attribute);
+                                        send_notification_delivery_status(*this,NOTIFICATION_STATUS_UNSUBSCRIBED);
+                                        M2MResourceInstanceList::const_iterator it;
+                                        it = _resource_instance_list.begin();
+                                        for (; it!=_resource_instance_list.end(); it++ ) {
+                                            (*it)->remove_observation_level(M2MBase::R_Attribute);
+                                        }
+                                    }
+                                    msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
+                                } else {
+                                    msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+                                }
+                            }
+                        }
+                    } else {
+                        tr_error("M2MResource::handle_get_request() - Content-Type %d not supported", coap_response->content_format);
+                        msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE;
+                    }
+                }
+            } else {
+                tr_error("M2MResource::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
+                // Operation is not allowed.
+                msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+            }
+        }
+        if(coap_response) {
+            coap_response->msg_code = msg_code;
+        }
+    } else {
+        coap_response = M2MResourceBase::handle_get_request(nsdl,
+                            received_coap_header,
+                            observation_handler);
+    }
+    return coap_response;
+}
+
+sn_coap_hdr_s* M2MResource::handle_put_request(nsdl_s *nsdl,
+                                               sn_coap_hdr_s *received_coap_header,
+                                               M2MObservationHandler *observation_handler,
+                                               bool &execute_value_updated)
+{
+    tr_info("M2MResource::handle_put_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
+    sn_coap_hdr_s * coap_response = NULL;
+    if(supports_multiple_instances()) {
+        coap_response = sn_nsdl_build_response(nsdl,
+                                               received_coap_header,
+                                               msg_code);
+        // process the PUT if we have registered a callback for it
+        if(received_coap_header) {
+            uint16_t coap_content_type = 0;
+            bool content_type_present = false;
+            if(received_coap_header->content_format != COAP_CT_NONE && coap_response) {
+                content_type_present = true;
+                coap_content_type = received_coap_header->content_format;
+            }
+            if(received_coap_header->options_list_ptr &&
+               received_coap_header->options_list_ptr->uri_query_ptr) {
+                char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr,
+                                                        received_coap_header->options_list_ptr->uri_query_len);
+                if (query){
+                    msg_code = COAP_MSG_CODE_RESPONSE_CHANGED;
+                    tr_info("M2MResource::handle_put_request() - query %s", query);
+                    // if anything was updated, re-initialize the stored notification attributes
+                    if (!handle_observation_attribute(query)){
+                        tr_debug("M2MResource::handle_put_request() - Invalid query");
+                        msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00
+                    }
+                    free(query);
+                }
+            } else if ((operation() & SN_GRS_PUT_ALLOWED) != 0) {
+                if(!content_type_present &&
+                   (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
+                    M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
+                    coap_content_type = COAP_CONTENT_OMA_TLV_TYPE;
+                }
+
+                tr_debug("M2MResource::handle_put_request() - Request Content-type: %d", coap_content_type);
+
+                if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type ||
+                   COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type) {
+                    set_coap_content_type(coap_content_type);
+                    M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
+                    error = M2MTLVDeserializer::deserialize_resource_instances(received_coap_header->payload_ptr,
+                                                                         received_coap_header->payload_len,
+                                                                         *this,
+                                                                         M2MTLVDeserializer::Put);
+                    switch(error) {
+                        case M2MTLVDeserializer::None:
+                            if(observation_handler) {
+                                String value = "";
+                                if (received_coap_header->uri_path_ptr != NULL &&
+                                    received_coap_header->uri_path_len > 0) {
+
+                                    value.append_raw((char*)received_coap_header->uri_path_ptr,received_coap_header->uri_path_len);
+                                }
+                                execute_value_updated = true;
+                            }
+                            msg_code = COAP_MSG_CODE_RESPONSE_CHANGED;
+                            break;
+                        case M2MTLVDeserializer::NotFound:
+                            msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
+                            break;
+                        case M2MTLVDeserializer::NotAllowed:
+                            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+                            break;
+                        case M2MTLVDeserializer::NotValid:
+                            msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+                            break;
+                        case M2MTLVDeserializer::OutOfMemory:
+                            msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
+                            break;
+                    }
+                } else {
+                    msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
+                } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type)
+            } else {
+                // Operation is not allowed.
+                tr_error("M2MResource::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
+                msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+            }
+        } else {
+            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+        }
+        if(coap_response) {
+            coap_response->msg_code = msg_code;
+        }
+    } else {
+        coap_response = M2MResourceBase::handle_put_request(nsdl,
+                            received_coap_header,
+                            observation_handler,
+                            execute_value_updated);
+    }
+    return coap_response;
+}
+
+
+sn_coap_hdr_s* M2MResource::handle_post_request(nsdl_s *nsdl,
+                                                sn_coap_hdr_s *received_coap_header,
+                                                M2MObservationHandler */*observation_handler*/,
+                                                bool &/*execute_value_updated*/,
+                                                sn_nsdl_addr_s *address)
+{
+    tr_info("M2MResource::handle_post_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
+    sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
+                                                           received_coap_header,
+                                                           msg_code);
+
+    // process the POST if we have registered a callback for it
+    if(received_coap_header) {
+        if ((operation() & SN_GRS_POST_ALLOWED) != 0) {
+            M2MResource::M2MExecuteParameter exec_params(object_name(), name(), object_instance_id());
+
+            uint16_t coap_content_type = 0;
+            if(received_coap_header->payload_ptr) {
+                if(received_coap_header->content_format != COAP_CT_NONE) {
+                    coap_content_type = received_coap_header->content_format;
+                }
+
+                if(coap_content_type == COAP_CT_TEXT_PLAIN) {
+                    exec_params._value = received_coap_header->payload_ptr;
+                    if (exec_params._value) {
+                        exec_params._value_length = received_coap_header->payload_len;
+                    }
+                } else {
+                    msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
+                }
+            }
+            if(COAP_MSG_CODE_RESPONSE_CHANGED == msg_code) {
+                tr_debug("M2MResource::handle_post_request - Execute resource function");
+#ifndef DISABLE_DELAYED_RESPONSE
+                if (coap_response) {
+                    if(_delayed_response) {
+                        if(received_coap_header->token_len) {
+                            free(_delayed_token);
+                            _delayed_token = NULL;
+                            _delayed_token_len = 0;
+                            _delayed_token = alloc_copy(received_coap_header->token_ptr, received_coap_header->token_len);
+                            if(_delayed_token) {
+                                _delayed_token_len = received_coap_header->token_len;
+                            }
+                        }
+                    } else {
+    #endif
+                        uint32_t length = 0;
+                        get_value(coap_response->payload_ptr, length);
+                        coap_response->payload_len = length;
+    #ifndef DISABLE_DELAYED_RESPONSE
+                    }
+                }
+#endif
+                execute(&exec_params);
+            }
+
+        } else { // if ((object->operation() & SN_GRS_POST_ALLOWED) != 0)
+            tr_error("M2MResource::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
+            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.05
+        }
+    } else { //if(object && received_coap_header)
+        tr_error("M2MResource::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
+        msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.01
+    }
+    if(coap_response) {
+        coap_response->msg_code = msg_code;
+    }
+    return coap_response;
+}
+
+M2MBase *M2MResource::get_parent() const
+{
+    return (M2MBase *) &get_parent_object_instance();
+}
+
+M2MObjectInstance& M2MResource::get_parent_object_instance() const
+{
+    return _parent;
+}
+
+uint16_t M2MResource::object_instance_id() const
+{
+    const M2MObjectInstance& parent_object_instance = get_parent_object_instance();
+    return parent_object_instance.instance_id();
+}
+
+M2MResource& M2MResource::get_parent_resource() const
+{
+    return (M2MResource&)*this;
+}
+
+const char* M2MResource::object_name() const
+{
+    const M2MObjectInstance& parent_object_instance = _parent;
+    const M2MObject& parent_object = parent_object_instance.get_parent_object();
+
+    return parent_object.name();
+}
+
+#ifdef MEMORY_OPTIMIZED_API
+M2MResource::M2MExecuteParameter::M2MExecuteParameter(const char *object_name, const char *resource_name,
+                                                        uint16_t object_instance_id) :
+_object_name(object_name),
+_resource_name(resource_name),
+_value(NULL),
+_value_length(0),
+_object_instance_id(object_instance_id)
+{
+}
+#else
+M2MResource::M2MExecuteParameter::M2MExecuteParameter(const String &object_name, const String &resource_name,
+                                                        uint16_t object_instance_id) :
+_object_name(object_name),
+_resource_name(resource_name),
+_value(NULL),
+_value_length(0),
+_object_instance_id(object_instance_id)
+{
+}
+#endif
+
+// These could be actually changed to be inline ones, as it would likely generate
+// smaller code at application side.
+
+const uint8_t *M2MResource::M2MExecuteParameter::get_argument_value() const
+{
+    return _value;
+}
+
+uint16_t M2MResource::M2MExecuteParameter::get_argument_value_length() const
+{
+    return _value_length;
+}
+
+#ifdef MEMORY_OPTIMIZED_API
+const char* M2MResource::M2MExecuteParameter::get_argument_object_name() const
+{
+    return _object_name;
+}
+
+const char* M2MResource::M2MExecuteParameter::get_argument_resource_name() const
+{
+    return _resource_name;
+}
+#else
+const String& M2MResource::M2MExecuteParameter::get_argument_object_name() const
+{
+    return _object_name;
+}
+
+const String& M2MResource::M2MExecuteParameter::get_argument_resource_name() const
+{
+    return _resource_name;
+}
+#endif
+
+uint16_t M2MResource::M2MExecuteParameter::get_argument_object_instance_id() const
+{
+    return _object_instance_id;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mresourcebase.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,935 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+// Needed for PRIu64 on FreeRTOS
+#include <stdio.h>
+// Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+
+// Note: this macro is needed on armcc to get the the PRI*32 macros
+// from inttypes.h in a C++ code.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <stdlib.h>
+#include "mbed-client/m2mresourcebase.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2mobservationhandler.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mobjectinstance.h"
+#include "include/m2mcallbackstorage.h"
+#include "include/m2mreporthandler.h"
+#include "include/nsdllinker.h"
+#include "include/m2mtlvserializer.h"
+#include "mbed-client/m2mblockmessage.h"
+#include "mbed-trace/mbed_trace.h"
+
+#define TRACE_GROUP "mClt"
+
+// -9223372036854775808 - +9223372036854775807
+// max length of int64_t string is 20 bytes + nil
+#define REGISTRY_INT64_STRING_MAX_LEN 21
+// (space needed for -3.402823 × 10^38) + (magic decimal 6 digits added as no precision is added to "%f") + trailing zero
+#define REGISTRY_FLOAT_STRING_MAX_LEN 48
+
+
+
+M2MResourceBase::M2MResourceBase(
+                                         const String &res_name,
+                                         M2MBase::Mode resource_mode,
+                                         const String &resource_type,
+                                         M2MBase::DataType type,
+                                         char* path,
+                                         bool external_blockwise_store,
+                                         bool multiple_instance)
+: M2MBase(res_name,
+          resource_mode,
+#ifndef DISABLE_RESOURCE_TYPE
+          resource_type,
+#endif
+          path,
+          external_blockwise_store,
+          multiple_instance,
+          type)
+#ifndef DISABLE_BLOCK_MESSAGE
+ ,_block_message_data(NULL),
+#endif
+  _notification_status(M2MResourceBase::INIT)
+{
+}
+
+M2MResourceBase::M2MResourceBase(
+                                         const String &res_name,
+                                         M2MBase::Mode resource_mode,
+                                         const String &resource_type,
+                                         M2MBase::DataType type,
+                                         const uint8_t *value,
+                                         const uint8_t value_length,
+                                         char* path,
+                                         bool external_blockwise_store,
+                                         bool multiple_instance)
+: M2MBase(res_name,
+          resource_mode,
+#ifndef DISABLE_RESOURCE_TYPE
+          resource_type,
+#endif
+          path,
+          external_blockwise_store,
+          multiple_instance,
+          type)
+#ifndef DISABLE_BLOCK_MESSAGE
+ ,_block_message_data(NULL),
+#endif
+ _notification_status(M2MResourceBase::INIT)
+{
+    M2MBase::set_base_type(M2MBase::ResourceInstance);
+    if( value != NULL && value_length > 0 ) {
+        sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource();
+        res->resource = alloc_string_copy(value, value_length);
+        res->resource_len = value_length;
+    }
+}
+
+M2MResourceBase::M2MResourceBase(
+                                         const lwm2m_parameters_s* s,
+                                         M2MBase::DataType /*type*/)
+: M2MBase(s)
+#ifndef DISABLE_BLOCK_MESSAGE
+  ,_block_message_data(NULL),
+#endif
+  _notification_status(M2MResourceBase::INIT)
+{
+    // we are not there yet for this check as this is called from M2MResource(): assert(base_type() == M2MBase::ResourceInstance);
+}
+
+M2MResourceBase::~M2MResourceBase()
+{
+    execute_callback* callback = (execute_callback*)M2MCallbackStorage::remove_callback(*this,
+                                    M2MCallbackAssociation::M2MResourceInstanceExecuteCallback);
+    delete callback;
+
+    M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback2);
+#ifndef DISABLE_BLOCK_MESSAGE
+    incoming_block_message_callback *in_callback = (incoming_block_message_callback*)M2MCallbackStorage::remove_callback(*this,
+                                                        M2MCallbackAssociation::M2MResourceInstanceIncomingBlockMessageCallback);
+    delete in_callback;
+
+    outgoing_block_message_callback *out_callback = (outgoing_block_message_callback*)M2MCallbackStorage::remove_callback(*this,
+                                                        M2MCallbackAssociation::M2MResourceInstanceOutgoingBlockMessageCallback);
+    delete out_callback;
+#endif
+
+    notification_sent_callback *notif_callback = (notification_sent_callback*)M2MCallbackStorage::remove_callback(*this,
+                                                        M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback);
+    delete notif_callback;
+
+    M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback2);
+
+    notification_status_callback *notif_status_callback = (notification_status_callback*)M2MCallbackStorage::remove_callback(*this,
+                                                        M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback);
+    delete notif_status_callback;
+
+    M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback2);
+
+#ifndef DISABLE_BLOCK_MESSAGE
+    delete _block_message_data;
+#endif
+}
+
+M2MResourceBase::ResourceType M2MResourceBase::resource_instance_type() const
+{
+    M2MBase::lwm2m_parameters_s* param = M2MBase::get_lwm2m_parameters();
+    M2MBase::DataType type = param->data_type;
+    return convert_data_type(type);
+}
+
+
+bool M2MResourceBase::set_execute_function(execute_callback callback)
+{
+    execute_callback* old_callback = (execute_callback*)M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback);
+    delete old_callback;
+    // XXX: create a copy of the copy of callback object. Perhaps it would better to
+    // give a reference as parameter and just store that, as it would save some memory.
+    execute_callback* new_callback = new execute_callback(callback);
+
+    return M2MCallbackStorage::add_callback(*this, new_callback, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback);
+}
+
+bool M2MResourceBase::set_execute_function(execute_callback_2 callback)
+{
+    M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback2);
+
+    return M2MCallbackStorage::add_callback(*this, (void*)callback, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback2);
+}
+
+bool M2MResourceBase::set_resource_read_callback(read_resource_value_callback callback, void *client_args)
+{
+    M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceBaseValueReadCallback);
+    M2MBase::lwm2m_parameters_s* param = M2MBase::get_lwm2m_parameters();
+    param->read_write_callback_set = true;
+    return M2MCallbackStorage::add_callback(*this,
+                                            (void*)callback,
+                                            M2MCallbackAssociation::M2MResourceBaseValueReadCallback,
+                                            client_args);
+
+}
+
+bool M2MResourceBase::set_resource_write_callback(write_resource_value_callback callback, void *client_args)
+{
+    M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceBaseValueWriteCallback);
+    M2MBase::lwm2m_parameters_s* param = M2MBase::get_lwm2m_parameters();
+    param->read_write_callback_set = true;
+
+    return M2MCallbackStorage::add_callback(*this,
+                                            (void*)callback,
+                                            M2MCallbackAssociation::M2MResourceBaseValueWriteCallback,
+                                            client_args);
+}
+
+void M2MResourceBase::clear_value()
+{
+    tr_debug("M2MResourceBase::clear_value");
+
+    sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource();
+    free(res->resource);
+    res->resource = NULL;
+    res->resource_len = 0;
+
+    report();
+}
+
+bool M2MResourceBase::set_value_float(float value)
+{
+    bool success;
+    char buffer[REGISTRY_FLOAT_STRING_MAX_LEN];
+
+    // Convert value to string
+    /* write the float value to a decimal number string and copy it into a buffer allocated for caller */
+    uint32_t size = snprintf(buffer, REGISTRY_FLOAT_STRING_MAX_LEN, "%f", value);
+
+    success = set_value((const uint8_t*)buffer, size);
+
+    return success;
+}
+
+bool M2MResourceBase::set_value(int64_t value)
+{
+    bool success;
+    char buffer[REGISTRY_INT64_STRING_MAX_LEN];
+    uint32_t size = m2m::itoa_c(value, buffer);
+
+    success = set_value((const uint8_t*)buffer, size);
+
+    return success;
+}
+
+bool M2MResourceBase::set_value(const uint8_t *value,
+                                const uint32_t value_length)
+{
+    tr_debug("M2MResourceBase::set_value()");
+    bool success = false;
+    if( value != NULL && value_length > 0 ) {
+        M2MBase::lwm2m_parameters_s* param = M2MBase::get_lwm2m_parameters();
+        if (param->read_write_callback_set) {
+            return write_resource_value(*this, value, value_length);
+        } else {
+            uint8_t *value_copy = alloc_string_copy(value, value_length);
+            if (value_copy) {
+                value_set_callback callback = (value_set_callback)M2MCallbackStorage::get_callback(*this, M2MCallbackAssociation::M2MResourceBaseValueSetCallback);
+                if (callback) {
+                    (*callback)((const M2MResourceBase*)this, value_copy, value_length);
+                }
+                else {
+                    update_value(value_copy, value_length);
+                }
+                success = true;
+            }
+        }
+    }
+    return success;
+}
+
+bool M2MResourceBase::set_value_raw(uint8_t *value,
+                                const uint32_t value_length)
+
+{
+    tr_debug("M2MResourceBase::set_value_raw()");
+    bool success = false;
+    if( value != NULL && value_length > 0 ) {
+        success = true;
+        value_set_callback callback = (value_set_callback)M2MCallbackStorage::get_callback(*this, M2MCallbackAssociation::M2MResourceBaseValueSetCallback);
+        if (callback) {
+            (*callback)((const M2MResourceBase*)this, value, value_length);
+        }
+        else {
+            update_value(value, value_length);
+        }
+    }
+    return success;
+}
+
+void M2MResourceBase::update_value(uint8_t *value, const uint32_t value_length)
+{
+    bool changed = has_value_changed(value,value_length);
+    sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource();
+    free(res->resource);
+    res->resource = value;
+    res->resource_len = value_length;
+    if (changed) {
+        report_value_change();
+    }
+}
+
+void M2MResourceBase::report()
+{
+    M2MBase::Observation observation_level = M2MBase::observation_level();
+    tr_debug("M2MResourceBase::report() - level %d", observation_level);
+
+    // We must combine the parent object/objectinstance/resource observation information
+    // when determining if there is observation set or not.
+    M2MObjectInstance& object_instance = get_parent_resource().get_parent_object_instance();
+    int parent_observation_level = (int)object_instance.observation_level();
+
+    parent_observation_level |= (int)object_instance.get_parent_object().observation_level();
+    parent_observation_level |= (int)get_parent_resource().observation_level();
+    parent_observation_level |= (int)observation_level;
+
+    tr_debug("M2MResourceBase::report() - combined level %d", parent_observation_level);
+
+    if((M2MBase::O_Attribute & parent_observation_level) == M2MBase::O_Attribute ||
+       (M2MBase::OI_Attribute & parent_observation_level) == M2MBase::OI_Attribute) {
+        tr_debug("M2MResourceBase::report() -- object/instance level");
+        M2MObjectInstance& object_instance = get_parent_resource().get_parent_object_instance();
+        object_instance.notification_update((M2MBase::Observation)parent_observation_level);
+    }
+
+    if(M2MBase::Dynamic == mode() &&
+       (M2MBase::R_Attribute & parent_observation_level) == M2MBase::R_Attribute) {
+        tr_debug("M2MResourceBase::report() - resource level");
+
+        if (((resource_instance_type() != M2MResourceBase::STRING) &&
+             (resource_instance_type() != M2MResourceBase::OPAQUE)) &&
+             (observation_level != M2MBase::None)) {
+            M2MReportHandler *report_handler = M2MBase::report_handler();
+            if (report_handler && is_observable()) {
+                const float float_value = get_value_float();
+                report_handler->set_value(float_value);
+            }
+        }
+        else {
+            if (base_type() == M2MBase::ResourceInstance) {
+                const M2MResource& parent_resource = get_parent_resource();
+                M2MReportHandler *report_handler = parent_resource.report_handler();
+                if(report_handler && parent_resource.is_observable()) {
+                    report_handler->set_notification_trigger(parent_resource.get_parent_object_instance().instance_id());
+                }
+            }
+        }
+    } else if(M2MBase::Static == mode()) {
+        M2MObservationHandler *obs_handler = observation_handler();
+        if(obs_handler) {
+            obs_handler->value_updated(this);
+        }
+    } else {
+        if (is_observable()) {
+            tr_warn("M2MResourceBase::report() - resource %s is observable but not yet subscribed!", uri_path());
+        }
+        tr_debug("M2MResourceBase::report() - mode = %d, is_observable = %d", mode(), is_observable());
+    }
+}
+
+bool M2MResourceBase::has_value_changed(const uint8_t* value, const uint32_t value_len)
+{
+    bool changed = false;
+    sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource();
+
+    if(value_len != res->resource_len) {
+        changed = true;
+    } else if(value && !res->resource) {
+        changed = true;
+    } else if(res->resource && !value) {
+        changed = true;
+    } else {
+        if (res->resource) {
+            if (memcmp(value, res->resource, res->resource_len) != 0) {
+                changed = true;
+            }
+        }
+    }
+    return changed;
+}
+
+void M2MResourceBase::report_value_change()
+{
+    if (resource_instance_type() == M2MResourceBase::STRING ||
+        resource_instance_type() == M2MResourceBase::OPAQUE) {
+        M2MReportHandler *report_handler = M2MBase::report_handler();
+        if(report_handler && is_under_observation()) {
+            report_handler->set_notification_trigger();
+        }
+    }
+    report();
+}
+
+void M2MResourceBase::execute(void *arguments)
+{
+    // XXX: this line is expected by seven testcases and until this code hits master branch
+    // the testcases can not be modified and we need to print the false information too.
+    tr_debug("M2MResourceBase::execute");
+
+    execute_callback* callback = (execute_callback*)M2MCallbackStorage::get_callback(*this, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback);
+
+    if (callback) {
+        (*callback)(arguments);
+    }
+
+    execute_callback_2 callback2 = (execute_callback_2)M2MCallbackStorage::get_callback(*this, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback2);
+    if (callback2) {
+        (*callback2)(arguments);
+    }
+}
+
+int M2MResourceBase::read_resource_value(const M2MResourceBase &resource, void *buffer, size_t *buffer_len)
+{
+    tr_debug("M2MResourceBase::read_resource_value");
+
+    M2MCallbackAssociation* item = M2MCallbackStorage::get_association_item(resource,
+                                                                            M2MCallbackAssociation::M2MResourceBaseValueReadCallback);
+
+    if (item) {
+        read_resource_value_callback callback = (read_resource_value_callback)item->_callback;
+        assert(callback);
+        return (*callback)(resource, buffer, buffer_len, item->_client_args);
+    } else {
+        if (value_length() > *buffer_len) {
+            return -1;
+        } else {
+            memcpy(buffer, value(), value_length());
+            *buffer_len = value_length();
+            return 0;
+        }
+    }
+}
+
+bool M2MResourceBase::write_resource_value(const M2MResourceBase &resource, const uint8_t *buffer, const size_t buffer_size)
+{
+    tr_debug("M2MResourceBase::write_resource_value");
+    M2MCallbackAssociation* item = M2MCallbackStorage::get_association_item(resource,
+                                                                            M2MCallbackAssociation::M2MResourceBaseValueWriteCallback);
+    if (item) {
+        write_resource_value_callback callback = (write_resource_value_callback)item->_callback;
+        if (callback) {
+            return (*callback)(resource, buffer, buffer_size, item->_client_args);
+        }
+    }
+
+    return false;
+}
+
+void M2MResourceBase::get_value(uint8_t *&value, uint32_t &value_length)
+{
+    value_length = 0;
+    if(value) {
+        free(value);
+        value = NULL;
+    }
+
+    sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource();
+    if(res->resource && res->resource_len > 0) {
+        value = alloc_string_copy(res->resource, res->resource_len);
+        if(value) {
+            value_length = res->resource_len;
+        }
+    }
+}
+
+int64_t M2MResourceBase::get_value_int() const
+{
+    int64_t value_int = 0;
+
+    const char *value_string = (char *)value();
+    const uint32_t value_len = value_length();
+
+    if ((value_string) && (value_len <= REGISTRY_INT64_STRING_MAX_LEN)) {
+
+        // -9223372036854775808 - +9223372036854775807
+        // max length of int64_t string is 20 bytes + nil
+        // The +1 here is there in case the string was already zero terminated.
+        char temp[REGISTRY_INT64_STRING_MAX_LEN + 1];
+
+        memcpy(temp, value_string, value_len);
+        temp[value_len] = 0;
+
+        value_int = atoll(temp);
+    }
+    return value_int;
+}
+
+String M2MResourceBase::get_value_string() const
+{
+    // XXX: do a better constructor to avoid pointless malloc
+    String value;
+    if (get_nsdl_resource()->resource) {
+        value.append_raw((char*)get_nsdl_resource()->resource, get_nsdl_resource()->resource_len);
+    }
+    return value;
+}
+
+float M2MResourceBase::get_value_float() const
+{
+    float value_float = 0;
+
+    const char *value_string = (char *)value();
+    const uint32_t value_len = value_length();
+
+    if ((value_string) && (value_len <= REGISTRY_FLOAT_STRING_MAX_LEN)) {
+
+        // (space needed for -3.402823 × 10^38) + (magic decimal 6 digits added as no precision is added to "%f") + trailing zero
+        // The +1 here is there in case the string was already zero terminated.
+        char temp[REGISTRY_FLOAT_STRING_MAX_LEN + 1];
+
+        memcpy(temp, value_string, value_len);
+        temp[value_len] = 0;
+
+        value_float = atof(temp);
+    }
+
+    return value_float;
+}
+
+uint8_t* M2MResourceBase::value() const
+{
+    return get_nsdl_resource()->resource;
+}
+
+uint32_t M2MResourceBase::value_length() const
+{
+    return get_nsdl_resource()->resource_len;
+}
+
+void M2MResourceBase::set_value_set_callback(value_set_callback callback)
+{
+    M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceBaseValueSetCallback);
+    M2MCallbackStorage::add_callback(*this, (void*)callback, M2MCallbackAssociation::M2MResourceBaseValueSetCallback);
+}
+
+sn_coap_hdr_s* M2MResourceBase::handle_get_request(nsdl_s *nsdl,
+                                               sn_coap_hdr_s *received_coap_header,
+                                               M2MObservationHandler *observation_handler)
+{
+    tr_info("M2MResourceBase::handle_get_request()");
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
+    sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl,
+                                                          received_coap_header,
+                                                          msg_code);
+    if (received_coap_header) {
+        // process the GET if we have registered a callback for it
+        if ((operation() & SN_GRS_GET_ALLOWED) != 0) {
+            if (coap_response) {
+                bool content_type_present = false;
+                if (received_coap_header->options_list_ptr &&
+                    received_coap_header->options_list_ptr->accept != COAP_CT_NONE) {
+                    content_type_present = true;
+                    coap_response->content_format = received_coap_header->options_list_ptr->accept;
+                    set_coap_content_type(coap_response->content_format);
+                }
+                if (!content_type_present) {
+                    if (resource_instance_type() == M2MResourceInstance::OPAQUE) {
+                        coap_response->content_format = sn_coap_content_format_e(COAP_CONTENT_OMA_OPAQUE_TYPE);
+                    } else {
+                        coap_response->content_format = sn_coap_content_format_e(COAP_CONTENT_OMA_PLAIN_TEXT_TYPE);
+                    }
+                }
+                // fill in the CoAP response payload
+                coap_response->payload_ptr = NULL;
+                uint32_t payload_len = 0;
+#ifndef DISABLE_BLOCK_MESSAGE
+                //If handler exists it means that resource value is stored in application side
+                if (block_message() && block_message()->is_block_message()) {
+                    outgoing_block_message_callback* outgoing_block_message_cb = (outgoing_block_message_callback*)M2MCallbackStorage::get_callback(*this,
+                                                                                    M2MCallbackAssociation::M2MResourceInstanceOutgoingBlockMessageCallback);
+                    if (outgoing_block_message_cb) {
+                        String name = "";
+                        if (received_coap_header->uri_path_ptr != NULL &&
+                            received_coap_header->uri_path_len > 0) {
+                            name.append_raw((char *)received_coap_header->uri_path_ptr, received_coap_header->uri_path_len);
+                        }
+                        (*outgoing_block_message_cb)(name, coap_response->payload_ptr, payload_len);
+                    }
+                } else {
+#endif
+                    if (coap_response->content_format == COAP_CONTENT_OMA_TLV_TYPE ||
+                        coap_response->content_format == COAP_CONTENT_OMA_TLV_TYPE_OLD) {
+                        coap_response->payload_ptr = M2MTLVSerializer::serialize(&get_parent_resource(), payload_len);
+                    } else {
+                        get_value(coap_response->payload_ptr,payload_len);
+                    }
+#ifndef DISABLE_BLOCK_MESSAGE
+                }
+#endif
+                tr_debug("M2MResourceBase::handle_get_request() - Request Content-type: %d", coap_response->content_format);
+                coap_response->payload_len = payload_len;
+                coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
+                if (coap_response->options_list_ptr) {
+                    coap_response->options_list_ptr->max_age = max_age();
+                }
+
+                if (received_coap_header->options_list_ptr) {
+                    if (received_coap_header->options_list_ptr->observe != -1) {
+                        if (is_observable()) {
+                            uint32_t number = 0;
+                            uint8_t observe_option = 0;
+                            observe_option = received_coap_header->options_list_ptr->observe;
+
+                            if (START_OBSERVATION == observe_option) {
+                                // If the observe length is 0 means register for observation.
+                                if (received_coap_header->options_list_ptr->observe != -1) {
+                                    number = received_coap_header->options_list_ptr->observe;
+                                }
+
+                                // If the observe value is 0 means register for observation.
+                                if (number == 0) {
+                                    tr_info("M2MResourceBase::handle_get_request - put resource under observation");
+                                    set_under_observation(true,observation_handler);
+                                    send_notification_delivery_status(*this, NOTIFICATION_STATUS_SUBSCRIBED);
+                                    M2MBase::add_observation_level(M2MBase::R_Attribute);
+                                    if (coap_response->options_list_ptr) {
+                                        coap_response->options_list_ptr->observe = observation_number();
+                                    }
+                                }
+
+                                if (received_coap_header->token_ptr) {
+                                    set_observation_token(received_coap_header->token_ptr,
+                                                          received_coap_header->token_len);
+                                }
+
+                            } else if (STOP_OBSERVATION == observe_option) {
+                                tr_info("M2MResourceBase::handle_get_request - stops observation");
+                                set_under_observation(false,NULL);
+                                M2MBase::remove_observation_level(M2MBase::R_Attribute);
+                                send_notification_delivery_status(*this, NOTIFICATION_STATUS_UNSUBSCRIBED);
+                            }
+                        } else {
+                            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+                        }
+                    }
+                }
+            }
+        } else {
+            tr_error("M2MResourceBase::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
+            // Operation is not allowed.
+            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+        }
+    } else {
+        msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+    }
+
+    if (coap_response) {
+        coap_response->msg_code = msg_code;
+    }
+
+    return coap_response;
+}
+
+sn_coap_hdr_s* M2MResourceBase::handle_put_request(nsdl_s *nsdl,
+                                               sn_coap_hdr_s *received_coap_header,
+                                               M2MObservationHandler *observation_handler,
+                                               bool &execute_value_updated)
+{
+    tr_info("M2MResourceBase::handle_put_request()");
+
+    sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
+    sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl,
+                                                           received_coap_header,
+                                                           msg_code);
+    // process the PUT if we have registered a callback for it
+    if(received_coap_header && coap_response) {
+        uint16_t coap_content_type = 0;
+        if(received_coap_header->content_format != COAP_CT_NONE) {
+            coap_content_type = received_coap_header->content_format;
+        }
+        if(received_coap_header->options_list_ptr &&
+           received_coap_header->options_list_ptr->uri_query_ptr) {
+            char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr,
+                                                    received_coap_header->options_list_ptr->uri_query_len);
+            if (query){
+                tr_info("M2MResourceBase::handle_put_request() - query %s", query);
+
+                // if anything was updated, re-initialize the stored notification attributes
+                if (!handle_observation_attribute(query)){
+                    tr_error("M2MResourceBase::handle_put_request() - Invalid query");
+                    msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
+                }
+                free(query);
+            }
+            else {
+                // memory allocation for query fails
+                tr_error("M2MResourceBase::handle_put_request() - Out of memory !!!");
+                msg_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; // 4.00
+            }
+        } else if ((operation() & SN_GRS_PUT_ALLOWED) != 0) {
+            tr_debug("M2MResourceBase::handle_put_request() - Request Content-type: %d", coap_content_type);
+
+            if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type ||
+               COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type) {
+                msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
+            } else {
+#ifndef DISABLE_BLOCK_MESSAGE
+                if (block_message()) {
+                    block_message()->set_message_info(received_coap_header);
+                    if (block_message()->is_block_message()) {
+                        incoming_block_message_callback* incoming_block_message_cb = (incoming_block_message_callback*)M2MCallbackStorage::get_callback(*this,
+                                                                                M2MCallbackAssociation::M2MResourceInstanceIncomingBlockMessageCallback);
+                        if (incoming_block_message_cb) {
+                            (*incoming_block_message_cb)(_block_message_data);
+                        }
+                        if (block_message()->is_last_block()) {
+                            block_message()->clear_values();
+                            coap_response->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED;
+                        } else {
+                            coap_response->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING;
+                        }
+                        if (block_message()->error_code() != M2MBlockMessage::ErrorNone) {
+                            block_message()->clear_values();
+                        }
+                    }
+                }
+#endif
+                // Firmware object uri path is limited to be max 255 bytes
+                if ((strcmp(uri_path(), FIRMAWARE_PACKAGE_URI_PATH) == 0) &&
+                    received_coap_header->payload_len > 255) {
+                    msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE;
+                } else if ((strcmp(uri_path(), SERVER_LIFETIME_PATH) == 0)) {
+                    // Check that lifetime can't go below 60s
+                    char *query = (char*)alloc_string_copy(received_coap_header->payload_ptr,
+                                                           received_coap_header->payload_len);
+
+                    if (query) {
+                        int32_t lifetime = atol(query);
+                        if (lifetime < MINIMUM_REGISTRATION_TIME) {
+                            tr_error("M2MResourceBase::handle_put_request() - lifetime value % " PRId32 " not acceptable", lifetime);
+                            msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE;
+                        }
+                        free(query);
+                    }
+                    else {
+                        // memory allocation for query fails
+                        tr_error("M2MResourceBase::handle_put_request() - Out of memory !!!");
+                        msg_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
+                    }
+                }
+
+                // Do not update resource value in error case.
+                if ((received_coap_header->payload_ptr) && (msg_code == COAP_MSG_CODE_RESPONSE_CHANGED)) {
+                    execute_value_updated = true;
+                }
+            }
+        } else {
+            // Operation is not allowed.
+            tr_error("M2MResourceBase::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
+            msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+        }
+    } else {
+        msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
+    }
+    if(coap_response) {
+        coap_response->msg_code = msg_code;
+    }
+
+    return coap_response;
+}
+
+
+#ifndef DISABLE_BLOCK_MESSAGE
+
+M2MBlockMessage* M2MResourceBase::block_message() const
+{
+    return _block_message_data;
+}
+
+bool M2MResourceBase::set_incoming_block_message_callback(incoming_block_message_callback callback)
+{
+    incoming_block_message_callback* old_callback = (incoming_block_message_callback*)M2MCallbackStorage::remove_callback(*this,
+                                                        M2MCallbackAssociation::M2MResourceInstanceIncomingBlockMessageCallback);
+    delete old_callback;
+
+    // copy the callback object. This will change on next version to be a direct pointer to a interface class,
+    // this FPn<> is just too heavy for this usage.
+    incoming_block_message_callback* new_callback = new incoming_block_message_callback(callback);
+
+    delete _block_message_data;
+    _block_message_data = NULL;
+    _block_message_data = new M2MBlockMessage();
+
+    return M2MCallbackStorage::add_callback(*this,
+                                            new_callback,
+                                            M2MCallbackAssociation::M2MResourceInstanceIncomingBlockMessageCallback);
+}
+
+bool M2MResourceBase::set_outgoing_block_message_callback(outgoing_block_message_callback callback)
+{
+    outgoing_block_message_callback *old_callback = (outgoing_block_message_callback*)M2MCallbackStorage::remove_callback(*this,
+                                                         M2MCallbackAssociation::M2MResourceInstanceOutgoingBlockMessageCallback);
+    delete old_callback;
+
+    outgoing_block_message_callback *new_callback = new outgoing_block_message_callback(callback);
+    return M2MCallbackStorage::add_callback(*this,
+                                            new_callback,
+                                            M2MCallbackAssociation::M2MResourceInstanceOutgoingBlockMessageCallback);
+}
+#endif
+
+bool M2MResourceBase::set_notification_sent_callback(notification_sent_callback callback)
+{
+    notification_sent_callback *old_callback = (notification_sent_callback*)M2MCallbackStorage::remove_callback(*this,
+                                                         M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback);
+    delete old_callback;
+
+    notification_sent_callback *new_callback = new notification_sent_callback(callback);
+    return M2MCallbackStorage::add_callback(*this,
+                                            new_callback,
+                                            M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback);
+}
+
+bool M2MResourceBase::set_notification_sent_callback(notification_sent_callback_2 callback)
+{
+    M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback2);
+
+    return M2MCallbackStorage::add_callback(*this,
+                                            (void*)callback,
+                                            M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback2);
+}
+
+bool M2MResourceBase::set_notification_status_callback(notification_status_callback callback)
+{
+    notification_status_callback *old_callback = (notification_status_callback*)M2MCallbackStorage::remove_callback(*this,
+                                                         M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback);
+    delete old_callback;
+
+    notification_status_callback *new_callback = new notification_status_callback(callback);
+    return M2MCallbackStorage::add_callback(*this,
+                                            new_callback,
+                                            M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback);
+}
+
+bool M2MResourceBase::set_notification_status_callback(notification_status_callback_2 callback)
+{
+    M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback2);
+
+    return M2MCallbackStorage::add_callback(*this,
+                                            (void*)callback,
+                                            M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback2);
+}
+
+void M2MResourceBase::notification_sent()
+{
+    // Now we will call both callbacks, if they are set. This is different from original behavior.
+    notification_sent_callback* callback =
+            (notification_sent_callback*)M2MCallbackStorage::get_callback(*this,
+                                                                          M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback);
+    if (callback) {
+        (*callback)();
+    }
+
+    notification_sent_callback_2 callback2 =
+            (notification_sent_callback_2)M2MCallbackStorage::get_callback(*this,
+                                                                           M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback2);
+    if (callback2) {
+        (*callback2)();
+    }
+}
+
+void M2MResourceBase::notification_status(const uint16_t msg_id, const NotificationStatus status)
+{
+    if (_notification_status != status) {
+        _notification_status = status;
+        // Now we will call both callbacks, if they are set. This is different from original behavior.
+        notification_status_callback* callback =
+                (notification_status_callback*)M2MCallbackStorage::get_callback(*this,
+                                                                              M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback);
+        if (callback) {
+            (*callback)(msg_id, status);
+        }
+
+        notification_status_callback_2 callback2 =
+                (notification_status_callback_2)M2MCallbackStorage::get_callback(*this,
+                                                                               M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback2);
+        if (callback2) {
+            (*callback2)(msg_id, status);
+        }
+    }
+}
+
+M2MResourceBase::ResourceType M2MResourceBase::convert_data_type(M2MBase::DataType type) const
+{
+    M2MResourceBase::ResourceType res_type = M2MResourceBase::OBJLINK;
+    switch(type) {
+        case M2MBase::STRING:
+            res_type = M2MResourceBase::STRING;
+            break;
+        case M2MBase::INTEGER:
+            res_type = M2MResourceBase::INTEGER;
+            break;
+        case M2MBase::FLOAT:
+            res_type = M2MResourceBase::FLOAT;
+            break;
+        case M2MBase::OPAQUE:
+            res_type = M2MResourceBase::OPAQUE;
+            break;
+        case M2MBase::BOOLEAN:
+            res_type = M2MResourceBase::BOOLEAN;
+            break;
+        case M2MBase::TIME:
+            res_type = M2MResourceBase::TIME;
+            break;
+        case M2MBase::OBJLINK:
+            res_type = M2MResourceBase::OBJLINK;
+            break;
+    }
+    return res_type;
+}
+
+M2MResourceBase::NotificationStatus M2MResourceBase::notification_status() const
+{
+    return _notification_status;
+}
+
+void M2MResourceBase::clear_notification_status()
+{
+    _notification_status = M2MResourceBase::INIT;
+}
+
+void M2MResourceBase::publish_value_in_registration_msg(bool publish_value)
+{
+    M2MBase::lwm2m_parameters_s* param = M2MBase::get_lwm2m_parameters();
+    assert(param->data_type == M2MBase::INTEGER ||
+           param->data_type == M2MBase::STRING ||
+           param->data_type == M2MBase::FLOAT ||
+           param->data_type == M2MBase::BOOLEAN ||
+           param->data_type == M2MBase::OPAQUE);
+
+    uint8_t pub_value = publish_value;
+
+    if (param->data_type == M2MBase::OPAQUE) {
+        pub_value = 2;
+    } else {
+        pub_value = (uint8_t)publish_value;
+    }
+    param->dynamic_resource_params->publish_value = pub_value;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mresourceinstance.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include <stdlib.h>
+#include "mbed-client/m2mresource.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2mobservationhandler.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mobjectinstance.h"
+#include "include/m2mcallbackstorage.h"
+#include "include/m2mreporthandler.h"
+#include "mbed-client/m2mblockmessage.h"
+#include "mbed-trace/mbed_trace.h"
+
+#define TRACE_GROUP "mClt"
+
+M2MResourceInstance::M2MResourceInstance(M2MResource &parent,
+                                         const String &res_name,
+                                         M2MBase::Mode resource_mode,
+                                         const String &resource_type,
+                                         M2MBase::DataType type,
+                                         char* path,
+                                         bool external_blockwise_store,
+                                         bool multiple_instance)
+: M2MResourceBase(res_name,
+          resource_mode,
+          resource_type,
+          type,
+          path,
+          external_blockwise_store,
+          multiple_instance
+          ),
+ _parent_resource(parent)
+{
+    set_base_type(M2MBase::ResourceInstance);
+}
+
+M2MResourceInstance::M2MResourceInstance(M2MResource &parent,
+                                         const String &res_name,
+                                         M2MBase::Mode resource_mode,
+                                         const String &resource_type,
+                                         M2MBase::DataType type,
+                                         const uint8_t *value,
+                                         const uint8_t value_length,
+                                         char* path,
+                                         bool external_blockwise_store,
+                                         bool multiple_instance)
+: M2MResourceBase(res_name,
+          resource_mode,
+          resource_type,
+          type,
+          value,
+          value_length,
+          path,
+          external_blockwise_store,
+          multiple_instance),
+ _parent_resource(parent)
+{
+    set_base_type(M2MBase::ResourceInstance);
+}
+
+M2MResourceInstance::M2MResourceInstance(M2MResource &parent,
+                                         const lwm2m_parameters_s* s,
+                                         M2MBase::DataType type)
+: M2MResourceBase(s, type),
+  _parent_resource(parent)
+{
+
+    assert(base_type() == M2MBase::ResourceInstance);
+}
+
+M2MResourceInstance::~M2MResourceInstance()
+{
+    free_resources();
+}
+
+M2MObservationHandler* M2MResourceInstance::observation_handler() const
+{
+    const M2MResource& parent_resource = get_parent_resource();
+
+    // XXX: need to check the flag too
+    return parent_resource.observation_handler();
+}
+
+void M2MResourceInstance::set_observation_handler(M2MObservationHandler *handler)
+{
+    M2MResource& parent_resource = get_parent_resource();
+
+    // XXX: need to set the flag too
+    parent_resource.set_observation_handler(handler);
+}
+
+bool M2MResourceInstance::handle_observation_attribute(const char *query)
+{
+    tr_debug("M2MResourceInstance::handle_observation_attribute - is_under_observation(%d)", is_under_observation());
+    bool success = false;
+
+    M2MReportHandler *handler = M2MBase::report_handler();
+    if (!handler) {
+        handler = M2MBase::create_report_handler();
+    }
+
+    if (handler) {
+        success = handler->parse_notification_attribute(query,
+                M2MBase::base_type(), resource_instance_type());
+        if(success) {
+            if (is_under_observation()) {
+                handler->set_under_observation(true);
+            }
+        } else {
+            handler->set_default_values();
+        }
+    }
+    return success;
+}
+
+uint16_t M2MResourceInstance::object_instance_id() const
+{
+    const M2MObjectInstance& parent_object_instance = get_parent_resource().get_parent_object_instance();
+    return parent_object_instance.instance_id();
+}
+
+M2MResource& M2MResourceInstance::get_parent_resource() const
+{
+    return _parent_resource;
+}
+
+M2MBase *M2MResourceInstance::get_parent() const
+{
+    return (M2MBase *) &get_parent_resource();
+}
+
+const char* M2MResourceInstance::object_name() const
+{
+    const M2MObjectInstance& parent_object_instance = _parent_resource.get_parent_object_instance();
+    const M2MObject& parent_object = parent_object_instance.get_parent_object();
+
+    return parent_object.name();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2msecurity.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "mbed-client/m2msecurity.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mobjectinstance.h"
+#include "mbed-client/m2mresource.h"
+#include "mbed-client/m2mstring.h"
+#include "mbed-trace/mbed_trace.h"
+
+#include <stdlib.h>
+
+#define TRACE_GROUP "mClt"
+
+#define BUFFER_SIZE 21
+
+// Default instance id's that server uses
+#define DEFAULT_M2M_INSTANCE       0
+#define DEFAULT_BOOTSTRAP_INSTANCE 1
+
+M2MSecurity* M2MSecurity::_instance = NULL;
+
+M2MSecurity* M2MSecurity::get_instance()
+{
+    if (_instance == NULL) {
+        _instance = new M2MSecurity(M2MServer);
+    }
+    return _instance;
+}
+
+void M2MSecurity::delete_instance()
+{
+    delete _instance;
+    _instance = NULL;
+}
+
+
+M2MSecurity::M2MSecurity(ServerType ser_type)
+: M2MObject(M2M_SECURITY_ID, stringdup(M2M_SECURITY_ID))
+{
+}
+
+M2MSecurity::~M2MSecurity()
+{
+}
+
+M2MObjectInstance* M2MSecurity::create_object_instance(ServerType server_type)
+{
+    uint16_t instance_id = DEFAULT_M2M_INSTANCE;
+    if (server_type == Bootstrap) {
+        instance_id = DEFAULT_BOOTSTRAP_INSTANCE;
+    }
+
+    M2MObjectInstance *server_instance = M2MObject::object_instance(instance_id);
+    if (server_instance != NULL) {
+        // Instance already exists, return NULL
+        return NULL;
+    }
+
+    server_instance = M2MObject::create_object_instance(instance_id);
+    if (server_instance) {
+        M2MResource* res = server_instance->create_dynamic_resource(SECURITY_M2M_SERVER_URI,
+                                                                     OMA_RESOURCE_TYPE,
+                                                                     M2MResourceInstance::STRING,
+                                                                     false);
+        if (res) {
+            res->set_operation(M2MBase::NOT_ALLOWED);
+        }
+        res = server_instance->create_dynamic_resource(SECURITY_BOOTSTRAP_SERVER,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::BOOLEAN,
+                                                        false);
+        if (res) {
+            res->set_operation(M2MBase::NOT_ALLOWED);
+            res->set_value((int)server_type);
+        }
+        res = server_instance->create_dynamic_resource(SECURITY_SECURITY_MODE,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::INTEGER,
+                                                        false);
+        if (res) {
+            res->set_operation(M2MBase::NOT_ALLOWED);
+        }
+        res = server_instance->create_dynamic_resource(SECURITY_PUBLIC_KEY,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::OPAQUE,
+                                                        false);
+        if (res) {
+            res->set_operation(M2MBase::NOT_ALLOWED);
+        }
+        res = server_instance->create_dynamic_resource(SECURITY_SERVER_PUBLIC_KEY,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::OPAQUE,
+                                                        false);
+        if (res) {
+            res->set_operation(M2MBase::NOT_ALLOWED);
+        }
+        res = server_instance->create_dynamic_resource(SECURITY_SECRET_KEY,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::OPAQUE,
+                                                        false);
+        if (res) {
+            res->set_operation(M2MBase::NOT_ALLOWED);
+        }
+
+        res = server_instance->create_dynamic_resource(SECURITY_OPEN_CERTIFICATE_CHAIN,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::OPAQUE,
+                                                        false);
+        if (res) {
+            res->set_operation(M2MBase::NOT_ALLOWED);
+        }
+
+        res = server_instance->create_dynamic_resource(SECURITY_CLOSE_CERTIFICATE_CHAIN,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::OPAQUE,
+                                                        false);
+        if (res) {
+            res->set_operation(M2MBase::NOT_ALLOWED);
+        }
+
+        res = server_instance->create_dynamic_resource(SECURITY_READ_CERTIFICATE_CHAIN,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::OPAQUE,
+                                                        false);
+        if (res) {
+            res->set_operation(M2MBase::NOT_ALLOWED);
+        }
+
+        if (M2MSecurity::M2MServer == server_type) {
+            res = server_instance->create_dynamic_resource(SECURITY_SHORT_SERVER_ID,
+                                                            OMA_RESOURCE_TYPE,
+                                                            M2MResourceInstance::INTEGER,
+                                                            false);
+            if (res) {
+                res->set_operation(M2MBase::NOT_ALLOWED);
+            }
+        }
+    }
+    return server_instance;
+}
+
+void M2MSecurity::remove_security_instances()
+{
+    int32_t instance_id = _instance->get_security_instance_id(M2MSecurity::Bootstrap);
+    if (instance_id >= 0) {
+        _instance->remove_object_instance(instance_id);
+    }
+    instance_id = _instance->get_security_instance_id(M2MSecurity::M2MServer);
+    if (instance_id >= 0) {
+        _instance->remove_object_instance(instance_id);
+    }
+}
+
+M2MResource* M2MSecurity::create_resource(SecurityResource resource, uint32_t value, uint16_t instance_id)
+{
+    M2MResource* res = NULL;
+    M2MObjectInstance *server_instance = M2MObject::object_instance(instance_id);
+    if (server_instance == NULL) {
+        return NULL;
+    }
+
+    const char* security_id_ptr = "";
+    if (!is_resource_present(resource, instance_id)) {
+        switch(resource) {
+            case SMSSecurityMode:
+               security_id_ptr = SECURITY_SMS_SECURITY_MODE;
+               break;
+            case M2MServerSMSNumber:
+                security_id_ptr = SECURITY_M2M_SERVER_SMS_NUMBER;
+                break;
+            case ShortServerID:
+                security_id_ptr = SECURITY_SHORT_SERVER_ID;
+                break;
+            case ClientHoldOffTime:
+                security_id_ptr = SECURITY_CLIENT_HOLD_OFF_TIME;
+                break;
+            default:
+                break;
+        }
+    }
+
+    const String security_id(security_id_ptr);
+
+    if (!security_id.empty()) {
+        if (server_instance) {
+            res = server_instance->create_dynamic_resource(security_id,OMA_RESOURCE_TYPE,
+                                                            M2MResourceInstance::INTEGER,
+                                                            false);
+
+            if (res) {
+                res->set_operation(M2MBase::NOT_ALLOWED);
+                res->set_value(value);
+            }
+        }
+    }
+    return res;
+}
+
+bool M2MSecurity::delete_resource(SecurityResource resource, uint16_t instance_id)
+{
+    bool success = false;
+    const char* security_id_ptr;
+    M2MObjectInstance *server_instance = M2MObject::object_instance(instance_id);
+    if (server_instance == NULL) {
+        return NULL;
+    }
+    switch(resource) {
+        case SMSSecurityMode:
+           security_id_ptr = SECURITY_SMS_SECURITY_MODE;
+           break;
+        case M2MServerSMSNumber:
+            security_id_ptr = SECURITY_M2M_SERVER_SMS_NUMBER;
+            break;
+        case ShortServerID:
+            if (M2MSecurity::Bootstrap == server_type(instance_id)) {
+                security_id_ptr = SECURITY_SHORT_SERVER_ID;
+            } else {
+                security_id_ptr = NULL;
+            }
+            break;
+        case ClientHoldOffTime:
+            security_id_ptr = SECURITY_CLIENT_HOLD_OFF_TIME;
+            break;
+        default:
+            // Others are mandatory resources hence cannot be deleted.
+            security_id_ptr = NULL;
+            break;
+    }
+
+    if (security_id_ptr) {
+        if (server_instance) {
+            success = server_instance->remove_resource(security_id_ptr);
+        }
+    }
+    return success;
+}
+
+bool M2MSecurity::set_resource_value(SecurityResource resource,
+                                     const String &value,
+                                     uint16_t instance_id)
+{
+    bool success = false;
+    if (M2MSecurity::M2MServerUri == resource) {
+        M2MResource* res = get_resource(resource, instance_id);
+        if (res) {
+            success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length());
+        }
+    }
+    return success;
+}
+
+bool M2MSecurity::set_resource_value(SecurityResource resource,
+                                     uint32_t value,
+                                     uint16_t instance_id)
+{
+    bool success = false;
+    M2MResource* res = get_resource(resource, instance_id);
+    if (res) {
+        if (M2MSecurity::SecurityMode == resource        ||
+           M2MSecurity::SMSSecurityMode == resource     ||
+           M2MSecurity::M2MServerSMSNumber == resource  ||
+           M2MSecurity::ShortServerID == resource       ||
+           M2MSecurity::BootstrapServer == resource     ||
+           M2MSecurity::ClientHoldOffTime == resource) {
+            success = res->set_value(value);
+
+        }
+    }
+    return success;
+}
+
+bool M2MSecurity::set_resource_value(SecurityResource resource,
+                                     const uint8_t *value,
+                                     const uint16_t length,
+                                     uint16_t instance_id)
+{
+    bool success = false;
+    M2MResource* res = get_resource(resource, instance_id);
+    if (res) {
+        if (M2MSecurity::PublicKey == resource           ||
+           M2MSecurity::ServerPublicKey == resource     ||
+           M2MSecurity::Secretkey == resource           ||
+           M2MSecurity::M2MServerUri == resource) {
+            success = res->set_value(value,length);
+        }
+    }
+    return success;
+}
+
+String M2MSecurity::resource_value_string(SecurityResource resource, uint16_t instance_id) const
+{
+    String value = "";
+    M2MResource* res = get_resource(resource, instance_id);
+    if (res) {
+        if (M2MSecurity::M2MServerUri == resource) {
+            value = res->get_value_string();
+        }
+    }
+    return value;
+}
+
+int M2MSecurity::resource_value_buffer(SecurityResource resource,
+                                            uint8_t *&data,
+                                            uint16_t instance_id,
+                                            size_t *buffer_len) const
+{
+    M2MResource* res = get_resource(resource, instance_id);
+    if (res) {
+        if (M2MSecurity::PublicKey == resource        ||
+            M2MSecurity::ServerPublicKey == resource  ||
+            M2MSecurity::Secretkey == resource ||
+            M2MSecurity::OpenCertificateChain == resource ||
+            M2MSecurity::CloseCertificateChain == resource ||
+            M2MSecurity::ReadDeviceCertificateChain == resource) {
+            return res->read_resource_value(*(M2MResourceBase *)res, data, buffer_len);
+        }
+    }
+
+    return -1;
+}
+
+uint32_t M2MSecurity::resource_value_buffer(SecurityResource resource,
+                                            const uint8_t *&data,
+                                            uint16_t instance_id) const
+{
+    uint32_t size = 0;
+    M2MResource* res = get_resource(resource, instance_id);
+    if (res) {
+        if (M2MSecurity::PublicKey == resource        ||
+            M2MSecurity::ServerPublicKey == resource  ||
+            M2MSecurity::Secretkey == resource) {
+            data = res->value();
+            size = res->value_length();
+        }
+    }
+    return size;
+}
+
+
+uint32_t M2MSecurity::resource_value_int(SecurityResource resource, uint16_t instance_id) const
+{
+    uint32_t value = 0;
+    M2MResource* res = get_resource(resource, instance_id);
+    if (res) {
+        if (M2MSecurity::SecurityMode == resource        ||
+           M2MSecurity::SMSSecurityMode == resource     ||
+           M2MSecurity::M2MServerSMSNumber == resource  ||
+           M2MSecurity::ShortServerID == resource       ||
+           M2MSecurity::BootstrapServer == resource     ||
+           M2MSecurity::ClientHoldOffTime == resource) {
+            // note: the value may be 32bit int on 32b archs.
+            value = res->get_value_int();
+        }
+    }
+    return value;
+}
+
+bool M2MSecurity::is_resource_present(SecurityResource resource, uint16_t instance_id) const
+{
+    bool success = false;
+    M2MResource *res = get_resource(resource, instance_id);
+    if (res) {
+        success = true;
+    }
+    return success;
+}
+
+uint16_t M2MSecurity::total_resource_count(uint16_t instance_id) const
+{
+    uint16_t count = 0;
+    M2MObjectInstance *server_instance = M2MObject::object_instance(instance_id);
+    if (server_instance) {
+        count = server_instance->resources().size();
+    }
+    return count;
+}
+
+M2MSecurity::ServerType M2MSecurity::server_type(uint16_t instance_id) const
+{
+    uint32_t sec_mode = resource_value_int(M2MSecurity::BootstrapServer, instance_id);
+    M2MSecurity::ServerType type = M2MSecurity::M2MServer;
+    if (sec_mode == 1) {
+        type = M2MSecurity::Bootstrap;
+    }
+    return type;
+}
+
+M2MResource* M2MSecurity::get_resource(SecurityResource res, uint16_t instance_id) const
+{
+    M2MResource* res_object = NULL;
+    M2MObjectInstance *server_instance = M2MObject::object_instance(instance_id);
+    if (server_instance == NULL) {
+        return NULL;
+    }
+
+    if (server_instance) {
+        const char* res_name_ptr = NULL;
+        switch(res) {
+            case M2MServerUri:
+                res_name_ptr = SECURITY_M2M_SERVER_URI;
+                break;
+            case BootstrapServer:
+                res_name_ptr = SECURITY_BOOTSTRAP_SERVER;
+                break;
+            case SecurityMode:
+                res_name_ptr = SECURITY_SECURITY_MODE;
+                break;
+            case PublicKey:
+                res_name_ptr = SECURITY_PUBLIC_KEY;
+                break;
+            case ServerPublicKey:
+                res_name_ptr = SECURITY_SERVER_PUBLIC_KEY;
+                break;
+            case Secretkey:
+                res_name_ptr = SECURITY_SECRET_KEY;
+                break;
+            case SMSSecurityMode:
+                res_name_ptr = SECURITY_SMS_SECURITY_MODE;
+                break;
+            case SMSBindingKey:
+                res_name_ptr = SECURITY_SMS_BINDING_KEY;
+                break;
+            case SMSBindingSecretKey:
+                res_name_ptr = SECURITY_SMS_BINDING_SECRET_KEY;
+                break;
+            case M2MServerSMSNumber:
+                res_name_ptr = SECURITY_M2M_SERVER_SMS_NUMBER;
+                break;
+            case ShortServerID:
+                res_name_ptr = SECURITY_SHORT_SERVER_ID;
+                break;
+            case ClientHoldOffTime:
+                res_name_ptr = SECURITY_CLIENT_HOLD_OFF_TIME;
+                break;
+            case OpenCertificateChain:
+                res_name_ptr = SECURITY_OPEN_CERTIFICATE_CHAIN;
+                break;
+            case CloseCertificateChain:
+                res_name_ptr = SECURITY_CLOSE_CERTIFICATE_CHAIN;
+                break;
+            case ReadDeviceCertificateChain:
+                res_name_ptr = SECURITY_READ_CERTIFICATE_CHAIN;
+                break;
+        }
+
+        if (res_name_ptr) {
+            res_object = server_instance->resource(res_name_ptr);
+        }
+    }
+    return res_object;
+}
+
+void M2MSecurity::clear_resources(uint16_t instance_id)
+{
+    for(int i = 0; i <= M2MSecurity::ClientHoldOffTime; i++) {
+        M2MResource *res = get_resource((SecurityResource) i, instance_id);
+        if (res) {
+            res->clear_value();
+        }
+    }
+}
+
+int32_t M2MSecurity::get_security_instance_id(ServerType ser_type) const
+{
+    int32_t instance_id = -1;
+
+    const M2MObjectInstanceList &insts = instances();
+
+    if (!insts.empty()) {
+        M2MObjectInstanceList::const_iterator it;
+        it = insts.begin();
+        for ( ; it != insts.end(); it++ ) {
+            uint16_t id = (*it)->instance_id();
+            if (server_type(id) == ser_type) {
+                instance_id = id;
+                break;
+            }
+        }
+    }
+    return instance_id;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mserver.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#include "mbed-client/m2mserver.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mobjectinstance.h"
+#include "mbed-client/m2mresource.h"
+#include "mbed-client/m2mstring.h"
+
+#define TRACE_GROUP "mClt"
+
+#define BUFFER_SIZE 21
+
+M2MServer::M2MServer()
+: M2MObject(M2M_SERVER_ID, stringdup(M2M_SERVER_ID))
+{
+    M2MObject::create_object_instance();
+
+    _server_instance = object_instance();
+
+    if(_server_instance) {
+
+        M2MResource* res = _server_instance->create_dynamic_resource(SERVER_SHORT_SERVER_ID,
+                                                                     OMA_RESOURCE_TYPE,
+                                                                     M2MResourceInstance::INTEGER,
+                                                                     true);
+        if(res) {
+            res->set_operation(M2MBase::GET_PUT_ALLOWED);
+        }
+        res = _server_instance->create_dynamic_resource(SERVER_LIFETIME,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::INTEGER,
+                                                        true);
+        if(res) {
+            res->set_operation(M2MBase::GET_PUT_POST_ALLOWED);
+        }
+        res = _server_instance->create_dynamic_resource(SERVER_NOTIFICATION_STORAGE,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::BOOLEAN,
+                                                        true);
+        if(res) {
+            res->set_operation(M2MBase::GET_PUT_POST_ALLOWED);
+        }
+        res = _server_instance->create_dynamic_resource(SERVER_BINDING,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::STRING,
+                                                        true);
+        if(res) {
+            res->set_operation(M2MBase::GET_PUT_POST_ALLOWED);
+        }
+        res = _server_instance->create_dynamic_resource(SERVER_REGISTRATION_UPDATE,
+                                                        OMA_RESOURCE_TYPE,
+                                                        M2MResourceInstance::OPAQUE,
+                                                        false);
+        if(res) {
+          res->set_operation(M2MBase::POST_ALLOWED);
+        }
+    }
+}
+
+M2MServer::~M2MServer()
+{
+
+}
+
+M2MResource* M2MServer::create_resource(ServerResource resource, uint32_t value)
+{
+    M2MResource* res = NULL;
+    const char* server_id_ptr = "";
+    if(!is_resource_present(resource)) {
+        switch(resource) {
+        case DefaultMinPeriod:
+            server_id_ptr = SERVER_DEFAULT_MIN_PERIOD;
+            break;
+        case DefaultMaxPeriod:
+            server_id_ptr = SERVER_DEFAULT_MAX_PERIOD;
+            break;
+        case DisableTimeout:
+            server_id_ptr = SERVER_DISABLE_TIMEOUT;
+            break;
+        default:
+            break;
+        }
+    }
+    String server_id(server_id_ptr);
+    
+    if(!server_id.empty()) {
+        if(_server_instance) {
+            res = _server_instance->create_dynamic_resource(server_id,
+                                                            OMA_RESOURCE_TYPE,
+                                                            M2MResourceInstance::INTEGER,
+                                                            true);
+            if(res) {
+                res->set_operation(M2MBase::GET_PUT_POST_ALLOWED);
+                
+                res->set_value(value);
+            }
+        }
+    }
+    return res;
+}
+
+M2MResource* M2MServer::create_resource(ServerResource resource)
+{
+    M2MResource* res = NULL;
+    if(!is_resource_present(resource)) {
+        if(M2MServer::Disable == resource) {
+                if(_server_instance) {
+                    res = _server_instance->create_dynamic_resource(SERVER_DISABLE,
+                                                                    OMA_RESOURCE_TYPE,
+                                                                    M2MResourceInstance::OPAQUE,
+                                                                    false);
+                if(res) {
+                    res->set_operation(M2MBase::POST_ALLOWED);
+                }
+            }
+        }
+    }
+    return res;
+}
+
+bool M2MServer::delete_resource(ServerResource resource)
+{
+    bool success = false;
+    const char* server_id_ptr;
+    switch(resource) {
+        case DefaultMinPeriod:
+           server_id_ptr = SERVER_DEFAULT_MIN_PERIOD;
+           break;
+        case DefaultMaxPeriod:
+            server_id_ptr = SERVER_DEFAULT_MAX_PERIOD;
+            break;
+        case Disable:
+            server_id_ptr = SERVER_DISABLE;
+            break;
+        case DisableTimeout:
+            server_id_ptr = SERVER_DISABLE_TIMEOUT;
+            break;
+        default:
+            server_id_ptr = NULL;
+            break;
+    }
+
+    if(server_id_ptr) {
+        if(_server_instance) {
+            success = _server_instance->remove_resource(server_id_ptr);
+        }
+    }
+    return success;
+}
+
+bool M2MServer::set_resource_value(ServerResource resource,
+                                   const String &value)
+{
+    bool success = false;
+    M2MResource* res = get_resource(resource);
+    if(res && (M2MServer::Binding == resource)) {
+        success = res->set_value((const uint8_t*)value.c_str(),(uint32_t)value.length());
+    }
+    return success;
+}
+
+bool M2MServer::set_resource_value(ServerResource resource,
+                                   uint32_t value)
+{
+    bool success = false;
+    M2MResource* res = get_resource(resource);
+    if(res) {
+        if(M2MServer::ShortServerID == resource     ||
+           M2MServer::Lifetime == resource          ||
+           M2MServer::DefaultMinPeriod == resource  ||
+           M2MServer::DefaultMaxPeriod == resource  ||
+           M2MServer::DisableTimeout == resource    ||
+           M2MServer::NotificationStorage == resource) {
+            // If it is any of the above resource
+            // set the value of the resource.
+
+            success = res->set_value(value);
+        }
+    }
+    return success;
+}
+
+String M2MServer::resource_value_string(ServerResource resource) const
+{
+    String value = "";
+    M2MResource* res = get_resource(resource);
+    if(res && (M2MServer::Binding == resource)) {
+
+        value = res->get_value_string();
+    }
+    return value;
+}
+
+
+uint32_t M2MServer::resource_value_int(ServerResource resource) const
+{
+    uint32_t value = 0;
+    M2MResource* res = get_resource(resource);
+    if(res) {
+        if(M2MServer::ShortServerID == resource     ||
+           M2MServer::Lifetime == resource          ||
+           M2MServer::DefaultMinPeriod == resource  ||
+           M2MServer::DefaultMaxPeriod == resource  ||
+           M2MServer::DisableTimeout == resource    ||
+           M2MServer::NotificationStorage == resource) {
+
+            value = res->get_value_int();
+        }
+    }
+    return value;
+}
+
+bool M2MServer::is_resource_present(ServerResource resource) const
+{
+    bool success = false;
+    M2MResource *res = get_resource(resource);
+    if(res) {
+        success = true;
+    }
+    return success;
+}
+
+uint16_t M2MServer::total_resource_count() const
+{
+    uint16_t total_count = 0;
+    if(_server_instance) {
+    total_count = _server_instance->resources().size();
+    }
+    return total_count;
+}
+
+M2MResource* M2MServer::get_resource(ServerResource res) const
+{
+    M2MResource* res_object = NULL;
+    const char* res_name_ptr = NULL;
+    switch(res) {
+    case ShortServerID:
+        res_name_ptr = SERVER_SHORT_SERVER_ID;
+        break;
+    case Lifetime:
+        res_name_ptr = SERVER_LIFETIME;
+        break;
+    case DefaultMinPeriod:
+        res_name_ptr = SERVER_DEFAULT_MIN_PERIOD;
+        break;
+    case DefaultMaxPeriod:
+        res_name_ptr = SERVER_DEFAULT_MAX_PERIOD;
+        break;
+    case Disable:
+        res_name_ptr = SERVER_DISABLE;
+        break;
+    case DisableTimeout:
+        res_name_ptr = SERVER_DISABLE_TIMEOUT;
+        break;
+    case NotificationStorage:
+        res_name_ptr = SERVER_NOTIFICATION_STORAGE;
+        break;
+    case Binding:
+        res_name_ptr = SERVER_BINDING;
+        break;
+    case RegistrationUpdate:
+        res_name_ptr = SERVER_REGISTRATION_UPDATE;
+        break;
+    }
+
+    if(res_name_ptr) {
+        if(_server_instance) {
+            res_object = _server_instance->resource(res_name_ptr);
+        }
+    }
+    return res_object;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mstring.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "mbed-client/m2mstring.h"
+#include <string.h> // strlen
+#include <stdlib.h> // malloc, realloc
+#include <assert.h>
+#include <algorithm> // min
+
+namespace m2m {
+
+const String::size_type String::npos = static_cast<size_t>(-1);
+
+char* String::strdup(const char* s)
+{
+    const size_t len = strlen(s)+1;
+    char *p2 = static_cast<char*>(malloc(len));
+    if (p2) {
+        memcpy(p2, s, len);
+        allocated_ = len;
+        size_ = len-1;
+    }
+    return p2;
+}
+
+String::String()
+    : p( strdup("") )
+{
+}
+
+String::~String()
+{
+    free(p);
+    p = 0;
+}
+
+String::String(const String& s)
+    : p(0)
+{
+    p = static_cast<char*>(malloc(s.size_ + 1));
+
+    allocated_ = s.size_ + 1;
+    size_      = s.size_;
+    memcpy(p, s.p, size_ + 1);
+}
+
+String::String(const char* s)
+    : p(strdup(s))
+{
+}
+
+String::String(const char* str, size_t n)
+{
+    p = static_cast<char*>(malloc(n + 1));
+
+    allocated_ = n + 1;
+    size_      = n;
+    memcpy(p, str, n);
+    p[n] = 0;
+}
+
+String& String::operator=(const char* s)
+{
+    if ( p != s ) {
+        // s could point into our own string, so we have to allocate a new string
+        const size_t len = strlen(s);
+        char* copy = (char*) malloc( len + 1);
+        memmove(copy, s, len+1); // trailing 0
+        free( p );
+        p = copy;
+        size_ = len;
+        allocated_ = len+1;
+    }
+    return *this;
+}
+
+String& String::operator=(const String& s)
+{
+    return operator=(s.p);
+}
+
+String& String::operator+=(const String& s)
+{
+    if (s.size_ > 0) {
+        this->reserve(size_ + s.size_);
+        memmove(p+size_, s.p, s.size_+1); // trailing 0
+        size_ += s.size_;
+    }
+    return *this;
+}
+
+// since p and s may overlap, we have to copy our own string first
+String& String::operator+=(const char* s)
+{
+    const size_type lens = strlen(s);
+    if (lens > 0) {
+        if (size_ + lens + 1 <= allocated_) {
+            memmove(p+size_, s, lens+1); // trailing 0
+            size_ += lens;
+        } else {
+            String s2( *this );  // copy own data
+            s2.reserve(size_ + lens);
+            memmove(s2.p+size_, s, lens+1); // trailing 0
+            s2.size_ = size_ + lens;
+            this->swap( s2 );
+        }
+    }
+    return *this;
+}
+
+String& String::operator+=(const char c)
+{
+    push_back(c);
+    return *this;
+}
+
+void String::push_back(const char c) {
+
+    if (size_ == allocated_ - 1) {
+        size_t more =  (allocated_* 3) / 2; // factor 1.5
+        if ( more < 4 ) more = 4;
+        reserve( size_ + more );
+    }
+
+    p[size_] = c;
+    size_++;
+    p[size_] = 0;
+}
+
+bool String::operator==(const char* s) const
+{
+    if( s == NULL ) {
+        if( p == NULL ) {
+            return true;
+        }
+        return false;
+    }
+    bool ret = strcmp(p, s);
+    return !ret;
+}
+
+bool String::operator==(const String& s) const
+{
+    bool ret = strcmp(p, s.p);
+    return !ret;
+}
+
+void String::clear()
+{
+    size_ = 0;
+    p[0]  = 0;
+}
+
+String String::substr(const size_type pos, size_type length) const
+{
+    String s;
+    const size_type len = size_;
+
+    if ( pos <= len ) {
+
+        size_type remain = len - pos;
+
+        if ( length > remain )
+            length = remain;
+
+        s.reserve( length );
+
+        memcpy(s.p, p + pos, length);
+        s.p[length] = '\0';
+        s.size_ = length;
+    }
+    return s;
+}
+
+
+// checked access, accessing the NUL at end is allowed
+char String::at(const size_type i) const
+{
+    if ( i <= strlen(p) ) {
+        return p[i];
+    } else {
+        return '\0';
+    }
+}
+
+String& String::erase(size_type pos, size_type len)
+{
+    if (len > 0) {
+
+        if ( pos < size_ ) { // user must not remove trailing 0
+
+            size_type s2 = size_;
+            size_type remain = s2 - pos - len;
+
+            if (remain > 0) {
+                // erase by overwriting
+                memmove(p + pos, p + pos + len, remain);
+            }
+
+            //if ( remain < 0 ) remain = 0;
+
+            // remove unused space
+            this->resize( pos+remain );
+
+        }
+    }
+    return *this;
+}
+
+String& String::append( const char* str, size_type n) {
+    if (str && n > 0) {
+        size_t lens = strlen(str);
+        if (n > lens)
+            n = lens;
+        size_t newlen = size_ + n;
+        this->reserve( newlen );
+        memmove(p+size_, str, n); // p and s.p MAY overlap
+        p[newlen] = 0; // add NUL termination
+        size_ = newlen;
+    }
+    return *this;
+}
+
+String& String::append_raw( const char* str, size_type n) {
+    if (str && n > 0) {
+        size_t newlen = size_ + n;
+        this->reserve( newlen );
+        memmove(p+size_, str, n); // p and s.p MAY overlap
+        p[newlen] = 0; // add NUL termination
+        size_ = newlen;
+    }
+    return *this;
+}
+
+void String::append_int(int param) {
+
+    // max len of "-9223372036854775808" plus zero termination
+    char conv_buff[20+1];
+
+    int len = itoa_c(param, conv_buff);
+    append_raw(conv_buff, len);
+}
+
+int String::compare( size_type pos, size_type len, const String& str ) const {
+    int r = -1;
+    if (pos <= size_) {
+        if ( len > size_ - pos)
+            len = size_ - pos; // limit len to available length
+
+        const size_type osize = str.size();
+        const size_type len2   = std::min(len, osize);
+        r = strncmp( p + pos, str.p, len2);
+        if (r==0) // equal so far, now compare sizes
+            r = len < osize ? -1 : ( len == osize ? 0 : +1 );
+    }
+    return r;
+}
+
+int String::compare( size_type pos, size_type len, const char* str ) const {
+    int r = -1;
+    if (pos <= size_) {
+
+        if ( len > size_ - pos)
+            len = size_ - pos; // limit len to available length
+
+        const size_type osize = strlen(str);
+        const size_type len2   = std::min(len, osize);
+        r = strncmp( p + pos, str, len2);
+        if (r==0) // equal so far, now compare sizes
+            r = len < osize ? -1 : ( len == osize ? 0 : +1 );
+    }
+    return r;
+}
+
+int String::find_last_of(char c) const {
+    int r = -1;
+    char *v;
+    v = strrchr(p,c);
+    if (v != NULL) {
+        r = 0;
+        char* i = p;
+        while (v != i) {
+            i++;
+            r++;
+        }
+    }
+    return r;
+}
+
+void String::new_realloc( size_type n) {
+    if (n > 0 ) {
+        char* pnew = static_cast<char*>(realloc(p, n)); // could return NULL
+        if (pnew)
+            p = pnew;
+    }
+}
+
+void String::reserve( const size_type n) {
+    if (n >= allocated_ ) {
+        this->new_realloc(n + 1);
+        allocated_ = n + 1;
+    }
+}
+
+void String::resize( const size_type n) {
+    this->resize( n, 0 );
+}
+
+void String::resize( const size_type n, const char c) {
+    if (n < size_ ) {
+        p[n] = 0;
+        size_ = n;
+    }
+    else if (n >  size_ ) {
+        this->reserve( n );
+        for (size_type i=size_; i < n; ++i )
+            p[i] = c;
+        p[n] = 0;
+        size_ = n;
+    }
+}
+
+void String::swap( String& s ) {
+    std::swap( allocated_, s.allocated_ );
+    std::swap( size_,      s.size_      );
+    std::swap( p,          s.p          );
+}
+
+
+// Comparison
+bool operator<( const String& s1, const String& s2 ) {
+    return strcmp( s1.c_str(), s2.c_str() ) < 0;
+}
+
+void reverse(char s[], uint32_t length)
+{
+    uint32_t i, j;
+    char c;
+
+    for (i = 0, j = length-1; i<j; i++, j--) {
+        c = s[i];
+        s[i] = s[j];
+        s[j] = c;
+    }
+}
+
+uint32_t itoa_c (int64_t n, char s[])
+{
+    int64_t sign;
+    uint32_t i;
+
+    if ((sign = n) < 0)
+        n = -n;
+
+    i = 0;
+
+    do {
+        s[i++] = n % 10 + '0';
+    }
+    while ((n /= 10) > 0);
+
+    if (sign < 0)
+        s[i++] = '-';
+
+    s[i] = '\0';
+
+    m2m::reverse(s, i);
+    return i;
+}
+
+uint8_t* String::convert_integer_to_array(int64_t value, uint8_t &size, const uint8_t *array, const uint32_t array_size)
+{
+    uint8_t* buffer = NULL;
+    size = 0;
+    if (array) {
+        value = String::convert_array_to_integer(array, array_size);
+    }
+
+    if(value < 0xFF) {
+        size = 1;
+    } else if(value < 0xFFFF) {
+        size = 2;
+    } else if(value < 0xFFFFFF) {
+        size = 3;
+    } else if(value < 0xFFFFFFFF) {
+        size = 4;
+    } else if(value < 0xFFFFFFFFFF) {
+        size = 5;
+    } else if(value < 0xFFFFFFFFFFFF) {
+        size = 6;
+    } else if(value < 0xFFFFFFFFFFFFFF) {
+        size = 7;
+    } else {
+        size = 8;
+    }
+
+    buffer = (uint8_t*)malloc(size);
+    if (buffer) {
+        for (int i = 0; i < size; i++) {
+            buffer[i] = (value >> ((size - i - 1) * 8));
+        }
+    } else {
+        size = 0;
+    }
+    return buffer;
+}
+
+int64_t String::convert_array_to_integer(const uint8_t *value, const uint32_t size)
+{
+    int64_t temp_64 = 0;
+    for (int i = size - 1; i >= 0; i--) {
+        temp_64 += (uint64_t)(*value++) << i * 8;
+    }
+    return temp_64;
+}
+
+} // namespace
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mstringbufferbase.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#include "mbed-client/m2mstringbufferbase.h"
+
+#include "mbed-client/m2mstring.h"
+
+#include <assert.h>
+#include <string.h>
+
+
+bool StringBufferBase::ensure_space(size_t max_size, size_t required_size) const
+{
+    const size_t space_left = max_size - _curr_size;
+
+    bool space_available = false;
+
+    if (required_size <= space_left) {
+
+        space_available = true;
+    }
+    return space_available;
+}
+
+bool StringBufferBase::append(char *buff, size_t max_size, char data)
+{
+    bool space_available = ensure_space(max_size, 1 + 1); // there must be space for trailing zero too
+    if (space_available) {
+        buff[_curr_size++] = data;
+        buff[_curr_size] = '\0';
+        assert(_curr_size < max_size);
+    }
+    return space_available;
+}
+
+bool StringBufferBase::append(char *buff, size_t max_size, const char *data)
+{
+
+    const size_t string_len = strlen(data);
+    bool space_available = ensure_space(max_size, string_len + 1);
+    if (space_available) {
+        memcpy(buff + _curr_size, data, string_len + 1); // copy the zero terminator too
+        _curr_size += string_len;
+        assert(_curr_size < max_size);
+    }
+    return space_available;
+}
+
+bool StringBufferBase::append(char *buff, size_t max_size, const char *data, size_t data_len)
+{
+    bool space_available = true;
+    if (data_len > 0) {
+        space_available = ensure_space(max_size, data_len + 1);
+        if (space_available) {
+            memcpy(buff + _curr_size, data, data_len);
+            _curr_size += data_len;
+            // Todo: should the code actually check, if the data already contained zero or not?
+            buff[_curr_size] = '\0';
+            assert(_curr_size < max_size);
+        }
+    }
+    return space_available;
+}
+
+bool StringBufferBase::append_int(char *buff, size_t max_size, uint16_t data)
+{
+    // max len of "-9223372036854775808" plus zero termination
+    char conv_buff[20+1];
+
+    // re-use the String's functionality, a more optimal version would use snprintf() or int size specific converter
+    unsigned int len = m2m::itoa_c(data, conv_buff);
+
+    return append(buff, max_size, conv_buff, len);
+}
+
+int StringBufferBase::find_last_of(const char *buff, char search_char) const
+{
+    int last_index = -1;
+    // search from the end of string, return upon first found matching char
+    for (int index = (int)_curr_size; index >= 0; index--) {
+        if (buff[index] == search_char) {
+            last_index = index;
+            break;
+        }
+    }
+
+    return last_index;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mtlvdeserializer.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+// Needed for PRIu64 on FreeRTOS
+#include <stdio.h>
+// Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+
+// Note: this macro is needed on armcc to get the the PRI*32 macros
+// from inttypes.h in a C++ code.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include "include/m2mtlvdeserializer.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-trace/mbed_trace.h"
+#include "common_functions.h"
+
+#define TRACE_GROUP "mClt"
+#define BUFFER_SIZE 10
+
+bool M2MTLVDeserializer::is_object_instance(const uint8_t *tlv)
+{
+    return is_object_instance(tlv, 0);
+}
+
+bool M2MTLVDeserializer::is_resource(const uint8_t *tlv)
+{
+    return is_resource(tlv, 0);
+}
+
+bool M2MTLVDeserializer::is_multiple_resource(const uint8_t *tlv)
+{
+    return is_multiple_resource(tlv, 0);
+}
+
+bool M2MTLVDeserializer::is_resource_instance(const uint8_t *tlv)
+{
+    return is_resource_instance(tlv, 0);
+}
+
+M2MTLVDeserializer::Error M2MTLVDeserializer::deserialise_object_instances(const uint8_t* tlv,
+                                                                           uint32_t tlv_size,
+                                                                           M2MObject &object,
+                                                                           M2MTLVDeserializer::Operation operation)
+{
+    M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
+    if (is_object_instance(tlv) ) {
+        tr_debug("M2MTLVDeserializer::deserialise_object_instances");
+        error = deserialize_object_instances(tlv, tlv_size, 0, object,operation,false);
+        if(M2MTLVDeserializer::None == error) {
+            error = deserialize_object_instances(tlv, tlv_size, 0, object,operation,true);
+        }
+    } else {
+        tr_debug("M2MTLVDeserializer::deserialise_object_instances ::NotValid");
+        error = M2MTLVDeserializer::NotValid;
+    }
+    return error;
+}
+
+M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(const uint8_t *tlv,
+                                                                    uint32_t tlv_size,
+                                                                    M2MObjectInstance &object_instance,
+                                                                    M2MTLVDeserializer::Operation operation)
+{
+    M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
+    if (!is_resource(tlv) && !is_multiple_resource(tlv)) {
+        error = M2MTLVDeserializer::NotValid;
+    } else {
+        error = deserialize_resources(tlv, tlv_size, 0, object_instance, operation,false);
+        if(M2MTLVDeserializer::None == error) {
+            if (M2MTLVDeserializer::Put == operation) {
+                remove_resources(tlv, tlv_size, object_instance, 0);
+            }
+            error = deserialize_resources(tlv, tlv_size, 0, object_instance, operation,true);
+        }
+    }
+    return error;
+}
+
+M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(const uint8_t *tlv,
+                                                                             uint32_t tlv_size,
+                                                                             M2MResource &resource,
+                                                                             M2MTLVDeserializer::Operation operation)
+{
+    M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
+    if (!is_multiple_resource(tlv)) {
+        error = M2MTLVDeserializer::NotValid;
+    } else {
+        tr_debug("M2MTLVDeserializer::deserialize_resource_instances()");
+        uint8_t offset = 2;
+
+        ((tlv[0] & 0x20) == 0) ? offset : offset++;
+
+        uint8_t length = tlv[0] & 0x18;
+        if(length == 0x08) {
+            offset += 1;
+        } else if(length == 0x10) {
+            offset += 2;
+        } else if(length == 0x18) {
+            offset += 3;
+        }
+
+        tr_debug("M2MTLVDeserializer::deserialize_resource_instances() Offset %d", offset);
+        error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation,false);
+        if(M2MTLVDeserializer::None == error) {
+            if (M2MTLVDeserializer::Put == operation) {
+                remove_resource_instances(tlv, tlv_size, resource, offset);
+            }
+            error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation,true);
+        }
+    }
+    return error;
+}
+
+M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_object_instances(const uint8_t *tlv,
+                                                                           uint32_t tlv_size,
+                                                                           uint32_t offset,
+                                                                           M2MObject &object,
+                                                                           M2MTLVDeserializer::Operation operation,
+                                                                           bool update_value)
+{
+    tr_debug("M2MTLVDeserializer::deserialize_object_instances()");
+    M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
+    TypeIdLength til(tlv, offset);
+    til.deserialize();
+    offset = til._offset;
+
+    const M2MObjectInstanceList &list = object.instances();
+    M2MObjectInstanceList::const_iterator it;
+    it = list.begin();
+
+    if (TYPE_OBJECT_INSTANCE == til._type) {
+        for (; it!=list.end(); it++) {
+            if((*it)->instance_id() == til._id) {
+                error = deserialize_resources(tlv, tlv_size, offset, (**it),operation, update_value);
+            }
+        }
+        offset += til._length;
+
+        if(offset < tlv_size) {
+            error = deserialize_object_instances(tlv, tlv_size, offset, object, operation, update_value);
+        }
+    }
+    return error;
+}
+
+M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(const uint8_t *tlv,
+                                                                    uint32_t tlv_size,
+                                                                    uint32_t offset,
+                                                                    M2MObjectInstance &object_instance,
+                                                                    M2MTLVDeserializer::Operation operation,
+                                                                    bool update_value)
+{
+    tr_debug("M2MTLVDeserializer::deserialize_resources()");
+    M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
+    TypeIdLength til(tlv, offset);
+    til.deserialize();
+    offset = til._offset;
+
+    const M2MResourceList &list = object_instance.resources();
+    M2MResourceList::const_iterator it;
+    it = list.begin();
+
+    bool found = false;
+    bool multi = false;
+    if (TYPE_RESOURCE == til._type || TYPE_RESOURCE_INSTANCE == til._type) {
+        multi = false;
+        for (; it!=list.end(); it++) {
+            if((*it)->name_id() == til._id){
+                tr_debug("M2MTLVDeserializer::deserialize_resources() - Resource ID %d ", til._id);
+                found = true;
+                if(update_value) {
+                    if(til._length > 0) {
+                        tr_debug("M2MTLVDeserializer::deserialize_resources() - Update value");
+                        if (!set_resource_instance_value((*it), tlv+offset, til._length)) {
+                            error = M2MTLVDeserializer::OutOfMemory;
+                            break;
+                        }
+                    } else {
+                        tr_debug("M2MTLVDeserializer::deserialize_resources() - Clear Value");
+                        (*it)->clear_value();
+                    }
+                    break;
+                } else if(0 == ((*it)->operation() & SN_GRS_PUT_ALLOWED)) {
+                    tr_debug("M2MTLVDeserializer::deserialize_resources() - NOT_ALLOWED");
+                    error = M2MTLVDeserializer::NotAllowed;
+                    break;
+                }
+            }
+        }
+    } else if (TYPE_MULTIPLE_RESOURCE == til._type) {
+        multi = true;
+        for (; it!=list.end(); it++) {
+            if((*it)->supports_multiple_instances() &&
+                    (*it)->name_id() == til._id) {
+                found = true;
+                error = deserialize_resource_instances(tlv, tlv_size, offset, (**it), object_instance, operation, update_value);
+            }
+        }
+    } else {
+        error = M2MTLVDeserializer::NotValid;
+        return error;
+    }
+
+    if(!found) {
+        if(M2MTLVDeserializer::Post == operation) {
+            //Create a new Resource
+            String id;
+            id.append_int(til._id);
+            M2MResource *resource = object_instance.create_dynamic_resource(id,"",M2MResourceInstance::OPAQUE,true,multi);
+            if(resource) {
+                resource->set_operation(M2MBase::GET_PUT_POST_DELETE_ALLOWED);
+            }
+            if( TYPE_MULTIPLE_RESOURCE == til._type ) {
+                error = deserialize_resource_instances(tlv, tlv_size, offset, (*resource), object_instance, operation, update_value);
+            }
+        } else if(M2MTLVDeserializer::Put == operation) {
+            error = M2MTLVDeserializer::NotFound;
+        }
+    }
+
+
+    offset += til._length;
+
+    if(offset < tlv_size) {
+        error = deserialize_resources(tlv, tlv_size, offset, object_instance, operation, update_value);
+    }
+    return error;
+}
+
+M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(const uint8_t *tlv,
+                                                                             uint32_t tlv_size,
+                                                                             uint32_t offset,
+                                                                             M2MResource &resource,
+                                                                             M2MObjectInstance &object_instance,
+                                                                             M2MTLVDeserializer::Operation operation,
+                                                                             bool update_value)
+{
+    M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
+    TypeIdLength til(tlv, offset);
+    til.deserialize();
+    offset = til._offset;
+
+    if (TYPE_MULTIPLE_RESOURCE == til._type || TYPE_RESOURCE_INSTANCE == til._type) {
+        const M2MResourceInstanceList &list = resource.resource_instances();
+        M2MResourceInstanceList::const_iterator it;
+        it = list.begin();
+        bool found = false;
+        for (; it!=list.end(); it++) {
+            if((*it)->instance_id() == til._id && TYPE_RESOURCE_INSTANCE == til._type) {
+                found = true;
+                if(update_value) {
+                    if(til._length > 0) {
+                        if (!set_resource_instance_value((*it), tlv+offset, til._length)) {
+                            error = M2MTLVDeserializer::OutOfMemory;
+                            break;
+                        }
+                    } else {
+                        (*it)->clear_value();
+                    }
+                    break;
+                } else if(0 == ((*it)->operation() & SN_GRS_PUT_ALLOWED)) {
+                    error = M2MTLVDeserializer::NotAllowed;
+                    break;
+                }
+            }
+        }
+
+        if(!found) {
+            if(M2MTLVDeserializer::Post == operation) {
+                // Create a new Resource Instance
+                M2MResourceInstance *res_instance = object_instance.create_dynamic_resource_instance(resource.name(),"",
+                                                                                                 resource.resource_instance_type(),
+                                                                                                 true,
+                                                                                                 til._id);
+                if(res_instance) {
+                    res_instance->set_operation(M2MBase::GET_PUT_POST_DELETE_ALLOWED);
+                }
+            } else if(M2MTLVDeserializer::Put == operation) {
+                error = M2MTLVDeserializer::NotFound;
+            }
+        }
+    } else {
+        error = M2MTLVDeserializer::NotValid;
+        return error;
+    }
+
+    offset += til._length;
+
+    if(offset < tlv_size) {
+      error = deserialize_resource_instances(tlv, tlv_size, offset, resource, object_instance, operation, update_value);
+    }
+    return error;
+}
+
+M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(const uint8_t *tlv,
+                                                                             uint32_t tlv_size,
+                                                                             uint32_t offset,
+                                                                             M2MResource &resource,
+                                                                             M2MTLVDeserializer::Operation operation,
+                                                                             bool update_value)
+{
+    M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
+    TypeIdLength til(tlv, offset);
+    til.deserialize();
+    offset = til._offset;
+
+    if (TYPE_RESOURCE_INSTANCE == til._type) {
+        const M2MResourceInstanceList &list = resource.resource_instances();
+        M2MResourceInstanceList::const_iterator it;
+        it = list.begin();
+        bool found = false;
+        for (; it!=list.end(); it++) {
+            if((*it)->instance_id() == til._id) {
+                found = true;
+                if(update_value) {
+                    if(til._length > 0) {
+                        if (!set_resource_instance_value((*it),tlv+offset, til._length)) {
+                            error = M2MTLVDeserializer::OutOfMemory;
+                            break;
+                        }
+                    } else {
+                        (*it)->clear_value();
+                    }
+                    break;
+                } else if(0 == ((*it)->operation() & SN_GRS_PUT_ALLOWED)) {
+                    error = M2MTLVDeserializer::NotAllowed;
+                    break;
+                }
+            }
+        }
+        if(!found) {
+            if(M2MTLVDeserializer::Post == operation) {
+                error = M2MTLVDeserializer::NotAllowed;
+            } else if(M2MTLVDeserializer::Put == operation) {
+                error = M2MTLVDeserializer::NotFound;
+            }
+        }
+    } else {
+        error = M2MTLVDeserializer::NotValid;
+        return error;
+    }
+
+    offset += til._length;
+
+    if(offset < tlv_size) {
+         error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation, update_value);
+    }
+    return error;
+}
+
+bool M2MTLVDeserializer::is_object_instance(const uint8_t *tlv, uint32_t offset)
+{
+    bool ret = false;
+    if (tlv) {
+        uint8_t value = tlv[offset];
+        ret = (TYPE_OBJECT_INSTANCE == (value & TYPE_RESOURCE));
+    }
+    return ret;
+}
+
+uint16_t M2MTLVDeserializer::instance_id(const uint8_t *tlv)
+{
+    TypeIdLength til(tlv, 0);
+    til.deserialize();
+    uint16_t id = til._id;
+    return id;
+}
+
+bool M2MTLVDeserializer::is_resource(const uint8_t *tlv, uint32_t offset)
+{
+    bool ret = false;
+    if (tlv) {
+        ret = (TYPE_RESOURCE == (tlv[offset] & TYPE_RESOURCE));
+    }
+    return ret;
+}
+
+bool M2MTLVDeserializer::is_multiple_resource(const uint8_t *tlv, uint32_t offset)
+{
+    bool ret = false;
+    if (tlv) {
+        ret = (TYPE_MULTIPLE_RESOURCE == (tlv[offset] & TYPE_RESOURCE));
+    }
+    return ret;
+}
+
+bool M2MTLVDeserializer::is_resource_instance(const uint8_t *tlv, uint32_t offset)
+{
+    bool ret = false;
+    if (tlv) {
+        ret = (TYPE_RESOURCE_INSTANCE == (tlv[offset] & TYPE_RESOURCE));
+    }
+    return ret;
+}
+
+bool M2MTLVDeserializer::set_resource_instance_value(M2MResourceBase *res, const uint8_t *tlv, const uint32_t size)
+{
+    bool success = true;
+    switch (res->resource_instance_type()) {
+        case M2MResourceBase::INTEGER:
+        case M2MResourceBase::BOOLEAN:
+        case M2MResourceBase::TIME:
+        {
+            int64_t value = String::convert_array_to_integer(tlv, size);
+            if (!res->set_value(value)) {
+                success = false;
+            }
+            break;
+        // Todo! implement conversion for other types as well
+        }
+        case M2MResourceBase::STRING:
+        case M2MResourceBase::OPAQUE:
+        case M2MResourceBase::OBJLINK:
+            if (!res->set_value(tlv, size)) {
+                success = false;
+            }
+            break;
+        case M2MResourceBase::FLOAT:
+        {
+            uint32_t value = common_read_32_bit(tlv);
+            if (!res->set_value_float(*(float*)&value)) {
+                success = false;
+            }
+            break;
+        }
+        default:
+            success = false;
+            break;
+    }
+
+    return success;
+}
+
+void M2MTLVDeserializer::remove_resources(const uint8_t *tlv,
+                                          uint32_t tlv_size,
+                                          M2MObjectInstance &object_instance,
+                                          uint32_t offset_size)
+{
+    tr_debug("M2MTLVDeserializer::remove_resources");
+    uint32_t offset = offset_size;
+    const M2MResourceList &list = object_instance.resources();
+    M2MResourceList::const_iterator it;
+
+    it = list.begin();
+    for (; it!=list.end();) {
+        bool found = false;
+        while(offset < tlv_size) {
+            TypeIdLength til(tlv, offset);
+            til.deserialize();
+            offset = til._offset;
+            offset += til._length;
+            if((*it)->name_id() == til._id){
+                offset = offset_size;
+                found = true;
+                break;
+            }
+        }
+        offset = offset_size;
+
+        // Remove resource if not part of the TLV message
+        if (!found) {
+            tr_debug("M2MTLVDeserializer::remove_resources - remove resource %" PRId32, (*it)->name_id());
+            object_instance.remove_resource((*it)->name());
+        } else {
+            ++it;
+        }
+    }
+}
+
+void M2MTLVDeserializer::remove_resource_instances(const uint8_t *tlv,
+                                          uint32_t tlv_size,
+                                          M2MResource &resource,
+                                          uint32_t offset_size)
+{
+    tr_debug("M2MTLVDeserializer::remove_resource_instances");
+    uint32_t offset = offset_size;
+    const M2MResourceInstanceList &list = resource.resource_instances();
+    M2MResourceInstanceList::const_iterator it;
+    it = list.begin();
+
+    for (; it!=list.end();) {
+        bool found = false;
+        while (offset < tlv_size) {
+            TypeIdLength til(tlv, offset);
+            til.deserialize();
+            offset = til._offset;
+            offset += til._length;
+            if ((*it)->instance_id() == til._id){
+                offset = offset_size;
+                found = true;
+                break;
+            }
+        }
+        offset = offset_size;
+
+        // Remove resource instance if not part of the TLV message
+        if (!found) {
+            tr_debug("M2MTLVDeserializer::remove_resource_instances - remove resource instance %d", (*it)->instance_id());
+            resource.remove_resource_instance((*it)->instance_id());
+        } else {
+            ++it;
+        }
+    }
+}
+
+TypeIdLength::TypeIdLength(const uint8_t *tlv, uint32_t offset)
+: _tlv(tlv), _offset(offset), _type(tlv[offset] & 0xC0), _id(0), _length(0)
+{
+}
+
+void TypeIdLength::deserialize()
+{
+    uint32_t idLength = _tlv[_offset] & ID16;
+    uint32_t lengthType = _tlv[_offset] & LENGTH24;
+    if (0 == lengthType) {
+        _length = _tlv[_offset] & 0x07;
+    }
+    _offset++;
+
+    deserialiseID(idLength);
+    deserialiseLength(lengthType);
+}
+
+void TypeIdLength::deserialiseID(uint32_t idLength)
+{
+    _id = _tlv[_offset++] & 0xFF;
+    if (ID16 == idLength) {
+        _id = (_id << 8) + (_tlv[_offset++] & 0xFF);
+    }
+}
+
+void TypeIdLength::deserialiseLength(uint32_t lengthType)
+{
+    if (lengthType > 0) {
+        _length = _tlv[_offset++] & 0xFF;
+    }
+    if (lengthType > LENGTH8) {
+        _length = (_length << 8) + (_tlv[_offset++] & 0xFF);
+    }
+    if (lengthType > LENGTH16) {
+        _length = (_length << 8) + (_tlv[_offset++] & 0xFF);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/m2mtlvserializer.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "include/m2mtlvserializer.h"
+#include "mbed-client/m2mconstants.h"
+
+#include <stdlib.h>
+#include "common_functions.h"
+
+#define TRACE_GROUP "mClt"
+
+#define MAX_TLV_LENGTH_SIZE 3
+#define MAX_TLV_ID_SIZE 2
+#define TLV_TYPE_SIZE 1
+
+uint8_t* M2MTLVSerializer::serialize(const M2MObjectInstanceList &object_instance_list, uint32_t &size)
+{
+    return serialize_object_instances(object_instance_list, size);
+}
+
+uint8_t* M2MTLVSerializer::serialize(const M2MResourceList &resource_list, uint32_t &size)
+{
+    bool valid = true;
+    return serialize_resources(resource_list, size,valid);
+}
+
+uint8_t* M2MTLVSerializer::serialize(const M2MResource *resource, uint32_t &size)
+{
+    uint8_t* data = NULL;
+    serialize(resource, data, size);
+    return data;
+}
+
+uint8_t* M2MTLVSerializer::serialize_object_instances(const M2MObjectInstanceList &object_instance_list, uint32_t &size)
+{
+    uint8_t *data = NULL;
+
+    if(!object_instance_list.empty()) {
+        M2MObjectInstanceList::const_iterator it;
+        it = object_instance_list.begin();
+        for (; it!=object_instance_list.end(); it++) {            
+            uint16_t id = (*it)->instance_id();
+            serialize(id, *it, data, size);            
+        }
+    }
+    return data;
+}
+
+uint8_t* M2MTLVSerializer::serialize_resources(const M2MResourceList &resource_list, uint32_t &size, bool &valid)
+{
+    uint8_t *data = NULL;
+
+    if(!resource_list.empty()) {
+        M2MResourceList::const_iterator it;
+        it = resource_list.begin();
+        for (; it!=resource_list.end(); it++) {
+            if((*it)->name_id() == -1) {
+                valid = false;
+                break;
+            }
+        }
+        if(valid) {
+            it = resource_list.begin();
+            for (; it!=resource_list.end(); it++) {
+                if (((*it)->operation() & M2MBase::GET_ALLOWED) == M2MBase::GET_ALLOWED) {
+                    if(!serialize(*it, data, size)) {
+                        /* serializing has failed */
+                        /* free data so far */
+                        free(data);
+                        /* invalidate */
+                        valid = false;
+                        /* return NULL immediately */
+                        return NULL;
+                    }
+                }
+            }
+        }
+    }
+    return data;
+}
+
+bool M2MTLVSerializer::serialize(uint16_t id, const M2MObjectInstance *object_instance, uint8_t *&data, uint32_t &size)
+{
+    uint8_t *resource_data = NULL;
+    uint32_t resource_size = 0;
+    bool success;
+
+    bool valid = true;
+    resource_data = serialize_resources(object_instance->resources(),resource_size,valid);
+    if(valid) {
+        if(serialize_TILV(TYPE_OBJECT_INSTANCE, id, resource_data, resource_size, data, size)) {
+            success = true;
+        } else {
+            /* serializing object instance failed */
+            success = false;
+        }
+        free(resource_data);
+    } else {
+        /* serializing resources failed */
+        success = false;
+    }
+    return success;
+}
+
+bool M2MTLVSerializer::serialize(const M2MResource *resource, uint8_t *&data, uint32_t &size)
+{
+    bool success = false;
+    if(resource->name_id() != -1) {
+        success = resource->supports_multiple_instances() ?
+                serialize_multiple_resource(resource, data, size) :
+                serialize_resource(resource, data, size);
+    }
+    return success;
+}
+
+bool M2MTLVSerializer::serialize_resource(const M2MResource *resource, uint8_t *&data, uint32_t &size)
+{
+    bool success = false;
+    if(resource->name_id() != -1) {
+        if ( (resource->resource_instance_type() == M2MResourceBase::INTEGER) ||
+             (resource->resource_instance_type() == M2MResourceBase::BOOLEAN) ||
+             (resource->resource_instance_type() == M2MResourceBase::TIME) ) {
+            success = serialize_TLV_binary_int(resource, TYPE_RESOURCE, resource->name_id(), data, size);
+        }
+        else if (resource->resource_instance_type() == M2MResourceBase::FLOAT) {
+            success = serialize_TLV_binary_float(resource, TYPE_RESOURCE, resource->name_id(), data, size);
+        }
+        else {
+             success = serialize_TILV(TYPE_RESOURCE, resource->name_id(),
+                      resource->value(), resource->value_length(), data, size);
+        }
+    }
+    return success;
+}
+
+bool M2MTLVSerializer::serialize_multiple_resource(const M2MResource *resource, uint8_t *&data, uint32_t &size)
+{
+    bool success = false;
+    uint8_t *nested_data = NULL;
+    uint32_t nested_data_size = 0;
+
+    const M2MResourceInstanceList &instance_list = resource->resource_instances();
+    if(!instance_list.empty()) {
+        M2MResourceInstanceList::const_iterator it;
+        it = instance_list.begin();
+        for (; it!=instance_list.end(); it++) {
+            uint16_t id = (*it)->instance_id();
+            if (((*it)->operation() & M2MBase::GET_ALLOWED) == M2MBase::GET_ALLOWED) {
+                if(!serialize_resource_instance(id, (*it), nested_data, nested_data_size)) {
+                    /* serializing instance has failed */
+                    /* free data so far allocated */
+                    free(nested_data);
+                    /* return fail immediately*/
+                    success = false;
+                    return success;
+                }
+            }
+        }
+    }
+    if(resource->name_id() != -1 &&
+            (resource->operation() & M2MBase::GET_ALLOWED) == M2MBase::GET_ALLOWED) {
+        success = serialize_TILV(TYPE_MULTIPLE_RESOURCE, resource->name_id(),
+                                    nested_data, nested_data_size, data, size);
+    }
+
+    free(nested_data);
+    return success;
+}
+
+bool M2MTLVSerializer::serialize_resource_instance(uint16_t id, const M2MResourceInstance *resource, uint8_t *&data, uint32_t &size)
+{
+    bool success;
+
+    if ( (resource->resource_instance_type() == M2MResourceBase::INTEGER) ||
+         (resource->resource_instance_type() == M2MResourceBase::BOOLEAN) ||
+         (resource->resource_instance_type() == M2MResourceBase::TIME) ) {
+        success=serialize_TLV_binary_int(resource, TYPE_RESOURCE_INSTANCE, id, data, size);
+    }
+    else if (resource->resource_instance_type() == M2MResourceBase::FLOAT) {
+        success=serialize_TLV_binary_float(resource, TYPE_RESOURCE_INSTANCE, id, data, size);
+    }
+    else {
+        success=serialize_TILV(TYPE_RESOURCE_INSTANCE, id, resource->value(), resource->value_length(), data, size);
+    }
+
+    return success;
+}
+
+/* See, OMA-TS-LightweightM2M-V1_0-20170208-A, Appendix C,
+ * Data Types, Integer, Boolean and Time TLV Format */
+bool M2MTLVSerializer::serialize_TLV_binary_int(const M2MResourceBase *resource, uint8_t type, uint16_t id, uint8_t *&data, uint32_t &size)
+{
+    int64_t valueInt = resource->get_value_int();
+    uint32_t buffer_size;
+    /* max len 8 bytes */
+    uint8_t buffer[8];
+
+    if (resource->resource_instance_type() == M2MResourceBase::BOOLEAN) {
+        buffer_size = 1;
+        buffer[0] = valueInt;
+    } else {
+        buffer_size = 8;
+        common_write_64_bit(valueInt, buffer);
+    }
+
+    return serialize_TILV(type, id, buffer, buffer_size, data, size);
+}
+
+/* See, OMA-TS-LightweightM2M-V1_0-20170208-A, Appendix C,
+ * Data Type Float (32 bit only) TLV Format */
+bool M2MTLVSerializer::serialize_TLV_binary_float(const M2MResourceBase *resource, uint8_t type, uint16_t id, uint8_t *&data, uint32_t &size)
+{
+    float valueFloat = resource->get_value_float();
+    /* max len 8 bytes */
+    uint8_t buffer[4];
+
+    common_write_32_bit(*(uint32_t*)&valueFloat, buffer);
+
+    return serialize_TILV(type, id, buffer, 4, data, size);
+}
+
+
+bool M2MTLVSerializer::serialize_TILV(uint8_t type, uint16_t id, uint8_t *value, uint32_t value_length, uint8_t *&data, uint32_t &size)
+{
+    uint8_t *tlv = 0;
+    const uint32_t type_length = TLV_TYPE_SIZE;
+    type += id < 256 ? 0 : ID16;
+    type += value_length < 8 ? value_length :
+            value_length < 256 ? LENGTH8 :
+            value_length < 65536 ? LENGTH16 : LENGTH24;
+    uint8_t tlv_type;
+    tlv_type = type & 0xFF;
+
+    uint32_t id_size;
+    uint8_t id_array[MAX_TLV_ID_SIZE];
+    serialize_id(id, id_size, id_array);
+
+    uint32_t length_size;
+    uint8_t length_array[MAX_TLV_LENGTH_SIZE];
+    serialize_length(value_length, length_size, length_array);
+
+    tlv = (uint8_t*)malloc(size + type_length + id_size + length_size + value_length);
+    if (!tlv) {
+        /* memory allocation has failed */
+        /* return failure immediately */
+        return false;
+        /* eventually NULL will be returned to serializer public method caller */
+    }
+    if(data) {
+        memcpy(tlv, data, size);
+        free(data);
+    }
+    memcpy(tlv+size, &tlv_type, type_length);
+    memcpy(tlv+size+type_length, id_array, id_size);
+    memcpy(tlv+size+type_length+id_size, length_array, length_size);
+    memcpy(tlv+size+type_length+id_size+length_size, value, value_length);
+
+    data = tlv;
+    size += type_length + id_size + length_size + value_length;
+    return true;
+}
+
+void M2MTLVSerializer::serialize_id(uint16_t id, uint32_t &size, uint8_t *id_ptr)
+{
+    if(id > 255) {
+        size=2;
+        id_ptr[0] = (id & 0xFF00) >> 8;
+        id_ptr[1] = id & 0xFF;
+    } else {
+        size=1;
+        id_ptr[0] = id & 0xFF;
+    }
+}
+
+void M2MTLVSerializer::serialize_length(uint32_t length, uint32_t &size, uint8_t *length_ptr)
+{
+    if (length > 65535) {
+        size = 3;
+        length_ptr[0] = (length & 0xFF0000) >> 16;
+        length_ptr[1] = (length & 0xFF00) >> 8;
+        length_ptr[2] = length & 0xFF;
+    } else if (length > 255) {
+        size = 2;
+        length_ptr[0] = (length & 0xFF00) >> 8;
+        length_ptr[1] = length & 0xFF;
+    } else if (length > 7) {
+        size = 1;
+        length_ptr[0] = length & 0xFF;
+    } else {
+        size=0;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/nsdlaccesshelper.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "include/nsdlaccesshelper.h"
+#include "include/m2mnsdlinterface.h"
+#include "sn_nsdl_lib.h"
+#include "sn_grs.h"
+#include <stdlib.h>
+
+// callback function for NSDL library to call into
+uint8_t __nsdl_c_callback(struct nsdl_s *nsdl_handle,
+                          sn_coap_hdr_s *received_coap_ptr,
+                          sn_nsdl_addr_s *address,
+                          sn_nsdl_capab_e nsdl_capab)
+{
+    uint8_t status = 0;
+    M2MNsdlInterface *interface = (M2MNsdlInterface*)sn_nsdl_get_context(nsdl_handle);
+    if(interface) {
+        status = interface->resource_callback(nsdl_handle,
+                                              received_coap_ptr,
+                                              address, nsdl_capab);
+    }
+    return status;
+}
+
+void* __nsdl_c_memory_alloc(uint16_t size)
+{
+    if(size)
+        return malloc(size);
+    else
+        return 0;
+}
+
+void __nsdl_c_memory_free(void *ptr)
+{
+    if(ptr)
+        free(ptr);
+}
+
+uint8_t __nsdl_c_send_to_server(struct nsdl_s * nsdl_handle,
+                                sn_nsdl_capab_e protocol,
+                                uint8_t *data_ptr,
+                                uint16_t data_len,
+                                sn_nsdl_addr_s *address_ptr)
+{
+    uint8_t status = 0;
+    M2MNsdlInterface *interface = (M2MNsdlInterface*)sn_nsdl_get_context(nsdl_handle);
+#if defined(FEA_TRACE_SUPPORT) || MBED_CONF_MBED_TRACE_ENABLE || YOTTA_CFG_MBED_TRACE || (defined(YOTTA_CFG) && !defined(NDEBUG))
+    coap_version_e version = COAP_VERSION_UNKNOWN;
+    sn_coap_hdr_s *header = sn_coap_parser(nsdl_handle->grs->coap, data_len, data_ptr, &version);
+    sn_nsdl_print_coap_data(header, true);
+    sn_coap_parser_release_allocated_coap_msg_mem(nsdl_handle->grs->coap, header);
+#endif
+    if(interface) {
+        status = interface->send_to_server_callback(nsdl_handle,
+                                                           protocol, data_ptr,
+                                                           data_len, address_ptr);
+    }
+    return status;
+}
+
+uint8_t __nsdl_c_received_from_server(struct nsdl_s * nsdl_handle,
+                                      sn_coap_hdr_s *coap_header,
+                                      sn_nsdl_addr_s *address_ptr)
+{
+    uint8_t status = 0;
+    M2MNsdlInterface *interface = (M2MNsdlInterface*)sn_nsdl_get_context(nsdl_handle);
+    if(interface) {
+        status = interface->received_from_server_callback(nsdl_handle,
+                                                          coap_header,
+                                                          address_ptr);
+    }
+    return status;
+}
+
+uint8_t __nsdl_c_auto_obs_token(struct nsdl_s *nsdl_handle, const char *path, uint8_t *token)
+{
+    M2MNsdlInterface *interface = (M2MNsdlInterface*)sn_nsdl_get_context(nsdl_handle);
+    if(interface) {
+        return interface->find_auto_obs_token(path, token);
+    }
+    return 0;
+}
+
+void* __socket_malloc( void * context, size_t size)
+{
+    (void) context;
+    return malloc(size);
+}
+
+void __socket_free(void * context, void * ptr)
+{
+    (void) context;
+    free(ptr);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-client/source/uriqueryparser.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "assert.h"
+#include "mbed-client/uriqueryparser.h"
+
+// Use int return value instead of ssize_t since we don't have it for all platforms
+int parse_query_parameter_value_from_uri(const char *uri, const char *parameter_name, const char **parameter_value)
+{
+    assert(uri);
+    assert(parameter_name);
+    assert(parameter_value);
+
+    *parameter_value = NULL;
+
+    char *value_ptr = strchr(uri, '?');
+    if (value_ptr == NULL) {
+        return -1;
+    }
+
+    // Skip '?'
+    value_ptr++;
+
+    return parse_query_parameter_value_from_query(value_ptr, parameter_name, parameter_value);
+}
+
+// Use int return value instead of ssize_t since we don't have it for all platforms
+int parse_query_parameter_value_from_query(const char *query, const char *parameter_name, const char **parameter_value)
+{
+    assert(query);
+    assert(parameter_name);
+    assert(parameter_value);
+
+    *parameter_value = NULL;
+    const int param_name_len = strlen(parameter_name);
+    const int query_len = strlen(query);
+
+    if (param_name_len == 0 || query_len == 0) {
+        return -1;
+    }
+
+    const char *value_ptr = query;
+
+    do {
+        value_ptr = strstr(value_ptr, parameter_name);
+
+        // No match at all, then break
+        if (!value_ptr) {
+            break;
+        }
+
+        // Check that match was at the beginning or there is a & before the match
+        if (!(value_ptr == query || *(value_ptr - 1) == '&')) {
+            // Offset value_ptr past the match to find next one
+            value_ptr += param_name_len;
+            continue;
+        }
+
+        // Offset to after parameter name
+        value_ptr += param_name_len;
+
+        // Check that parameter was not at the end
+        if (value_ptr >= query + query_len) {
+            break;
+        }
+
+        // CHeck that there is an '=' after parameter name, continue if not as there might be
+        // another parameter left
+        if (*value_ptr != '=') {
+            continue;
+        }
+
+        *parameter_value = ++value_ptr;
+        break;
+
+    } while (value_ptr);
+
+    // If parameter found, calculate length of value either ending at an '&' or the end
+    if (*parameter_value != NULL) {
+        value_ptr = strchr(*parameter_value, '&');
+        if (value_ptr) {
+            return value_ptr - *parameter_value;
+        }
+        return strlen(*parameter_value);
+    }
+    return -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-cloud-client/MbedCloudClient.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,425 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+
+#ifndef __MBED_CLOUD_CLIENT_H__
+#define __MBED_CLOUD_CLIENT_H__
+
+#include <map>
+#include <string>
+#include <vector>
+#include "include/ServiceClient.h"
+#include "mbed-cloud-client/MbedCloudClientConfig.h"
+
+using namespace std;
+class SimpleM2MResourceBase;
+
+/**
+ * \brief MbedCloudClientCallback
+ * A callback class for informing updated object and resource value from the
+ * LWM2M server to the user of the MbedCloudClient class. The user MUST instantiate the
+ * class derived out of this and pass the object to MbedCloudClient::set_update_callback().
+ */
+class MbedCloudClientCallback {
+
+public:
+
+    /**
+    * \brief A callback indicating that the value of the resource object is updated
+    *  by the LWM2M Cloud server.
+    * \param base The object whose value is updated.
+    * \param type The type of the object.
+    */
+    virtual void value_updated(M2MBase *base, M2MBase::BaseType type) = 0;
+};
+
+
+
+/*! \file MbedCloudClient.h
+ *  \brief MbedCloudClient.
+ *  This class provides an interface for handling all the mbed Cloud Client Interface operations
+ *  including device provisioning, identity setup, device resource management defined in the OMA
+ *  LWM2M specifications, and update firmware.
+ *  Device resource management includes Bootstrapping, Client Registration, Device Management &
+ *  Service Enablement and Information Reporting.
+ */
+
+class MbedCloudClient : public ServiceClientCallback {
+
+public:
+
+    /**
+     * \brief An enum defining different kinds of errors
+     * that can occur during various client operations.
+     */
+    typedef enum {
+        ConnectErrorNone                        = 0x0, // Range reserved for Connector Error from 0x30 - 0x3FF
+        ConnectAlreadyExists,
+        ConnectBootstrapFailed,
+        ConnectInvalidParameters,
+        ConnectNotRegistered,
+        ConnectTimeout,
+        ConnectNetworkError,
+        ConnectResponseParseFailed,
+        ConnectUnknownError,
+        ConnectMemoryConnectFail,
+        ConnectNotAllowed,
+        ConnectSecureConnectionFailed,
+        ConnectDnsResolvingFailed,
+        ConnectorFailedToStoreCredentials,
+        ConnectorFailedToReadCredentials,
+        ConnectorInvalidCredentials,
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+        UpdateWarningNoActionRequired           = UpdateClient::WarningBase, // Range reserved for Update Error from 0x0400 - 0x04FF
+        UpdateWarningCertificateNotFound        = UpdateClient::WarningCertificateNotFound,
+        UpdateWarningIdentityNotFound           = UpdateClient::WarningIdentityNotFound,
+        UpdateWarningCertificateInvalid         = UpdateClient::WarningCertificateInvalid,
+        UpdateWarningSignatureInvalid           = UpdateClient::WarningSignatureInvalid,
+        UpdateWarningVendorMismatch             = UpdateClient::WarningVendorMismatch,
+        UpdateWarningClassMismatch              = UpdateClient::WarningClassMismatch,
+        UpdateWarningDeviceMismatch             = UpdateClient::WarningDeviceMismatch,
+        UpdateWarningURINotFound                = UpdateClient::WarningURINotFound,
+        UpdateWarningRollbackProtection         = UpdateClient::WarningRollbackProtection,
+        UpdateWarningUnknown                    = UpdateClient::WarningUnknown,
+        UpdateErrorUserActionRequired           = UpdateClient::ErrorBase,
+        UpdateErrorWriteToStorage               = UpdateClient::ErrorWriteToStorage,
+        UpdateErrorInvalidHash                  = UpdateClient::ErrorInvalidHash,
+        UpdateFatalRebootRequired
+#endif
+    }Error;
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+    /**
+     * \brief Enum defining authorization requests from the Update client.
+     */
+    enum {
+        UpdateRequestInvalid                    = UpdateClient::RequestInvalid,
+        UpdateRequestDownload                   = UpdateClient::RequestDownload,
+        UpdateRequestInstall                    = UpdateClient::RequestInstall
+    };
+#endif
+
+    /**
+     * \brief Constructor
+     */
+    MbedCloudClient();
+
+    /**
+     * \brief Destructor
+     */
+    virtual ~MbedCloudClient();
+
+    /**
+     * \brief Adds a list of objects that the application wants to register to the
+     * LWM2M server. This function MUST be called before calling the setup()
+     * API. Otherwise, the application gets the error ConnectInvalidParameters, when
+     * calling setup().
+     * \param object_list Objects that contain information about the
+     * client attempting to register to the LWM2M server.
+     */
+    void add_objects(const M2MObjectList& object_list);
+
+    /**
+     * \brief Adds a list of M2MBase interface implementing objects that the application wants
+     * to register to the LWM2M server. This function MUST be called before calling the setup()
+     * API. Otherwise, the application gets the error ConnectInvalidParameters, when
+     * calling setup().
+     * \param base_list Object implementing the M2MBase interface that contain information about the
+     * client attempting to register to the LWM2M server.
+     */
+    void add_objects(const M2MBaseList& base_list);
+
+    void remove_object(M2MBase *object);
+    /**
+     * \brief Sets the callback function that is called when there is
+     * any new update on any Object/ObjectInstance/Resource from the LWM2M server,
+     * typically on receiving PUT commands on the registered objects.
+     * \param callback Passes the class object that implements the callback
+     * function to handle the incoming PUT request on a given object.
+     */
+    void set_update_callback(MbedCloudClientCallback *callback);
+
+    /**
+     * \brief Initiates the Cloud Client set up on the Cloud service. This
+     * function manages device provisioning (first time usage), bootstrapping
+     * (first time usage) and registering the client application to the Cloud
+     * service.
+     * \param iface A handler to the network interface on mbedOS, can be NULL on
+     * other platforms.
+     */
+    bool setup(void* iface);
+
+    /**
+     * \brief Sets the callback function that is called when the client is registered
+     * successfully to the Cloud. This is used for a statically defined function.
+     * \param fn A function pointer to the function that is called when the client
+     * is registered.
+     */
+    void on_registered(void(*fn)(void));
+
+    /**
+    * \brief Sets the callback function that is called when the client is registered
+    * successfully to the Cloud. This is an overloaded function for a class function.
+    * \param object A function pointer to the function that is called when the client
+    * is registered.
+    */
+    template<typename T>
+    void on_registered(T *object, void (T::*member)(void));
+
+    /**
+     * \brief Sets the callback function that is called when there is any error
+     * occuring in the client functionality. The error code can be mapped from the
+     * MbedCloudClient::Error enum. This is used for a statically defined function.
+     * \param fn A function pointer to the function that is called when there
+     * is any error in the client.
+     */
+    void on_error(void(*fn)(int));
+
+    /**
+     * \brief Sets the callback function that is called when there is an error
+     * occuring in the client functionality. The error code can be mapped from
+     * MbedCloudClient::Error enum. This is an overloaded function for a class function.
+     * \param object A function pointer to the function that is called when there
+     * is an error in the client.
+     */
+    template<typename T>
+    void on_error(T *object, void (T::*member)(int));
+
+    /**
+     * \brief Sets the callback function that is called when the client is unregistered
+     * successfully from the Cloud. This is used for a statically defined function.
+     * \param fn A function pointer to the function that is called when the client
+     * is unregistered.
+     */
+    void on_unregistered(void(*fn)(void));
+
+    /**
+    * \brief Sets the callback function that is called when the client is unregistered
+    * successfully from the Cloud. This is an overloaded function for a class function.
+    * \param object A function pointer to the function that is called when the client
+    * is unregistered.
+    */
+    template<typename T>
+    void on_unregistered(T *object, void (T::*member)(void));
+
+    /**
+     * \brief Sets the callback function that is called when the client registration
+     * is updated successfully to the Cloud. This is used for a statically defined function.
+     * \param fn A function pointer to the function that is called when the client
+     * registration is updated.
+     */
+    void on_registration_updated(void(*fn)(void));
+
+    /**
+     * \brief Sets the callback function that is called when the client registration
+     * is updated successfully to the Cloud. This is an overloaded function for a class
+     * function.
+     * \param object A function pointer to the function that is called when the client
+     * registration is updated.
+     */
+    template<typename T>
+        void on_registration_updated(T *object, void (T::*member)(void));
+
+    /**
+    * \brief Sends a registration update message to the Cloud when the client is registered
+    * successfully to the Cloud and there is no internal connection error.
+    * If the client is not connected and there is some other internal network
+    * transaction ongoing, this function triggers an error MbedCloudClient::ConnectNotAllowed.
+    * \deprecated
+    */
+    void keep_alive() m2m_deprecated;
+
+    /**
+    * \brief Sends a registration update message to the Cloud when the client is registered
+    * successfully to the Cloud and there is no internal connection error.
+    * If the client is not connected and there is some other internal network
+    * transaction ongoing, this function triggers an error MbedCloudClient::ConnectNotAllowed.
+    */
+    void register_update();
+
+    /**
+    * \brief Closes the connection towards Cloud and unregisters the client.
+    * This function triggers the on_unregistered() callback if set by the application.
+    */
+    void close();
+
+    /**
+     * \brief Returns pointer to the ConnectorClientEndpointInfo object.
+     * \return ConnectorClientEndpointInfo pointer.
+     */
+    const ConnectorClientEndpointInfo *endpoint_info() const;
+
+    /**
+     * \brief Sets the function that is called for indicating that the client
+     * is going to sleep when the binding mode is selected with queue mode.
+     * \param callback A function pointer that is called when the client
+     * goes to sleep.
+     */
+    void set_queue_sleep_handler(callback_handler handler);
+
+    /**
+     * \brief Sets the function callback that is called by client to
+     * fetch a random number from an application to ensure strong entropy.
+     * \param random_callback A function pointer that is called by client
+     * while performing a secure handshake.
+     * The function signature should be uint32_t (*random_number_callback)(void);
+     */
+    void set_random_number_callback(random_number_cb callback);
+
+    /**
+     * \brief Sets the function callback that is called by client to
+     * provide an entropy source from an application to ensure strong entropy.
+     * \param entropy_callback A function pointer that is called by mbed Client
+     * while performing a secure handshake.
+     * Function signature, if using mbed-client-mbedtls, should be
+     * int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output,
+     *                                     size_t len, size_t *olen);
+     */
+    void set_entropy_callback(entropy_cb callback);
+
+    /**
+     * \brief Set resource value in the Device Object
+     *
+     * \param resource Device enum to have value set.
+     * \param value String object.
+     * \return True if successful, false otherwise.
+     */
+    bool set_device_resource_value(M2MDevice::DeviceResource resource,
+                                   const std::string &value);
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+    /**
+     * \brief Registers a callback function for authorizing firmware downloads and reboots.
+     * \param handler Callback function.
+     */
+    void set_update_authorize_handler(void (*handler)(int32_t request));
+
+    /**
+     * \brief Authorize request passed to authorization handler.
+     * \param request Request being authorized.
+     */
+    void update_authorize(int32_t request);
+
+    /**
+     * \brief Registers a callback function for monitoring download progress.
+     * \param handler Callback function.
+     */
+    void set_update_progress_handler(void (*handler)(uint32_t progress, uint32_t total));
+#endif
+
+    /**
+     * @brief Return error description for the latest error code
+     * @return Error description string
+     */
+    const char *error_description() const;
+
+    /**
+     * @brief Sends the CoAP GET request to the server.
+     * API must be called again with the updated offset to complete the whole transfer.
+     * @uri Uri path to the data.
+     * @offset Data offset.
+     * @get_data_cb Callback which is triggered once there is data available.
+     * @get_data_error_cb Callback which is trigged in case of any error.
+    */
+    void send_get_request(const char *uri,
+                          const size_t offset,
+                          get_data_cb data_cb,
+                          get_data_error_cb error_cb,
+                          void *context);
+
+protected: // from ServiceClientCallback
+
+    /**
+    * \brief Indicates that the setup or close operation is complete
+    * with success or failure.
+    * \param status Indicates success or failure in terms of status code.
+    */
+    virtual void complete(ServiceClientCallbackStatus status);
+
+    /**
+    * \brief Indicates an error condition from the underlying clients like
+    * identity, connector or update client.
+    * \param error Indicates an error code translated to MbedCloudClient::Error.
+    * \param reason, Indicates human readable text for error description.
+    */
+    virtual void error(int error, const char *reason);
+
+    /**
+    * \brief A callback indicating that the value of the resource object is updated
+    *  by the LWM2M Cloud server.
+    * \param base The object whose value is updated.
+    * \param type The type of the object.
+    */
+    virtual void value_updated(M2MBase *base, M2MBase::BaseType type);
+
+private:
+
+    /**
+    * \brief Registers the update callback functions for SimpleM2MResourceBase
+    * objects.
+    * \param route The URI path of the registered resource such as "/Test/0/res/".
+    * \param resource Object of the SimpleM2MResourceBase.
+    */
+    void register_update_callback(string route, SimpleM2MResourceBase* resource);
+
+private:
+
+    ServiceClient                                   _client;
+    MbedCloudClientCallback                         *_value_callback;
+    map<string, M2MObject*>                         _objects;
+    map<string, M2MResource*>                       _resources;
+    M2MBaseList                                     _object_list;
+    map<string, SimpleM2MResourceBase*>             _update_values;
+    FP0<void>                                       _on_registered;
+    FP0<void>                                       _on_unregistered;
+    FP0<void>                                       _on_registration_updated;
+    FP1<void,int>                                   _on_error;
+    const char                                      *_error_description;
+
+
+friend class SimpleM2MResourceBase;
+};
+
+template<typename T>
+void MbedCloudClient::on_registered(T *object, void (T::*member)(void))
+{
+    FP0<void> fp(object, member);
+    _on_registered = fp;
+}
+
+template<typename T>
+void MbedCloudClient::on_error(T *object, void (T::*member)(int))
+{
+    FP1<void, int> fp(object, member);
+    _on_error = fp;
+}
+
+template<typename T>
+void MbedCloudClient::on_unregistered(T *object, void (T::*member)(void))
+{
+    FP0<void> fp(object, member);
+    _on_unregistered = fp;
+}
+
+template<typename T>
+void MbedCloudClient::on_registration_updated(T *object, void (T::*member)(void))
+{
+    FP0<void> fp(object, member);
+    _on_registration_updated = fp;
+}
+#endif // __MBED_CLOUD_CLIENT_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-cloud-client/MbedCloudClientConfig.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,100 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef MBED_CLOUD_CLIENT_CONFIG_H
+#define MBED_CLOUD_CLIENT_CONFIG_H
+
+#include <stdint.h>
+
+/*! \file MbedCloudClientConfig.h
+* \brief Configuration options (set of defines and values).
+*
+*  This lists a set of compile-time options that needs to be used to enable
+*  or disable features selectively, and set the values for the mandatory
+*  parameters.
+*/
+
+#if defined (__ICCARM__)
+#define m2m_deprecated
+#else
+#define m2m_deprecated __attribute__ ((deprecated))
+#endif
+
+#ifdef __DOXYGEN__
+
+/**
+* \def MBED_CLOUD_CLIENT_ENDPOINT_TYPE
+*
+* \brief This is mandatory MACRO and MUST be enabled. You MUST define it like this #define MBED_CLOUD_CLIENT_ENDPOINT_TYPE "default".
+*/
+#define MBED_CLOUD_CLIENT_ENDPOINT_TYPE          /* "default" */
+
+/**
+* \def MBED_CLOUD_CLIENT_LIFETIME
+*
+* \brief This is mandatory MACRO and MUST be enabled. You MUST define it like this: #define MBED_CLOUD_CLIENT_LIFETIME 3600.
+* This value denotes time in seconds.
+*/
+#define MBED_CLOUD_CLIENT_LIFETIME               /* 3600 */
+
+/**
+* \def MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP
+*
+* \brief Enable this MACRO if you want to enable UDP mode for the client.
+*/
+#define MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP
+
+/**
+* \def MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP
+*
+* \brief Enable this MACRO if you want to enable TCP mode for the client.
+*/
+#define MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP
+
+/**
+* \def MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE
+*
+* \brief Enable this MACRO if you want to enable UDP_QUEUE mode for the client.
+*/
+#define MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE
+
+/**
+* \def MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE
+*
+* \brief Enable this MACRO if you want to enable TCP_QUEUE mode for the client.
+*/
+
+#define MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE
+
+#endif
+
+/**
+* \def MBED_CLOUD_CLIENT_LISTEN_PORT
+*
+* \brief This is mandatory MACRO and is set to 0 by default. This implies that the client picks a random port
+ * for listening to the incoming connection.
+*/
+#define MBED_CLOUD_CLIENT_LISTEN_PORT           0
+
+#ifdef MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#include MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#endif
+
+#include "MbedCloudClientConfigCheck.h"
+
+#endif // MBED_CLOUD_CLIENT_CONFIG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-cloud-client/MbedCloudClientConfigCheck.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,75 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+
+#ifndef MBED_CLOUD_CONFIG_CHECK_H
+#define MBED_CLOUD_CONFIG_CHECK_H
+
+/*! \file MbedCloudClientConfigCheck.h
+* \brief Configuration options check.
+*
+*  This set checks and validates the compile-time options that can be made for possible client library.
+*  NOTE: Not to be used by developers.
+*/
+
+#ifndef MBED_CLOUD_CLIENT_ENDPOINT_TYPE
+#error "MBED_CLOUD_CLIENT_ENDPOINT_TYPE must be defined with valid endpoint type"
+#endif
+
+#ifndef MBED_CLOUD_CLIENT_LIFETIME
+#error "MBED_CLOUD_CLIENT_LIFETIME must be defined with valid non-zero lifetime value in seconds, default is 60"
+#endif
+
+#ifndef MBED_CLOUD_CLIENT_LISTEN_PORT
+#error "MBED_CLOUD_CLIENT_LISTEN_PORT must be defined with valid non-zero port number, default is 0"
+#endif
+
+#if !defined (SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE) || (SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE < 16)
+#error "SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE must be defined with one of the values from this - 128, 256, 512 or 1024"
+#endif
+
+#if defined (MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE)
+#error "TCP queue mode not supported!"
+#endif
+
+#if defined (MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP) && ( defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP) || \
+defined (MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE) || defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE))
+#error "Only one MBED_CLOUD_CLIENT_TRANSPORT_MODE can be defined at a time"
+#endif
+
+#if defined (MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP) && ( defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP) || \
+defined (MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE) || defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE))
+#error "Only one MBED_CLOUD_CLIENT_TRANSPORT_MODE can be defined at a time"
+#endif
+
+#if defined (MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE) && ( defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP) || \
+defined (MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP) || defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE))
+#error "Only one MBED_CLOUD_CLIENT_TRANSPORT_MODE can be defined at a time"
+#endif
+
+#if defined (MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE) && ( defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP) || \
+defined (MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE) || defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP))
+#error "Only one MBED_CLOUD_CLIENT_TRANSPORT_MODE can be defined at a time"
+#endif
+
+#if !defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP) && !defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP) \
+&& !defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE) && !defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE)
+#error "One MBED_CLOUD_CLIENT_TRANSPORT_MODE must be defined at a time"
+#endif
+
+#endif // MBED_CLOUD_CONFIG_CHECK_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-cloud-client/SimpleM2MResource.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,279 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef SIMPLE_M2M_RESOURCE_H
+#define SIMPLE_M2M_RESOURCE_H
+
+
+#include "mbed-cloud-client/MbedCloudClient.h"
+
+/*! \file SimpleM2MResource.h
+ *  \brief SimpleM2MResourceBase.
+ * This class provides an easy wrapper base class for creating a simple M2MResource based on
+ * integer and string values. This class is NOT meant to be directed instantiated but is used
+ * by the SimpleM2MResourceInt and SimpleM2MResourceString classes to create resources.
+ */
+
+class SimpleM2MResourceBase {
+
+protected:
+
+    // Prevents the use of default constructor.
+    SimpleM2MResourceBase();
+
+    // Prevents the use of assignment operator.
+    SimpleM2MResourceBase& operator=( const SimpleM2MResourceBase& /*other*/ );
+
+    // Prevents the use of copy constructor
+    SimpleM2MResourceBase( const M2MBase& /*other*/ );
+
+    SimpleM2MResourceBase(MbedCloudClient* client, string route);
+
+    /**
+     * \brief Destructor
+     */
+    virtual ~SimpleM2MResourceBase();
+
+
+public:
+
+    /**
+     * \brief Defines M2MResource internally and creates a necessary LWM2M
+     * structure like object and object instance based on the given string
+     * URI path and sets the right M2M operation to the resource.
+     * \param v The URI path for the resource "Test/0/res" in this format.
+     * \param opr An operation to be set for the resource.
+     * \param observable True if the resource is observable, else false.
+     * \return True if resource is created, else false.
+     */
+    bool define_resource_internal(string v,
+                                  M2MBase::Operation opr,
+                                  bool observable);
+
+    /**
+     * \brief Gets the value set in a resource in text format.
+     * \return The value set in the resource.
+     */
+    string get() const;
+
+    /**
+     * \brief Sets the value in a resource in text format.
+     * \param v The value to be set.
+     * \return True if set successfully, else false.
+     */
+    bool set(string v);
+
+    /**
+     * \brief Sets the value in a resource in integer format.
+     * \param v The value to be set.
+     * \return True if set successfully, else false.
+     */
+    bool set(const int& v);
+
+    /**
+     * \brief Sets the callback function to be called
+     * when the resource received a POST command.
+     * \param fn A function to be called.
+     * This is used for a statically defined function.
+     * \return True if set successfully, else false.
+     */
+    bool set_post_function(void(*fn)(void*));
+
+    /**
+     * \brief Sets the callback function to be called
+     * when a resource received the POST command.
+     * \param fn A function to be called.
+     * This is an overloaded function for a class function.
+     * \return True if set successfully, else false.
+     */
+    bool set_post_function(execute_callback fn);
+
+    /**
+    * \brief Returns the M2MResource object of the registered object through
+    * the SimpleM2MResourceBase objects.
+    * \return The object of the M2MResource.
+    */
+    M2MResource* get_resource();
+
+    /**
+    * \brief Calls when there is an indication that the value of the resource
+    * object is updated by the LWM2M Cloud server.
+    */
+    virtual void update(){}
+
+private:
+
+    /**
+    * \brief An internal helper function to break the URI path into a list of
+    * strings such as "Test/0/res" into a list of three strings.
+    * \param route The URI path in the format "Test/0/res".
+    * \return A list of strings parsed from the URI path.
+    */
+    vector<string> parse_route(const char* route);
+
+private:
+    MbedCloudClient*                    _client;   // Not owned
+    string                              _route;
+};
+
+/**
+ *  \brief SimpleM2MResourceString.
+ *  This class provides an easy wrapper base class for creating a simple M2MResource based on
+ * string values. This class provides an easy access to the M2MResource objects without the application
+ * requiring to create Objects and Object Instances.
+ */
+
+class SimpleM2MResourceString : public SimpleM2MResourceBase
+{
+public:
+
+    /**
+     *  \brief Constructor.
+     *  \param client A handler for MbedCloudClient.
+     *  \param route The route for the resource such as "Test/0/res".
+     *  \param v The value of the resource.
+     *  \param opr An operation that can be supported by the resource.
+     *  \param observable True if the resource is observable.
+     *  \param on_update If the resource supports the PUT operation, a function pointer
+     *  for the callback function that is called when the client receives an
+     *  updated value for this resource.
+     */
+    SimpleM2MResourceString(MbedCloudClient* client,
+                   const char* route,
+                   string v,
+                   M2MBase::Operation opr = M2MBase::GET_PUT_ALLOWED,
+                   bool observable = true,
+                   FP1<void, string> on_update = NULL);
+
+    /**
+     *  \brief Constructor. This is overloaded function.
+     *  \param client A handler for MbedCloudClient.
+     *  \param route The route for the resource such as "Test/0/res".
+     *  \param v The value of the resource.
+     *  \param opr An operation that can be supported by the resource.
+     *  \param observable True if resource is observable.
+     *  \param on_update If the resource supports the PUT operation, a function pointer
+     *  for the callback function that is called when the client receives an
+     *  updated value for this resource.
+     */
+    SimpleM2MResourceString(MbedCloudClient* client,
+                   const char* route,
+                   string v,
+                   M2MBase::Operation opr,
+                   bool observable,
+                   void(*on_update)(string));
+
+
+    /**
+     * \brief Destructor
+     */
+    virtual ~SimpleM2MResourceString();
+
+    /**
+     * \brief Overloaded operator for = operation.
+     */
+    string operator=(const string& new_value);
+
+    /**
+     * \brief Overloaded operator for string() operation.
+     */
+    operator string() const;
+
+    /**
+    * \brief Calls when there is an indication that the value of the resource
+    * object is updated by the LWM2M Cloud server.
+    */
+    virtual void update();
+
+private:
+    FP1<void, string>                   _on_update;
+};
+
+/**
+ *  \brief SimpleM2MResourceInt.
+ *  This class provides an easy wrapper base class for creating a simple M2MResource based on
+ * integer values. This class provides easy access to M2MResource objects without the application
+ * requiring to create Objects and Object Instances.
+ */
+
+class SimpleM2MResourceInt : public SimpleM2MResourceBase
+{
+public:
+
+    /**
+     *  \brief Constructor.
+     *  \param client A handler for MbedCloudClient.
+     *  \param route The route for the resource such as "Test/0/res".
+     *  \param v The value of the resource.
+     *  \param opr An operation that can be supported by the resource.
+     *  \param observable True if the resource is observable, else false.
+     *  \param on_update If the resource supports the PUT operation, a function pointer
+     *  for the callback function that is called when the client receives an
+     *  updated value for this resource.
+     */
+    SimpleM2MResourceInt(MbedCloudClient* client,
+                const char* route,
+                int v,
+                M2MBase::Operation opr = M2MBase::GET_PUT_ALLOWED,
+                bool observable = true,
+                FP1<void, int> on_update = NULL);
+
+    /**
+     *  \brief Constructor. This is an overloaded function
+     *  \param client A handler for MbedCloudClient.
+     *  \param route The route for the resource such as "Test/0/res"
+     *  \param v The value of the resource.
+     *  \param opr An operation that can be supported by the resource.
+     *  \param observable True if the resource is observable, else false.
+     *  \param on_update If the resource supports the PUT operation, a function pointer
+     *  for the callback function that is called when the client receives an
+     *  updated value for this resource.
+     */
+    SimpleM2MResourceInt(MbedCloudClient* client,
+                const char* route,
+                int v,
+                M2MBase::Operation opr,
+                bool observable,
+                void(*on_update)(int));
+
+    /**
+     * \brief Destructor
+     */
+    virtual ~SimpleM2MResourceInt();
+
+    /**
+     * \brief Overloaded operator for = operation.
+     */
+    int operator=(int new_value);
+
+    /**
+     * \brief Overloaded operator for int() operation.
+     */
+    operator int() const;
+
+    /**
+    * \brief Calls when there is an indication that the value of the resource
+    * object is updated by the LWM2M Cloud server.
+    */
+    virtual void update();
+
+private:
+    FP1<void, int>                  _on_update;
+};
+
+#endif // SIMPLE_M2M_RESOURCE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+test/*
+unittest/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/README.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+CoAP C library - Builder and Parser for CoAP messages.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/apache-2.0.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,56 @@
+
+
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+    You must give any other recipients of the Work or Derivative Works a copy of this License; and
+    You must cause any modified files to carry prominent notices stating that You changed the files; and
+    You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+    If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+    You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/doxygen/libcoap_doxy	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1846 @@
+# Doxyfile 1.8.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should 
+# identify the project. Note that if you do not use Doxywizard you need 
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME           = libcoap
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description 
+# for a project that appears at the top of each page and should give viewer 
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          = "CoAP C library"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is 
+# included in the documentation. The maximum height of the logo should not 
+# exceed 55 pixels and the maximum width should not exceed 200 pixels. 
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO           = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = ../docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, 
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English 
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, 
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, 
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip. Note that you specify absolute paths here, but also 
+# relative paths, which will be relative from the directory where doxygen is 
+# started.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful if your file system 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 16
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only). 
+# A mapping has the form "name=value". For example adding 
+# "class=itcl::class" will allow you to use the command class in the 
+# itcl::class meaning.
+
+TCL_SUBST              = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it 
+# parses. With this tag you can assign which parser to use for a given 
+# extension. Doxygen has a built-in mapping, but you can override or extend it 
+# using this tag. The format is ext=language, where ext is a file extension, 
+# and language is one of the parsers supported by doxygen: IDL, Java, 
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, 
+# C++. For instance to make doxygen treat .inc files as Fortran files (default 
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note 
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the 
+# files are not read by doxygen.
+
+EXTENSION_MAPPING      = 
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all 
+# comments according to the Markdown format, which allows for more readable 
+# documentation. See http://daringfireball.net/projects/markdown/ for details. 
+# The output of markdown processing is further processed by doxygen, so you 
+# can mix doxygen, HTML, and XML commands with Markdown formatting. 
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes, 
+# or namespaces to their corresponding documentation. Such a link can be 
+# prevented in individual cases by by putting a % sign in front of the word or 
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also makes the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to 
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES (the
+# default) will make doxygen replace the get and set methods by a property in
+# the documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and 
+# unions are shown inside the group in which they are included (e.g. using 
+# @ingroup) instead of on a separate page (for HTML and Man pages) or 
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and 
+# unions with only public data fields will be shown inline in the documentation 
+# of the scope in which they are defined (i.e. file, namespace, or group 
+# documentation), provided this scope is documented. If set to NO (the default), 
+# structs, classes, and unions are shown on a separate page (for HTML and Man 
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to 
+# determine which symbols to keep in memory and which to flush to disk. 
+# When the cache is full, less often used symbols will be written to disk. 
+# For small to medium size projects (<1000 input files) the default value is 
+# probably good enough. For larger projects a too small cache size can cause 
+# doxygen to be busy swapping symbols to and from disk most of the time 
+# causing a significant performance penalty. 
+# If the system has enough physical memory increasing the cache will improve the 
+# performance by keeping more symbols in memory. Note that the value works on 
+# a logarithmic scale so increasing the size by one will roughly double the 
+# memory usage. The cache size is given by this formula: 
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE      = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be 
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given 
+# their name and scope. Since this can be an expensive process and often the 
+# same symbol appear multiple times in the code, doxygen keeps a cache of 
+# pre-resolved symbols. If the cache is too small doxygen will become slower. 
+# If the cache is too large, memory is wasted. The cache size is given by this 
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal 
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = NO
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = YES
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen 
+# will list include files with double quotes in the documentation 
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen 
+# will sort the (brief and detailed) documentation of class members so that 
+# constructors and destructors are listed first. If set to NO (the default) 
+# the constructors will appear in the respective orders defined by 
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. 
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO 
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. 
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to 
+# do proper type resolution of all parameters of a function it will reject a 
+# match between the prototype and the implementation of a member function even 
+# if there is only one candidate or it is obvious which candidate to choose 
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen 
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or macro consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and macros in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 18
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. 
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page.  This will remove the Namespaces entry from the Quick Index 
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed 
+# by doxygen. The layout file controls the global structure of the generated 
+# output files in an output format independent way. To create the layout file 
+# that represents doxygen's defaults, run doxygen with the -l option. 
+# You can optionally specify a file name after the option, if omitted 
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE            = 
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files 
+# containing the references data. This must be a list of .bib files. The 
+# .bib extension is automatically appended if omitted. Using this command 
+# requires the bibtex tool to be installed. See also 
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style 
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this 
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES         = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = ../nsdl-c
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh 
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py 
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.d \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.idl \
+                         *.odl \
+                         *.cs \
+                         *.php \
+                         *.php3 \
+                         *.inc \
+                         *.m \
+                         *.markdown \
+                         *.md \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.f90 \
+                         *.f \
+                         *.for \
+                         *.vhd \
+                         *.vhdl
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag. 
+# Note that relative paths are relative to the directory from which doxygen is 
+# run.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or 
+# directories that are symbolic links (a Unix file system feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty or if 
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file 
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) 
+# and it is also possible to disable source filtering for a specific pattern 
+# using *.ext= (so without naming a filter). This option only has effect when 
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS = 
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 
+# link to the source code.  Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header. Note that when using a custom header you are responsible  
+# for the proper inclusion of any scripts and style sheets that doxygen 
+# needs, which is dependent on the configuration options used. 
+# It is advised to generate a default header using "doxygen -w html 
+# header.html footer.html stylesheet.css YourConfigFile" and then modify 
+# that header. Note that the header is subject to change so you typically 
+# have to redo this when upgrading to a newer version of doxygen or when 
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If left blank doxygen will 
+# generate a default style sheet. Note that it is recommended to use 
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this 
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET        = 
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional 
+# user-defined cascading style sheet that is included after the standard 
+# style sheets created by doxygen. Using this option one can overrule 
+# certain style aspects. This is preferred over using HTML_STYLESHEET 
+# since it does not replace the standard style sheet and is therefor more 
+# robust against future updates. Doxygen will copy the style sheet file to 
+# the output directory.
+
+HTML_EXTRA_STYLESHEET  = 
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or 
+# other source files which should be copied to the HTML output directory. Note 
+# that these files will be copied to the base HTML output directory. Use the 
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these 
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that 
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES       = 
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. 
+# Doxygen will adjust the colors in the style sheet and background images 
+# according to this color. Hue is specified as an angle on a colorwheel, 
+# see http://en.wikipedia.org/wiki/Hue for more information. 
+# For instance the value 0 represents red, 60 is yellow, 120 is green, 
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. 
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of 
+# the colors in the HTML output. For a value of 0 the output will use 
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to 
+# the luminance component of the colors in the HTML output. Values below 
+# 100 gradually make the output lighter, whereas values above 100 make 
+# the output darker. The value divided by 100 is the actual gamma applied, 
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, 
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML 
+# page will contain the date and time when the page was generated. Setting 
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of 
+# entries shown in the various tree structured indices initially; the user 
+# can expand and collapse entries dynamically later on. Doxygen will expand 
+# the tree to such a level that at most the specified number of entries are 
+# visible (unless a fully collapsed tree already exceeds this amount). 
+# So setting the number of entries 1 will produce a full collapsed tree by 
+# default. 0 is a special value representing an infinite number of entries 
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup. 
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html 
+# for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely 
+# identify the documentation publisher. This should be a reverse domain-name 
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING 
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file 
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and 
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated 
+# that can be used as input for Qt's qhelpgenerator to generate a 
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can 
+# be used to specify the file name of the resulting .qch file. 
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               = 
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to 
+# add. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   = 
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the 
+# custom filter to add. For more information please see 
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> 
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  = 
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this 
+# project's 
+# filter section matches. 
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> 
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  = 
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can 
+# be used to specify the location of Qt's qhelpgenerator. 
+# If non-empty doxygen will try to run qhelpgenerator on the generated 
+# .qhp file.
+
+QHG_LOCATION           = 
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files  
+# will be generated, which together with the HTML files, form an Eclipse help 
+# plugin. To install this plugin and make it available under the help contents 
+# menu in Eclipse, the contents of the directory containing the HTML and XML 
+# files needs to be copied into the plugins directory of eclipse. The name of 
+# the directory within the plugins directory should be the same as 
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before 
+# the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin 
+# the directory name containing the HTML and XML files should also have 
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) 
+# at top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it. Since the tabs have the same information as the 
+# navigation tree you can set this option to NO if you already set 
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 
+# structure should be generated to display hierarchical information. 
+# If the tag value is set to YES, a side panel will be generated 
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). 
+# Windows users are probably better off using the HTML help feature. 
+# Since the tree basically has the same information as the tab index you 
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values 
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML 
+# documentation. Note that a value of 0 will completely suppress the enum 
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open 
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images 
+# generated for formulas are transparent PNGs. Transparent PNGs are 
+# not supported properly for IE 6.0, but are supported on all modern browsers. 
+# Note that when changing this option you need to delete any form_*.png files 
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax 
+# (see http://www.mathjax.org) which uses client side Javascript for the 
+# rendering instead of using prerendered bitmaps. Use this if you do not 
+# have LaTeX installed or if you want to formulas look prettier in the HTML 
+# output. When enabled you may also need to install MathJax separately and 
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you need to specify the location relative to the 
+# HTML output directory using the MATHJAX_RELPATH option. The destination 
+# directory should contain the MathJax.js script. For instance, if the mathjax 
+# directory is located at the same level as the HTML output directory, then 
+# MATHJAX_RELPATH should be ../mathjax. The default value points to 
+# the MathJax Content Delivery Network so you can quickly see the result without 
+# installing MathJax.  However, it is strongly recommended to install a local 
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension 
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS     = 
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box 
+# for the HTML output. The underlying search engine uses javascript 
+# and DHTML and should work on any modern browser. Note that when using 
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets 
+# (GENERATE_DOCSET) there is already a search function so this one should 
+# typically be disabled. For large projects the javascript based search engine 
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be 
+# implemented using a PHP enabled web server instead of at the web client 
+# using Javascript. Doxygen will generate the search PHP script and index 
+# file to put on the web server. The advantage of the server 
+# based approach is that it scales better to large projects and allows 
+# full text search. The disadvantages are that it is more difficult to setup 
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name. 
+# Note that when enabling USE_PDFLATEX this option is only used for 
+# generating bitmaps for formulas in the HTML output, but not in the 
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for 
+# the generated latex document. The footer should contain everything after 
+# the last chapter. If it is left blank doxygen will generate a 
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include 
+# source code with syntax highlighting in the LaTeX output. 
+# Note that which sources are shown also depends on other settings 
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the 
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See 
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition that 
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all references to function-like macros 
+# that are alone on a line, have an all uppercase name, and do not end with a 
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each 
+# tag file the location of the external documentation should be added. The 
+# format of a tag file without this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths 
+# or URLs. Note that each tag file must have a unique name (where the name does 
+# NOT include the path). If a tag file is not located in the directory in which 
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option also works with HAVE_DOT disabled, but it is recommended to 
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = NO
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is 
+# allowed to run in parallel. When set to 0 (the default) doxygen will 
+# base this on the number of processors available in the system. You can set it 
+# explicitly to a value larger than 0 to get control over the balance 
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS        = 0
+
+# By default doxygen will use the Helvetica font for all dot files that 
+# doxygen generates. When you want a differently looking font you can specify 
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find 
+# the font, which can be done by putting it in a standard location or by setting 
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the 
+# directory containing the font.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. 
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the Helvetica font. 
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to 
+# set the path where dot can find it.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside 
+# the class node. If there are many fields or methods and many nodes the 
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS 
+# threshold limits the number of items for each type to make the size more 
+# managable. Set this to 0 for no limit. Note that the threshold may be 
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = YES
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include 
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are svg, png, jpg, or gif. 
+# If left blank png will be used. If you choose svg you need to set 
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files 
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to 
+# enable generation of interactive SVG images that allow zooming and panning. 
+# Note that this requires a modern browser other than Internet Explorer. 
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you 
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files 
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG        = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that 
+# contain msc files that are included in the documentation (see the 
+# \mscfile command).
+
+MSCFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 44
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, because dot on Windows does not 
+# seem to support this out of the box. Warning: Depending on the platform used, 
+# enabling this option may lead to badly anti-aliased labels on the edges of 
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/mbed-coap/sn_coap_header.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+ * \file sn_coap_header.h
+ *
+ * \brief CoAP C-library User header interface header file
+ */
+
+#ifndef SN_COAP_HEADER_H_
+#define SN_COAP_HEADER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Handle structure */
+struct coap_s;
+
+/* * * * * * * * * * * * * * */
+/* * * * ENUMERATIONS  * * * */
+/* * * * * * * * * * * * * * */
+
+/**
+ * \brief Enumeration for CoAP Version
+ */
+typedef enum coap_version_ {
+    COAP_VERSION_1          = 0x40,
+    COAP_VERSION_UNKNOWN    = 0xFF
+} coap_version_e;
+
+/**
+ * \brief Enumeration for CoAP Message type, used in CoAP Header
+ */
+typedef enum sn_coap_msg_type_ {
+    COAP_MSG_TYPE_CONFIRMABLE       = 0x00, /**< Reliable Request messages */
+    COAP_MSG_TYPE_NON_CONFIRMABLE   = 0x10, /**< Non-reliable Request and Response messages */
+    COAP_MSG_TYPE_ACKNOWLEDGEMENT   = 0x20, /**< Response to a Confirmable Request  */
+    COAP_MSG_TYPE_RESET             = 0x30  /**< Answer a Bad Request */
+} sn_coap_msg_type_e;
+
+/**
+ * \brief Enumeration for CoAP Message code, used in CoAP Header
+ */
+typedef enum sn_coap_msg_code_ {
+    COAP_MSG_CODE_EMPTY                                 = 0,
+    COAP_MSG_CODE_REQUEST_GET                           = 1,
+    COAP_MSG_CODE_REQUEST_POST                          = 2,
+    COAP_MSG_CODE_REQUEST_PUT                           = 3,
+    COAP_MSG_CODE_REQUEST_DELETE                        = 4,
+
+    COAP_MSG_CODE_RESPONSE_CREATED                      = 65,
+    COAP_MSG_CODE_RESPONSE_DELETED                      = 66,
+    COAP_MSG_CODE_RESPONSE_VALID                        = 67,
+    COAP_MSG_CODE_RESPONSE_CHANGED                      = 68,
+    COAP_MSG_CODE_RESPONSE_CONTENT                      = 69,
+    COAP_MSG_CODE_RESPONSE_CONTINUE                     = 95,
+    COAP_MSG_CODE_RESPONSE_BAD_REQUEST                  = 128,
+    COAP_MSG_CODE_RESPONSE_UNAUTHORIZED                 = 129,
+    COAP_MSG_CODE_RESPONSE_BAD_OPTION                   = 130,
+    COAP_MSG_CODE_RESPONSE_FORBIDDEN                    = 131,
+    COAP_MSG_CODE_RESPONSE_NOT_FOUND                    = 132,
+    COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED           = 133,
+    COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE               = 134,
+    COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE    = 136,
+    COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED          = 140,
+    COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE     = 141,
+    COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT   = 143,
+    COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR        = 160,
+    COAP_MSG_CODE_RESPONSE_NOT_IMPLEMENTED              = 161,
+    COAP_MSG_CODE_RESPONSE_BAD_GATEWAY                  = 162,
+    COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE          = 163,
+    COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT              = 164,
+    COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED       = 165
+} sn_coap_msg_code_e;
+
+/**
+ * \brief Enumeration for CoAP Option number, used in CoAP Header
+ */
+typedef enum sn_coap_option_numbers_ {
+    COAP_OPTION_IF_MATCH        = 1,
+    COAP_OPTION_URI_HOST        = 3,
+    COAP_OPTION_ETAG            = 4,
+    COAP_OPTION_IF_NONE_MATCH   = 5,
+    COAP_OPTION_OBSERVE         = 6,
+    COAP_OPTION_URI_PORT        = 7,
+    COAP_OPTION_LOCATION_PATH   = 8,
+    COAP_OPTION_URI_PATH        = 11,
+    COAP_OPTION_CONTENT_FORMAT  = 12,
+    COAP_OPTION_MAX_AGE         = 14,
+    COAP_OPTION_URI_QUERY       = 15,
+    COAP_OPTION_ACCEPT          = 17,
+    COAP_OPTION_LOCATION_QUERY  = 20,
+    COAP_OPTION_BLOCK2          = 23,
+    COAP_OPTION_BLOCK1          = 27,
+    COAP_OPTION_SIZE2           = 28,
+    COAP_OPTION_PROXY_URI       = 35,
+    COAP_OPTION_PROXY_SCHEME    = 39,
+    COAP_OPTION_SIZE1           = 60
+//  128 =   (Reserved)
+//  132 =   (Reserved)
+//  136 =   (Reserved)
+} sn_coap_option_numbers_e;
+
+/**
+ * \brief Enumeration for CoAP Content Format codes
+ */
+typedef enum sn_coap_content_format_ {
+    COAP_CT_NONE                = -1, // internal
+    COAP_CT_TEXT_PLAIN          = 0,
+    COAP_CT_LINK_FORMAT         = 40,
+    COAP_CT_XML                 = 41,
+    COAP_CT_OCTET_STREAM        = 42,
+    COAP_CT_EXI                 = 47,
+    COAP_CT_JSON                = 50,
+    COAP_CT__MAX                = 0xffff
+} sn_coap_content_format_e;
+
+/**
+ * \brief Enumeration for CoAP Observe option values
+ *
+ * draft-ietf-core-observe-16
+ */
+typedef enum sn_coap_observe_ {
+    COAP_OBSERVE_NONE           = -1, // internal
+
+    // Values for GET requests
+    COAP_OBSERVE_REGISTER       = 0,
+    COAP_OBSERVE_DEREGISTER     = 1,
+
+    // In responses, value is a 24-bit opaque sequence number
+    COAP_OBSERVE__MAX   = 0xffffff
+} sn_coap_observe_e;
+
+/**
+ * \brief Enumeration for CoAP status, used in CoAP Header
+ */
+typedef enum sn_coap_status_ {
+    COAP_STATUS_OK                             = 0, /**< Default value is OK */
+    COAP_STATUS_PARSER_ERROR_IN_HEADER         = 1, /**< CoAP will send Reset message to invalid message sender */
+    COAP_STATUS_PARSER_DUPLICATED_MSG          = 2, /**< CoAP will send Acknowledgement message to duplicated message sender */
+    COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING = 3, /**< User will get whole message after all message blocks received.
+                                                         User must release messages with this status. */
+    COAP_STATUS_PARSER_BLOCKWISE_ACK           = 4, /**< Acknowledgement for sent Blockwise message received */
+    COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED  = 5, /**< Blockwise message received but not supported by compiling switch */
+    COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED  = 6, /**< Blockwise message fully received and returned to app.
+                                                         User must take care of releasing whole payload of the blockwise messages */
+    COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED = 7, /**< When re-transmissions have been done and ACK not received, CoAP library calls
+                                                         RX callback with this status */
+
+    COAP_STATUS_BUILDER_BLOCK_SENDING_FAILED   = 8, /**< Blockwise message sending timeout.
+                                                         The msg_id in sn_coap_hdr_s* parameter of RX callback is set to the same value
+                                                         as in the first block sent, and parameter sn_nsdl_addr_s* is set as NULL.  */
+    COAP_STATUS_BUILDER_BLOCK_SENDING_DONE     = 9  /**< Blockwise message sending, last block sent.
+                                                         The msg_id in sn_coap_hdr_s* parameter of RX callback is set to the same value
+                                                         as in the first block sent, and parameter sn_nsdl_addr_s* is set as NULL. */
+
+} sn_coap_status_e;
+
+
+/* * * * * * * * * * * * * */
+/* * * * STRUCTURES  * * * */
+/* * * * * * * * * * * * * */
+
+/**
+ * \brief Structure for CoAP Options
+ */
+typedef struct sn_coap_options_list_ {
+    uint8_t         etag_len;           /**< 1-8 bytes. Repeatable */
+    unsigned int    use_size1:1;
+    unsigned int    use_size2:1;
+
+    uint16_t    proxy_uri_len;      /**< 1-1034 bytes. */
+    uint16_t    uri_host_len;       /**< 1-255 bytes. */
+    uint16_t    location_path_len;  /**< 0-255 bytes. Repeatable */
+    uint16_t    location_query_len; /**< 0-255 bytes. Repeatable */
+    uint16_t    uri_query_len;      /**< 1-255 bytes. Repeatable */
+
+    sn_coap_content_format_e accept; /**< Value 0-65535. COAP_CT_NONE if not used */
+
+    uint32_t    max_age;            /**< Value in seconds (default is 60) */
+    uint32_t    size1;              /**< 0-4 bytes. */
+    uint32_t    size2;              /**< 0-4 bytes. */
+    int32_t     uri_port;           /**< Value 0-65535. -1 if not used */
+    int32_t     observe;            /**< Value 0-0xffffff. -1 if not used */
+    int32_t     block1;             /**< Value 0-0xffffff. -1 if not used. Not for user */
+    int32_t     block2;             /**< Value 0-0xffffff. -1 if not used. Not for user */
+
+    uint8_t    *proxy_uri_ptr;      /**< Must be set to NULL if not used */
+    uint8_t    *etag_ptr;           /**< Must be set to NULL if not used */
+    uint8_t    *uri_host_ptr;       /**< Must be set to NULL if not used */
+    uint8_t    *location_path_ptr;  /**< Must be set to NULL if not used */
+    uint8_t    *location_query_ptr; /**< Must be set to NULL if not used */
+    uint8_t    *uri_query_ptr;      /**< Must be set to NULL if not used */
+} sn_coap_options_list_s;
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+/* !!! Main CoAP message struct !!! */
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+/**
+ * \brief Main CoAP message struct
+ */
+typedef struct sn_coap_hdr_ {
+    uint8_t                 token_len;          /**< 1-8 bytes. */
+
+    sn_coap_status_e        coap_status;        /**< Used for telling to User special cases when parsing message */
+    sn_coap_msg_code_e      msg_code;           /**< Empty: 0; Requests: 1-31; Responses: 64-191 */
+
+    sn_coap_msg_type_e      msg_type;           /**< Confirmable, Non-Confirmable, Acknowledgement or Reset */
+    sn_coap_content_format_e content_format;    /**< Set to COAP_CT_NONE if not used */
+
+    uint16_t                msg_id;             /**< Message ID. Parser sets parsed message ID, builder sets message ID of built coap message */
+    uint16_t                uri_path_len;       /**< 0-255 bytes. Repeatable. */
+    uint16_t                payload_len;        /**< Must be set to zero if not used */
+
+    uint8_t                *token_ptr;          /**< Must be set to NULL if not used */
+    uint8_t                *uri_path_ptr;       /**< Must be set to NULL if not used. E.g: temp1/temp2 */
+    uint8_t                *payload_ptr;        /**< Must be set to NULL if not used */
+
+    /* Here are not so often used Options */
+    sn_coap_options_list_s *options_list_ptr;   /**< Must be set to NULL if not used */
+} sn_coap_hdr_s;
+
+/* * * * * * * * * * * * * * */
+/* * * * ENUMERATIONS  * * * */
+/* * * * * * * * * * * * * * */
+
+
+/**
+ * \brief Used protocol
+ */
+typedef enum sn_nsdl_capab_ {
+    SN_NSDL_PROTOCOL_HTTP           = 0x01,         /**< Unsupported */
+    SN_NSDL_PROTOCOL_HTTPS          = 0x02,         /**< Unsupported */
+    SN_NSDL_PROTOCOL_COAP           = 0x04          /**< Supported */
+} sn_nsdl_capab_e;
+
+/* * * * * * * * * * * * * */
+/* * * * STRUCTURES  * * * */
+/* * * * * * * * * * * * * */
+
+
+/**
+ * \brief Used for creating manually registration message with sn_coap_register()
+ */
+typedef struct registration_info_ {
+    uint8_t endpoint_len;
+    uint8_t endpoint_type_len;
+    uint16_t links_len;
+
+    uint8_t *endpoint_ptr;          /**< Endpoint name */
+    uint8_t *endpoint_type_ptr;     /**< Endpoint type */
+    uint8_t *links_ptr;             /**< Resource registration string */
+} registration_info_t;
+
+
+/**
+ * \brief Address type of given address
+ */
+typedef enum sn_nsdl_addr_type_ {
+    SN_NSDL_ADDRESS_TYPE_IPV6       = 0x01,         /**< Supported */
+    SN_NSDL_ADDRESS_TYPE_IPV4       = 0x02,         /**< Supported */
+    SN_NSDL_ADDRESS_TYPE_HOSTNAME   = 0x03,         /**< Unsupported */
+    SN_NSDL_ADDRESS_TYPE_NONE       = 0xFF
+} sn_nsdl_addr_type_e;
+
+/**
+ * \brief Address structure of Packet data
+ */
+typedef struct sn_nsdl_addr_ {
+    uint8_t                 addr_len;
+    sn_nsdl_addr_type_e     type;
+    uint16_t                port;
+    uint8_t                 *addr_ptr;
+} sn_nsdl_addr_s;
+
+
+/* * * * * * * * * * * * * * * * * * * * * * */
+/* * * * EXTERNAL FUNCTION PROTOTYPES  * * * */
+/* * * * * * * * * * * * * * * * * * * * * * */
+/**
+ * \fn sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr)
+ *
+ * \brief Parses CoAP message from given Packet data
+ *
+ * \param *handle Pointer to CoAP library handle
+ *
+ * \param packet_data_len is length of given Packet data to be parsed to CoAP message
+ *
+ * \param *packet_data_ptr is source for Packet data to be parsed to CoAP message
+ *
+ * \param *coap_version_ptr is destination for parsed CoAP specification version
+ *
+ * \return Return value is pointer to parsed CoAP message.\n
+ *         In following failure cases NULL is returned:\n
+ *          -Failure in given pointer (= NULL)\n
+ *          -Failure in memory allocation (malloc() returns NULL)
+ */
+extern sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr);
+
+/**
+ * \fn void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr)
+ *
+ * \brief Releases memory of given CoAP message
+ *
+ *        Note!!! Does not release Payload part
+ *
+ * \param *handle Pointer to CoAP library handle
+ *
+ * \param *freed_coap_msg_ptr is pointer to released CoAP message
+ */
+extern void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr);
+
+/**
+ * \fn int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr)
+ *
+ * \brief Builds an outgoing message buffer from a CoAP header structure.
+ *
+ * \param *dst_packet_data_ptr is pointer to allocated destination to built CoAP packet
+ *
+ * \param *src_coap_msg_ptr is pointer to source structure for building Packet data
+ *
+ * \return Return value is byte count of built Packet data. In failure cases:\n
+ *          -1 = Failure in given CoAP header structure\n
+ *          -2 = Failure in given pointer (= NULL)
+ */
+extern int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr);
+
+/**
+ * \fn uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr)
+ *
+ * \brief Calculates needed Packet data memory size for given CoAP message
+ *
+ * \param *src_coap_msg_ptr is pointer to data which needed Packet
+ *          data length is calculated
+ *
+ * \return Return value is count of needed memory as bytes for build Packet data
+ *          Null if failed
+ */
+extern uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr);
+
+/**
+ * \fn int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr,  uint16_t blockwise_size)
+ *
+ * \brief Builds an outgoing message buffer from a CoAP header structure.
+ *
+ * \param *dst_packet_data_ptr is pointer to allocated destination to built CoAP packet
+ *
+ * \param *src_coap_msg_ptr is pointer to source structure for building Packet data
+ *
+ * \param blockwise_payload_size Blockwise message maximum payload size
+ *
+ * \return Return value is byte count of built Packet data. In failure cases:\n
+ *          -1 = Failure in given CoAP header structure\n
+ *          -2 = Failure in given pointer (= NULL)
+ */
+extern int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size);
+
+/**
+ * \fn uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size)
+ *
+ * \brief Calculates needed Packet data memory size for given CoAP message
+ *
+ * \param *src_coap_msg_ptr is pointer to data which needed Packet
+ *          data length is calculated
+ * \param blockwise_payload_size Blockwise message maximum payload size
+ *
+ * \return Return value is count of needed memory as bytes for build Packet data
+ *          Null if failed
+ */
+extern uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size);
+
+/**
+ * \fn sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)
+ *
+ * \brief Prepares generic response packet from a request packet. This function allocates memory for the resulting sn_coap_hdr_s
+ *
+ * \param *handle Pointer to CoAP library handle
+ * \param *coap_packet_ptr The request packet pointer
+ * \param msg_code response messages code
+ *
+ * \return *coap_packet_ptr The allocated and pre-filled response packet pointer
+ *          NULL    Error in parsing the request
+ *
+ */
+extern sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code);
+
+/**
+ * \brief Initialise a message structure to empty
+ *
+ * \param *coap_msg_ptr is pointer to CoAP message to initialise
+ *
+ * \return Return value is pointer passed in
+ */
+extern sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr);
+
+/**
+ * \brief Allocate an empty message structure
+ *
+ * \param *handle Pointer to CoAP library handle
+ *
+ * \return Return value is pointer to an empty CoAP message.\n
+ *         In following failure cases NULL is returned:\n
+ *          -Failure in given pointer (= NULL)\n
+ *          -Failure in memory allocation (malloc() returns NULL)
+ */
+extern sn_coap_hdr_s *sn_coap_parser_alloc_message(struct coap_s *handle);
+
+/**
+ * \brief Allocates and initializes options list structure
+ *
+ * \param *handle Pointer to CoAP library handle
+ * \param *coap_msg_ptr is pointer to CoAP message that will contain the options
+ *
+ * If the message already has a pointer to an option structure, that pointer
+ * is returned, rather than a new structure being allocated.
+ *
+ * \return Return value is pointer to the CoAP options structure.\n
+ *         In following failure cases NULL is returned:\n
+ *          -Failure in given pointer (= NULL)\n
+ *          -Failure in memory allocation (malloc() returns NULL)
+ */
+extern sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_coap_hdr_s *coap_msg_ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SN_COAP_HEADER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/mbed-coap/sn_coap_protocol.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+ * \file sn_coap_protocol.h
+ *
+ * \brief CoAP C-library User protocol interface header file
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SN_COAP_PROTOCOL_H_
+#define SN_COAP_PROTOCOL_H_
+
+#include "sn_coap_header.h"
+
+/**
+ * \fn struct coap_s *sn_coap_protocol_init(void* (*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void*),
+        uint8_t (*used_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *),
+        int8_t (*used_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *)
+ *
+ * \brief Initializes CoAP Protocol part. When using libNsdl, sn_nsdl_init() calls this function.
+ *
+ * \param *used_malloc_func_ptr is function pointer for used memory allocation function.
+ *
+ * \param *used_free_func_ptr is function pointer for used memory free function.
+ *
+ * \param *used_tx_callback_ptr function callback pointer to tx function for sending coap messages
+ *
+ * \param *used_rx_callback_ptr used to return CoAP header struct with status COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED
+ *        when re-sendings exceeded. If set to NULL, no error message is returned.
+ *
+ * \return  Pointer to handle when success
+ *          Null if failed
+ */
+
+extern struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *),
+        uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *),
+        int8_t (*used_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *));
+
+/**
+ * \fn int8_t sn_coap_protocol_destroy(void)
+ *
+ * \brief Frees all memory from CoAP protocol part
+ *
+ * \param *handle Pointer to CoAP library handle
+ *
+ * \return Return value is always 0
+ */
+extern int8_t sn_coap_protocol_destroy(struct coap_s *handle);
+
+/**
+ * \fn int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, void *param)
+ *
+ * \brief Builds Packet data from given CoAP header structure to be sent
+ *
+ * \param *dst_addr_ptr is pointer to destination address where CoAP message
+ *        will be sent (CoAP builder needs that information for message resending purposes)
+ *
+ * \param *dst_packet_data_ptr is pointer to destination of built Packet data
+ *
+ * \param *src_coap_msg_ptr is pointer to source of built Packet data
+ *
+ * \param param void pointer that will be passed to tx/rx function callback when those are called.
+ *
+ * \return Return value is byte count of built Packet data.\n
+ *         Note: If message is blockwised, all payload is not sent at the same time\n
+ *         In failure cases:\n
+ *          -1 = Failure in CoAP header structure\n
+ *          -2 = Failure in given pointer (= NULL)\n
+ *          -3 = Failure in Reset message\n
+ *          -4 = Failure in Resending message store\n
+ *         If there is not enough memory (or User given limit exceeded) for storing
+ *         resending messages, situation is ignored.
+ */
+extern int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, void *param);
+
+/**
+ * \fn sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t packet_data_len, uint8_t *packet_data_ptr)
+ *
+ * \brief Parses received CoAP message from given Packet data
+ *
+ * \param *src_addr_ptr is pointer to source address of received CoAP message
+ *        (CoAP parser needs that information for Message acknowledgement)
+ *
+ * \param *handle Pointer to CoAP library handle
+ *
+ * \param packet_data_len is length of given Packet data to be parsed to CoAP message
+ *
+ * \param *packet_data_ptr is pointer to source of Packet data to be parsed to CoAP message
+ *
+ * \param param void pointer that will be passed to tx/rx function callback when those are called.
+ *
+ * \return Return value is pointer to parsed CoAP message structure. This structure includes also coap_status field.\n
+ *         In following failure cases NULL is returned:\n
+ *          -Given NULL pointer\n
+ *          -Failure in parsed header of non-confirmable message\ŋ
+ *          -Out of memory (malloc() returns NULL)
+ */
+extern sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t packet_data_len, uint8_t *packet_data_ptr, void *);
+
+/**
+ * \fn int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time)
+ *
+ * \brief Sends CoAP messages from re-sending queue, if there is any.
+ *        Cleans also old messages from the duplication list and from block receiving list
+ *
+ *        This function can be called e.g. once in a second but also more frequently.
+ *
+ * \param *handle Pointer to CoAP library handle
+ *
+ * \param current_time is System time in seconds. This time is
+ *        used for message re-sending timing and to identify old saved data.
+ *
+ * \return  0 if success
+ *          -1 if failed
+ */
+
+extern int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time);
+
+/**
+ * \fn int8_t sn_coap_protocol_set_block_size(uint16_t block_size)
+ *
+ * \brief If block transfer is enabled, this function changes the block size.
+ *
+ * \param uint16_t block_size maximum size of CoAP payload. Valid sizes are 16, 32, 64, 128, 256, 512 and 1024 bytes
+ * \return  0 = success
+ *          -1 = failure
+ */
+extern int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size);
+
+/**
+ * \fn int8_t sn_coap_protocol_set_duplicate_buffer_size(uint8_t message_count)
+ *
+ * \brief If dublicate message detection is enabled, this function changes buffer size.
+ *
+ * \param uint8_t message_count max number of messages saved for duplicate control
+ * \return  0 = success
+ *          -1 = failure
+ */
+extern int8_t sn_coap_protocol_set_duplicate_buffer_size(struct coap_s *handle, uint8_t message_count);
+
+/**
+ * \fn int8_t sn_coap_protocol_set_retransmission_parameters(uint8_t resending_count, uint8_t resending_intervall)
+ *
+ * \brief  If re-transmissions are enabled, this function changes resending count and interval.
+ *
+ * \param uint8_t resending_count max number of resendings for message
+ * \param uint8_t resending_intervall message resending intervall in seconds
+ * \return  0 = success, -1 = failure
+ */
+extern int8_t sn_coap_protocol_set_retransmission_parameters(struct coap_s *handle,
+        uint8_t resending_count, uint8_t resending_interval);
+
+/**
+ * \fn int8_t sn_coap_protocol_set_retransmission_buffer(uint8_t buffer_size_messages, uint16_t buffer_size_bytes)
+ *
+ * \brief If re-transmissions are enabled, this function changes message retransmission queue size.
+ *  Set size to '0' to disable feature. If both are set to '0', then re-sendings are disabled.
+ *
+ * \param uint8_t buffer_size_messages queue size - maximum number of messages to be saved to queue
+ * \param uint8_t buffer_size_bytes queue size - maximum size of messages saved to queue
+ * \return  0 = success, -1 = failure
+ */
+extern int8_t sn_coap_protocol_set_retransmission_buffer(struct coap_s *handle,
+        uint8_t buffer_size_messages, uint16_t buffer_size_bytes);
+
+/**
+ * \fn void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle)
+ *
+ * \param *handle Pointer to CoAP library handle
+ *
+ * \brief If re-transmissions are enabled, this function removes all messages from the retransmission queue.
+ */
+extern void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle);
+
+/**
+ * \fn sn_coap_protocol_block_remove
+ *
+ * \brief Remove saved block data. Can be used to remove the data from RAM to enable storing it to other place.
+ *
+ * \param handle Pointer to CoAP library handle
+ * \param source_address Addres from where the block has been received.
+ * \param payload_length Length of the coap payload of the block.
+ * \param payload Coap payload of the block.
+ *
+ */
+extern void sn_coap_protocol_block_remove(struct coap_s *handle, sn_nsdl_addr_s *source_address, uint16_t payload_length, void *payload);
+
+/**
+ * \fn sn_coap_protocol_remove_sent_blockwise_message
+ *
+ * \brief Remove sent blockwise message from the linked list.
+ *
+ * \param handle Pointer to CoAP library handle
+ * \param message_id Message id to be removed.
+ *
+ */
+extern void sn_coap_protocol_remove_sent_blockwise_message(struct coap_s *handle, uint16_t message_id);
+
+/**
+ * \fn void sn_coap_protocol_delete_retransmission(struct coap_s *handle)
+ *
+ * \param *handle Pointer to CoAP library handle
+ * \msg_id message ID to be removed
+ * \return returns 0 when success, -1 for invalid parameter, -2 if message was not found
+ *
+ * \brief If re-transmissions are enabled, this function removes message from retransmission buffer.
+ */
+extern int8_t sn_coap_protocol_delete_retransmission(struct coap_s *handle, uint16_t msg_id);
+
+/**
+ * \fn int8_t sn_coap_convert_block_size(uint16_t block_size)
+ *
+ * \brief Utility function to convert block size.
+ *
+ * \param block_size Block size to convert.
+ *
+ * \return Value of range 0 - 6
+ */
+extern int8_t sn_coap_convert_block_size(uint16_t block_size);
+
+/**
+ * \fn int8_t sn_coap_protocol_handle_block2_response_internally(struct coap_s *handle, uint8_t handle_response)
+ *
+ * \brief This function change the state whether CoAP library sends the block 2 response automatically or not.
+ *
+ * \param *handle Pointer to CoAP library handle
+ * \param handle_response 1 if CoAP library handles the response sending otherwise 0.
+ *
+ * \return  0 = success, -1 = failure
+ */
+extern int8_t sn_coap_protocol_handle_block2_response_internally(struct coap_s *handle, uint8_t handle_response);
+
+/**
+ * \fn void sn_coap_protocol_clear_sent_blockwise_messages(struct coap_s *handle)
+ *
+ * \brief This function clears all the sent blockwise messages from the linked list.
+ *
+ * \param *handle Pointer to CoAP library handle
+ */
+extern void sn_coap_protocol_clear_sent_blockwise_messages(struct coap_s *handle);
+
+/**
+ * \fn void sn_coap_protocol_send_rst(struct coap_s *handle, uint16_t msg_id, sn_nsdl_addr_s *addr_ptr, void *param)
+ *
+ * \brief This function sends a RESET message.
+ *
+ * \param *handle Pointer to CoAP library handle
+ * \param msg_id Message id.
+ * \param addr_ptr Pointer to destination address where CoAP message will be sent
+ * \param param Pointer that will be passed to tx function callback
+ */
+extern void sn_coap_protocol_send_rst(struct coap_s *handle, uint16_t msg_id, sn_nsdl_addr_s *addr_ptr, void *param);
+
+/**
+ * \fn uint16_t sn_coap_protocol_get_configured_blockwise_size(struct coap_s *handle)
+ *
+ * \brief Get configured CoAP payload blockwise size
+ *
+ * \param *handle Pointer to CoAP library handle
+ */
+extern uint16_t sn_coap_protocol_get_configured_blockwise_size(struct coap_s *handle);
+
+#endif /* SN_COAP_PROTOCOL_H_ */
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/mbed-coap/sn_config.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifndef SN_CONFIG_H
+#define SN_CONFIG_H
+
+/**
+* \brief Configuration options (set of defines and values)
+*
+*  This lists set of compile-time options that needs to be used to enable
+*  or disable features selectively, and set the values for the mandatory
+*  parameters.
+*/
+
+/**
+ * \def SN_COAP_DUPLICATION_MAX_MSGS_COUNT
+ * \brief For Message duplication detection
+ * Init value for the maximum count of messages to be stored for duplication detection
+ * Setting of this value to 0 will disable duplication check, also reduce use of ROM memory
+ * Default is set to 1.
+ */
+#undef SN_COAP_DUPLICATION_MAX_MSGS_COUNT   /* 1 */
+
+/**
+ * \def SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+ *
+ * \brief For Message blockwising
+ * Init value for the maximum payload size to be sent and received at one blockwise message
+ * Setting of this value to 0 with SN_COAP_BLOCKWISE_ENABLED will disable this feature, and
+ * also reduce use of ROM memory.
+ * Note: This define is common for both received and sent Blockwise messages
+ */
+#undef SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE   /* 0 */ // < Must be 2^x and x is at least 4. Suitable values: 0, 16, 32, 64, 128, 256, 512 and 1024
+
+/**
+ * \def COAP_DISABLE_OBS_FEATURE
+ *
+ * \brief Disables CoAP 'obs' sending feature
+ * as part of registration message, this might be
+ * needed to be enabled for some strict LWM2M server implementation.
+ * By default, this feature is disabled.
+ */
+#undef COAP_DISABLE_OBS_FEATURE
+
+/**
+ * \def SN_COAP_DISABLE_RESENDINGS
+ *
+ * \brief Disables resending feature. Resending feature should not be needed
+ * when using CoAP with TCP transport for example. By default resendings are
+ * enabled. Set to 1 to disable.
+ */
+#undef SN_COAP_DISABLE_RESENDINGS          /* 0 */ // < Default re-sending are not disabled. Set to 1 to disable re-sendings
+
+/**
+ * \def SN_COAP_RESENDING_QUEUE_SIZE_MSGS
+ *
+ * \brief Sets the number of messages stored
+ * in the resending queue. Default is 2
+ */
+#undef SN_COAP_RESENDING_QUEUE_SIZE_MSGS    /* 2  */ // < Default re-sending queue size - defines how many messages can be stored. Setting this to 0 disables feature
+
+/**
+ * \def SN_COAP_RESENDING_QUEUE_SIZE_BYTES
+ *
+ * \brief Sets the size of the re-sending buffer.
+ * Setting this to 0 disables this feature.
+ * By default, this feature is disabled.
+ */
+#undef SN_COAP_RESENDING_QUEUE_SIZE_BYTES   /* 0  */ // Default re-sending queue size - defines size of the re-sending buffer. Setting this to 0 disables feature
+
+/**
+ * \def SN_COAP_MAX_INCOMING_MESSAGE_SIZE
+ *
+ * \brief Sets the maximum size (in bytes) that
+ * mbed Client will allow to be handled while
+ * receiving big payload in blockwise mode.
+ * Application can set this value based on their
+ * available storage capability.
+ * By default, maximum size is UINT16_MAX, 65535 bytes.
+ */
+#undef SN_COAP_MAX_INCOMING_MESSAGE_SIZE    /* UINT16_MAX */
+
+/**
+ * \def SN_COAP_MAX_NONBLOCKWISE_PAYLOAD_SIZE
+ * \brief Sets the maximum payload size allowed before blockwising the message.
+ * This option should only be used when using TCP and TLS as transport
+ * with known maximum fragment size. This optimizes the number of messages
+ * if it is possible to send larger than 1kB messages without blockwise transfer.
+ * If payload length is larger than SN_COAP_MAX_NONBLOCKWISE_PAYLOAD_SIZE
+ * it will be sent using blockwise transfer.
+ * By default, this feature is disabled, 0 disables the feature, set to positive
+ * value larger than SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE to enable.
+ * Note that value should be less than transport layer maximum fragment size.
+ * Note that value has no effect if blockwise transfer is disabled.
+ */
+#undef SN_COAP_MAX_NONBLOCKWISE_PAYLOAD_SIZE        /* 0 */
+
+/**
+ * \def SN_COAP_BLOCKWISE_ENABLED
+ * \brief Enables the blockwise functionality in CoAP library also when blockwise payload
+ * size is set to '0' in  SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE.
+ */
+#undef SN_COAP_BLOCKWISE_ENABLED                    /* 0 */
+
+#ifdef MBED_CLIENT_USER_CONFIG_FILE
+#include MBED_CLIENT_USER_CONFIG_FILE
+#endif
+
+#endif // SN_CONFIG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/source/include/sn_coap_header_internal.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+ * \file sn_coap_header_internal.h
+ *
+ * \brief Header file for CoAP Header part
+ *
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SN_COAP_HEADER_INTERNAL_H_
+#define SN_COAP_HEADER_INTERNAL_H_
+
+
+/* * * * * * * * * * * */
+/* * * * DEFINES * * * */
+/* * * * * * * * * * * */
+
+#define COAP_VERSION                                COAP_VERSION_1 /* Tells which IETF CoAP specification version the CoAP message supports. */
+/* This value is written to CoAP message header part. */
+
+/* CoAP Header defines */
+#define COAP_HEADER_LENGTH                          4   /* Fixed Header length of CoAP message as bytes */
+#define COAP_HEADER_VERSION_MASK                    0xC0
+#define COAP_HEADER_MSG_TYPE_MASK                   0x30
+#define COAP_HEADER_TOKEN_LENGTH_MASK               0x0F
+#define COAP_HEADER_MSG_ID_MSB_SHIFT                8
+
+/* CoAP Options defines */
+#define COAP_OPTIONS_OPTION_NUMBER_SHIFT            4
+
+/* * * * * * * * * * * * * * */
+/* * * * ENUMERATIONS  * * * */
+/* * * * * * * * * * * * * * */
+
+/* * * * * * * * * * * * * */
+/* * * * STRUCTURES  * * * */
+/* * * * * * * * * * * * * */
+
+/**
+ * \brief This structure is returned by sn_coap_exec() for sending
+ */
+typedef struct sn_nsdl_transmit_ {
+    sn_nsdl_addr_s         *dst_addr_ptr;
+
+    sn_nsdl_capab_e         protocol;
+
+    uint16_t                packet_len;
+    uint8_t                *packet_ptr;
+} sn_nsdl_transmit_s;
+
+/* * * * * * * * * * * * * * * * * * * * * * */
+/* * * * EXTERNAL FUNCTION PROTOTYPES  * * * */
+/* * * * * * * * * * * * * * * * * * * * * * */
+extern int8_t           sn_coap_header_validity_check(sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version);
+
+#endif /* SN_COAP_HEADER_INTERNAL_H_ */
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/source/include/sn_coap_protocol_internal.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+ * \file sn_coap_protocol_internal.h
+ *
+ * \brief Header file for CoAP Protocol part
+ *
+ */
+
+#ifndef SN_COAP_PROTOCOL_INTERNAL_H_
+#define SN_COAP_PROTOCOL_INTERNAL_H_
+
+#include "ns_list.h"
+#include "sn_coap_header_internal.h"
+#include "mbed-coap/sn_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct sn_coap_hdr_;
+
+/* * * * * * * * * * * */
+/* * * * DEFINES * * * */
+/* * * * * * * * * * * */
+
+/* * For Message resending * */
+#ifdef SN_COAP_DISABLE_RESENDINGS
+#define ENABLE_RESENDINGS                               0 /* Disable resendings */
+#else
+#define ENABLE_RESENDINGS                               1   /**< Enable / Disable resending from library in building */
+#endif
+
+#define SN_COAP_RESENDING_MAX_COUNT                     3   /**< Default number of re-sendings  */
+
+#ifdef YOTTA_CFG_COAP_RESENDING_QUEUE_SIZE_MSGS
+#define SN_COAP_RESENDING_QUEUE_SIZE_MSGS YOTTA_CFG_COAP_RESENDING_QUEUE_SIZE_MSGS
+#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_RESENDING_QUEUE_SIZE_MSGS
+#define SN_COAP_RESENDING_QUEUE_SIZE_MSGS MBED_CONF_MBED_CLIENT_SN_COAP_RESENDING_QUEUE_SIZE_MSGS
+#endif
+
+#ifndef SN_COAP_RESENDING_QUEUE_SIZE_MSGS
+#define SN_COAP_RESENDING_QUEUE_SIZE_MSGS               2   /**< Default re-sending queue size - defines how many messages can be stored. Setting this to 0 disables feature */
+#endif
+
+#ifdef YOTTA_CFG_COAP_RESENDING_QUEUE_SIZE_BYTES
+#define SN_COAP_RESENDING_QUEUE_SIZE_BYTES YOTTA_CFG_COAP_RESENDING_QUEUE_SIZE_BYTES
+#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_RESENDING_QUEUE_SIZE_BYTES
+#define SN_COAP_RESENDING_QUEUE_SIZE_BYTES MBED_CONF_MBED_CLIENT_SN_COAP_RESENDING_QUEUE_SIZE_BYTES
+#endif
+
+#ifndef SN_COAP_RESENDING_QUEUE_SIZE_BYTES
+#define SN_COAP_RESENDING_QUEUE_SIZE_BYTES              0   /**< Default re-sending queue size - defines size of the re-sending buffer. Setting this to 0 disables feature */
+#endif
+
+#define DEFAULT_RESPONSE_TIMEOUT                        10  /**< Default re-sending timeout as seconds */
+
+/* These parameters sets maximum values application can set with API */
+#define SN_COAP_MAX_ALLOWED_RESENDING_COUNT             6   /**< Maximum allowed count of re-sending */
+#define SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_MSGS    6   /**< Maximum allowed number of saved re-sending messages */
+#define SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_BYTES   512 /**< Maximum allowed size of re-sending buffer */
+#define SN_COAP_MAX_ALLOWED_RESPONSE_TIMEOUT            40  /**< Maximum allowed re-sending timeout */
+
+#define RESPONSE_RANDOM_FACTOR                          1.5   /**< Resending random factor, value is specified in IETF CoAP specification */
+
+/* * For Message duplication detecting * */
+
+/* Init value for the maximum count of messages to be stored for duplication detection          */
+/* Setting of this value to 0 will disable duplication check, also reduce use of ROM memory     */
+
+// Keep the old flag to maintain backward compatibility
+#ifndef SN_COAP_DUPLICATION_MAX_MSGS_COUNT
+#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT              0
+#endif
+
+#ifdef YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT
+#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT YOTTA_CFG_COAP_DUPLICATION_MAX_MSGS_COUNT
+#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_DUPLICATION_MAX_MSGS_COUNT
+#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT MBED_CONF_MBED_CLIENT_SN_COAP_DUPLICATION_MAX_MSGS_COUNT
+#endif
+
+
+
+/* Maximum allowed number of saved messages for duplicate searching */
+#define SN_COAP_MAX_ALLOWED_DUPLICATION_MESSAGE_COUNT   6
+
+/* Maximum time in seconds of messages to be stored for duplication detection */
+#define SN_COAP_DUPLICATION_MAX_TIME_MSGS_STORED    60 /* RESPONSE_TIMEOUT * RESPONSE_RANDOM_FACTOR * (2 ^ MAX_RETRANSMIT - 1) + the expected maximum round trip time */
+
+/* * For Message blockwising * */
+
+/* Init value for the maximum payload size to be sent and received at one blockwise message                         */
+/* Setting of this value to 0 will disable this feature, and also reduce use of ROM memory                          */
+/* Note: This define is common for both received and sent Blockwise messages                                        */
+
+#ifdef YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+#define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE YOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+#define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE MBED_CONF_MBED_CLIENT_SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+#endif
+
+#ifndef SN_COAP_BLOCKWISE_ENABLED
+#define SN_COAP_BLOCKWISE_ENABLED                   0  /**< Enable blockwise */
+#endif
+
+#ifndef SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+#define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE          0  /**< Must be 2^x and x is at least 4. Suitable values: 0, 16, 32, 64, 128, 256, 512 and 1024 */
+#endif
+
+#ifndef SN_COAP_MAX_NONBLOCKWISE_PAYLOAD_SIZE
+#define SN_COAP_MAX_NONBLOCKWISE_PAYLOAD_SIZE       0
+#endif
+
+#ifdef MBED_CONF_MBED_CLIENT_SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED
+#define SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED MBED_CONF_MBED_CLIENT_SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED
+#endif
+
+#ifndef SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED
+#define SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED      60 /**< Maximum time in seconds of data (messages and payload) to be stored for blockwising */
+#endif
+
+#ifdef YOTTA_CFG_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE
+#define SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE YOTTA_CFG_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE
+#elif defined MBED_CONF_MBED_CLIENT_SN_COAP_MAX_INCOMING_MESSAGE_SIZE
+#define SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE MBED_CONF_MBED_CLIENT_SN_COAP_MAX_INCOMING_MESSAGE_SIZE
+#endif
+
+#ifndef SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE
+#define SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE UINT16_MAX
+#endif
+
+/* * For Option handling * */
+#define COAP_OPTION_MAX_AGE_DEFAULT                 60 /**< Default value of Max-Age if option not present */
+#define COAP_OPTION_URI_PORT_NONE                   (-1) /**< Internal value to represent no Uri-Port option */
+#define COAP_OPTION_BLOCK_NONE                      (-1) /**< Internal value to represent no Block1/2 option */
+
+
+int8_t prepare_blockwise_message(struct coap_s *handle, struct sn_coap_hdr_ *coap_hdr_ptr);
+
+/* Structure which is stored to Linked list for message sending purposes */
+typedef struct coap_send_msg_ {
+    uint8_t             resending_counter;  /* Tells how many times message is still tried to resend */
+    uint32_t            resending_time;     /* Tells next resending time */
+
+    sn_nsdl_transmit_s *send_msg_ptr;
+
+    struct coap_s       *coap;              /* CoAP library handle */
+    void                *param;             /* Extra parameter that will be passed to TX/RX callback functions */
+
+    ns_list_link_t      link;
+} coap_send_msg_s;
+
+typedef NS_LIST_HEAD(coap_send_msg_s, link) coap_send_msg_list_t;
+
+/* Structure which is stored to Linked list for message duplication detection purposes */
+typedef struct coap_duplication_info_ {
+    uint32_t            timestamp; /* Tells when duplication information is stored to Linked list */
+    uint16_t            msg_id;
+    uint16_t            packet_len;
+    uint8_t             *packet_ptr;
+    struct coap_s       *coap;  /* CoAP library handle */
+    sn_nsdl_addr_s      *address;
+    void                *param;
+    ns_list_link_t      link;
+} coap_duplication_info_s;
+
+typedef NS_LIST_HEAD(coap_duplication_info_s, link) coap_duplication_info_list_t;
+
+/* Structure which is stored to Linked list for blockwise messages sending purposes */
+typedef struct coap_blockwise_msg_ {
+    uint32_t            timestamp;  /* Tells when Blockwise message is stored to Linked list */
+
+    sn_coap_hdr_s       *coap_msg_ptr;
+    struct coap_s       *coap;      /* CoAP library handle */
+
+    void                *param;
+    uint16_t            msg_id;
+
+    ns_list_link_t      link;
+} coap_blockwise_msg_s;
+
+typedef NS_LIST_HEAD(coap_blockwise_msg_s, link) coap_blockwise_msg_list_t;
+
+/* Structure which is stored to Linked list for blockwise messages receiving purposes */
+typedef struct coap_blockwise_payload_ {
+    uint32_t            timestamp; /* Tells when Payload is stored to Linked list */
+
+    uint8_t             addr_len;
+    uint8_t             *addr_ptr;
+    uint16_t            port;
+    uint32_t            block_number;
+    uint8_t             *token_ptr;
+    uint8_t             token_len;
+
+    uint16_t            payload_len;
+    uint8_t             *payload_ptr;
+    struct coap_s       *coap;  /* CoAP library handle */
+
+    ns_list_link_t     link;
+} coap_blockwise_payload_s;
+
+typedef NS_LIST_HEAD(coap_blockwise_payload_s, link) coap_blockwise_payload_list_t;
+
+struct coap_s {
+    void *(*sn_coap_protocol_malloc)(uint16_t);
+    void (*sn_coap_protocol_free)(void *);
+
+    uint8_t (*sn_coap_tx_callback)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *);
+    int8_t (*sn_coap_rx_callback)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *);
+
+    #if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */
+        coap_send_msg_list_t linked_list_resent_msgs; /* Active resending messages are stored to this Linked list */
+        uint16_t count_resent_msgs;
+    #endif
+
+    #if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */
+        coap_duplication_info_list_t  linked_list_duplication_msgs; /* Messages for duplicated messages detection is stored to this Linked list */
+        uint16_t                      count_duplication_msgs;
+    #endif
+
+    #if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwise is not enabled, this part of code will not be compiled */
+        coap_blockwise_msg_list_t     linked_list_blockwise_sent_msgs; /* Blockwise message to to be sent is stored to this Linked list */
+        coap_blockwise_payload_list_t linked_list_blockwise_received_payloads; /* Blockwise payload to to be received is stored to this Linked list */
+    #endif
+
+    uint32_t system_time;    /* System time seconds */
+    uint16_t sn_coap_block_data_size;
+    uint8_t sn_coap_resending_queue_msgs;
+    uint32_t sn_coap_resending_queue_bytes;
+    uint8_t sn_coap_resending_count;
+    uint8_t sn_coap_resending_intervall;
+    uint8_t sn_coap_duplication_buffer_size;
+    uint8_t sn_coap_internal_block2_resp_handling; /* If this is set then coap itself sends a next GET request automatically */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SN_COAP_PROTOCOL_INTERNAL_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/source/sn_coap_builder.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1091 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+ * \file sn_coap_builder.c
+ *
+ * \brief CoAP Message builder
+ *
+ * Functionality: Builds CoAP message
+ *
+ */
+
+/* * * * * * * * * * * * * * */
+/* * * * INCLUDE FILES * * * */
+/* * * * * * * * * * * * * * */
+
+#include <string.h> /* For memset() and memcpy() */
+
+#include "ns_types.h"
+#include "mbed-coap/sn_coap_header.h"
+#include "sn_coap_header_internal.h"
+#include "sn_coap_protocol_internal.h"
+#include "mbed-trace/mbed_trace.h"
+
+#define TRACE_GROUP "coap"
+/* * * * LOCAL FUNCTION PROTOTYPES * * * */
+static int8_t   sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr);
+static int8_t   sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr);
+static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option);
+static int16_t  sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len, uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number);
+static int16_t  sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option, uint16_t *previous_option_number);
+static uint8_t  sn_coap_builder_options_build_add_uint_option(uint8_t **dst_packet_data_pptr, uint32_t value, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number);
+static uint8_t  sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option);
+static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option);
+static int16_t  sn_coap_builder_options_get_option_part_position(uint16_t query_len, uint8_t *query_ptr, uint8_t query_index, sn_coap_option_numbers_e option);
+static void     sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr);
+static uint8_t  sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr/*, uint8_t block_option*/);
+
+sn_coap_hdr_s *sn_coap_build_response(struct coap_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)
+{
+    sn_coap_hdr_s *coap_res_ptr;
+
+    if (!coap_packet_ptr || !handle) {
+        return NULL;
+    }
+
+    coap_res_ptr = sn_coap_parser_alloc_message(handle);
+    if (!coap_res_ptr) {
+        tr_error("sn_coap_build_response - failed to allocate message!");
+        return NULL;
+    }
+
+    if (msg_code == COAP_MSG_CODE_REQUEST_GET) {
+        // Blockwise message response is new GET
+        coap_res_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
+        coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
+        /* msg_id needs to be set by the caller in this case */
+    }
+    else if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
+        coap_res_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
+        coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
+        coap_res_ptr->msg_id = coap_packet_ptr->msg_id;
+    }
+    else if (coap_packet_ptr->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE) {
+        coap_res_ptr->msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE;
+        coap_res_ptr->msg_code = (sn_coap_msg_code_e)msg_code;
+        /* msg_id needs to be set by the caller in this case */
+    }
+    else {
+        handle->sn_coap_protocol_free( coap_res_ptr );
+        return NULL;
+    }
+
+    if (coap_packet_ptr->token_ptr) {
+        coap_res_ptr->token_len = coap_packet_ptr->token_len;
+        coap_res_ptr->token_ptr = handle->sn_coap_protocol_malloc(coap_res_ptr->token_len);
+        if (!coap_res_ptr->token_ptr) {
+            tr_error("sn_coap_build_response - failed to allocate token!");
+            handle->sn_coap_protocol_free(coap_res_ptr);
+            return NULL;
+        }
+        memcpy(coap_res_ptr->token_ptr, coap_packet_ptr->token_ptr, coap_res_ptr->token_len);
+    }
+    return coap_res_ptr;
+}
+
+int16_t sn_coap_builder(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr)
+{
+    return sn_coap_builder_2(dst_packet_data_ptr, src_coap_msg_ptr, SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE);
+}
+
+int16_t sn_coap_builder_2(uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size)
+{
+    uint8_t *base_packet_data_ptr = NULL;
+
+    /* * * * Check given pointers  * * * */
+    if (dst_packet_data_ptr == NULL || src_coap_msg_ptr == NULL) {
+        return -2;
+    }
+
+    /* Initialize given Packet data memory area with zero values */
+    uint16_t dst_byte_count_to_be_built = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, blockwise_payload_size);
+    if (!dst_byte_count_to_be_built) {
+        tr_error("sn_coap_builder_2 - failed to allocate message!");
+        return -1;
+    }
+
+    memset(dst_packet_data_ptr, 0, dst_byte_count_to_be_built);
+
+    /* * * * Store base (= original) destination Packet data pointer for later usage * * * */
+    base_packet_data_ptr = dst_packet_data_ptr;
+
+    /* * * * * * * * * * * * * * * * * * */
+    /* * * * Header part building  * * * */
+    /* * * * * * * * * * * * * * * * * * */
+    if (sn_coap_builder_header_build(&dst_packet_data_ptr, src_coap_msg_ptr) != 0) {
+        /* Header building failed */
+        tr_error("sn_coap_builder_2 - header building failed!");
+        return -1;
+    }
+
+    /* If else than Reset message because Reset message must be empty */
+    if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET) {
+        /* * * * * * * * * * * * * * * * * * */
+        /* * * * Options part building * * * */
+        /* * * * * * * * * * * * * * * * * * */
+        sn_coap_builder_options_build(&dst_packet_data_ptr, src_coap_msg_ptr);
+
+        /* * * * * * * * * * * * * * * * * * */
+        /* * * * Payload part building * * * */
+        /* * * * * * * * * * * * * * * * * * */
+        sn_coap_builder_payload_build(&dst_packet_data_ptr, src_coap_msg_ptr);
+    }
+    /* * * * Return built Packet data length * * * */
+    return (dst_packet_data_ptr - base_packet_data_ptr);
+}
+uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_msg_ptr)
+{
+    return sn_coap_builder_calc_needed_packet_data_size_2(src_coap_msg_ptr, SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE);
+}
+
+uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size)
+{
+    (void)blockwise_payload_size;
+    uint16_t returned_byte_count = 0;
+
+    if (!src_coap_msg_ptr) {
+        return 0;
+    }
+    /* * * * *  HEADER * * * * */
+
+    /* Header size is fixed */
+    returned_byte_count = COAP_HEADER_LENGTH;
+
+    /* * * * * OPTIONS * * * * */
+
+    /* If else than Reset message because Reset message must be empty */
+    if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET) {
+        uint16_t repeatable_option_size = 0;
+        /* TOKEN - Length is 1-8 bytes */
+        if (src_coap_msg_ptr->token_ptr != NULL) {
+            if (src_coap_msg_ptr->token_len > 8 || src_coap_msg_ptr->token_len < 1) { /* Check that option is not longer than defined */
+                tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - token too large!");
+                return 0;
+            }
+
+            returned_byte_count += src_coap_msg_ptr->token_len;
+        }
+        /* URI PATH - Repeatable option. Length of one option is 0-255 */
+        if (src_coap_msg_ptr->uri_path_ptr != NULL) {
+            repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->uri_path_len,
+                                     src_coap_msg_ptr->uri_path_ptr, COAP_OPTION_URI_PATH);
+            if (repeatable_option_size) {
+                returned_byte_count += repeatable_option_size;
+            } else {
+                tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - uri path size failed!");
+                return 0;
+            }
+        }
+
+        uint16_t tempInt = 0;
+        /* CONTENT FORMAT - An integer option, up to 2 bytes */
+        if (src_coap_msg_ptr->content_format != COAP_CT_NONE) {
+            if ((uint32_t) src_coap_msg_ptr->content_format > 0xffff) {
+                tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - content format too large!");
+                return 0;
+            }
+
+            returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->content_format, COAP_OPTION_CONTENT_FORMAT, &tempInt);
+        }
+        /* If options list pointer exists */
+        if (src_coap_msg_ptr->options_list_ptr != NULL) {
+            /* ACCEPT - An integer option, up to 2 bytes */
+            if (src_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE) {
+                if ((uint32_t) src_coap_msg_ptr->options_list_ptr->accept > 0xffff) {
+                    tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - accept too large!");
+                    return 0;
+                }
+
+                returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->accept, COAP_OPTION_ACCEPT, &tempInt);
+            }
+            /* MAX AGE - An integer option, omitted for default. Up to 4 bytes */
+            if (src_coap_msg_ptr->options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) {
+                returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->max_age, COAP_OPTION_MAX_AGE, &tempInt);
+            }
+            /* PROXY URI - Length of this option is  1-1034 bytes */
+            if (src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) {
+                if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 1 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 12) {            /* Add option header byte(s) - depending of option length */
+                    returned_byte_count++;
+                }
+
+                else if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 13 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 269) {
+                    returned_byte_count += 2;
+                }
+
+                else if (src_coap_msg_ptr->options_list_ptr->proxy_uri_len >= 270 && src_coap_msg_ptr->options_list_ptr->proxy_uri_len <= 1034) {
+                    returned_byte_count += 3;
+                }
+
+                else {
+                    tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - proxy uri too large!");
+                    return 0;
+                }
+
+                /* Add needed memory for Option value */
+                returned_byte_count += src_coap_msg_ptr->options_list_ptr->proxy_uri_len;
+            }
+            /* ETAG - Repeatable option. Length of this option is 1-8 bytes*/
+            if (src_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) {
+                repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->etag_len,
+                                         src_coap_msg_ptr->options_list_ptr->etag_ptr, COAP_OPTION_ETAG);
+                if (repeatable_option_size) {
+                    returned_byte_count += repeatable_option_size;
+                } else {
+                    tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - etag too large!");
+                    return 0;
+                }
+            }
+            /* URI HOST - Length of this option is 1-255 bytes */
+            if (src_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) {
+                if (src_coap_msg_ptr->options_list_ptr->uri_host_len > 0 && src_coap_msg_ptr->options_list_ptr->uri_host_len <= 12) {
+                    returned_byte_count++;
+                }
+
+                else if (src_coap_msg_ptr->options_list_ptr->uri_host_len >= 13 && src_coap_msg_ptr->options_list_ptr->uri_host_len <= 255) {
+                    returned_byte_count += 2;
+                }
+
+                else {
+                    tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - uri host too large!");
+                    return 0;
+                }
+
+                returned_byte_count += src_coap_msg_ptr->options_list_ptr->uri_host_len;
+            }
+            /* LOCATION PATH - Repeatable option. Length of this option is 0-255 bytes*/
+            if (src_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) {
+                repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->location_path_len,
+                                         src_coap_msg_ptr->options_list_ptr->location_path_ptr, COAP_OPTION_LOCATION_PATH);
+                if (repeatable_option_size) {
+                    returned_byte_count += repeatable_option_size;
+                } else {
+                    tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - location path too large!");
+                    return 0;
+                }
+            }
+            /* URI PORT - An integer option, up to 2 bytes */
+            if (src_coap_msg_ptr->options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
+                if ((uint32_t) src_coap_msg_ptr->options_list_ptr->uri_port > 0xffff) {
+                    tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - uri port too large!");
+                    return 0;
+                }
+                returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->uri_port, COAP_OPTION_URI_PORT, &tempInt);
+            }
+            /* lOCATION QUERY - Repeatable option. Length of this option is 0-255 bytes */
+            if (src_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) {
+                repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->location_query_len,
+                                         src_coap_msg_ptr->options_list_ptr->location_query_ptr, COAP_OPTION_LOCATION_QUERY);
+                if (repeatable_option_size) {
+                    returned_byte_count += repeatable_option_size;
+                } else {
+                    tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - location query too large!");
+                    return 0;
+                }
+            }
+            /* OBSERVE - An integer option, up to 3 bytes */
+            if (src_coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
+                if ((uint32_t) src_coap_msg_ptr->options_list_ptr->observe > 0xffffff) {
+                    return 0;
+                }
+                returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->observe, COAP_OPTION_OBSERVE, &tempInt);
+            }
+            /* URI QUERY - Repeatable option. Length of this option is 1-255 */
+            if (src_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) {
+                repeatable_option_size = sn_coap_builder_options_calc_option_size(src_coap_msg_ptr->options_list_ptr->uri_query_len,
+                                         src_coap_msg_ptr->options_list_ptr->uri_query_ptr, COAP_OPTION_URI_QUERY);
+                if (repeatable_option_size) {
+                    returned_byte_count += repeatable_option_size;
+                } else {
+                    tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - observe too large!");
+                    return 0;
+                }
+            }
+
+            /* BLOCK 1 - An integer option, up to 3 bytes */
+            if (src_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
+                if ((uint32_t) src_coap_msg_ptr->options_list_ptr->block1 > 0xffffff) {
+                    tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - block1 too large!");
+                    return 0;
+                }
+                returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->block1, COAP_OPTION_BLOCK1, &tempInt);
+            }
+            /* SIZE1 - Length of this option is 0-4 bytes */
+            if (src_coap_msg_ptr->options_list_ptr->use_size1) {
+                returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->size1, COAP_OPTION_SIZE1, &tempInt);
+            }
+            /* BLOCK 2 - An integer option, up to 3 bytes */
+            if (src_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
+                if ((uint32_t) src_coap_msg_ptr->options_list_ptr->block2 > 0xffffff) {
+                    tr_error("sn_coap_builder_calc_needed_packet_data_size_2 - block2 too large!");
+                    return 0;
+                }
+                returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->block2, COAP_OPTION_BLOCK2, &tempInt);
+            }
+            /* SIZE2 - Length of this option is 0-4 bytes */
+            if (src_coap_msg_ptr->options_list_ptr->use_size2) {
+                returned_byte_count += sn_coap_builder_options_build_add_uint_option(NULL, src_coap_msg_ptr->options_list_ptr->size2, COAP_OPTION_SIZE2, &tempInt);
+            }
+        }
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+        if ((src_coap_msg_ptr->payload_len > SN_COAP_MAX_NONBLOCKWISE_PAYLOAD_SIZE) &&
+            (src_coap_msg_ptr->payload_len > blockwise_payload_size) &&
+            (blockwise_payload_size > 0)) {
+            returned_byte_count += blockwise_payload_size;
+        } else {
+            returned_byte_count += src_coap_msg_ptr->payload_len;
+        }
+#else
+        returned_byte_count += src_coap_msg_ptr->payload_len;
+#endif
+        if (src_coap_msg_ptr->payload_len) {
+            returned_byte_count ++;    /* For payload marker */
+        }
+        returned_byte_count += sn_coap_builder_options_calculate_jump_need(src_coap_msg_ptr/*, 0*/);
+    }
+    return returned_byte_count;
+}
+/**
+ * \fn static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr, uint8_t block_option)
+ *
+ * \brief Checks if there is need for option jump
+ *
+ * \param  *src_coap_msg_ptr is source of checked CoAP message
+ *
+ * \param  block option marks if block option is to be added to message later. 0 = no block option, 1 = block1 and 2 = block2
+ *
+ * \return Returns bytes needed for jumping
+ */
+
+static uint8_t sn_coap_builder_options_calculate_jump_need(sn_coap_hdr_s *src_coap_msg_ptr/*, uint8_t block_option*/)
+{
+    uint8_t previous_option_number = 0;
+    uint8_t needed_space           = 0;
+
+    if (src_coap_msg_ptr->options_list_ptr != NULL) {
+        /* If option numbers greater than 12 is not used, then jumping is not needed */
+        //TODO: Check if this is really needed! Does it enhance perf? If not -> remove
+        if (!src_coap_msg_ptr->options_list_ptr->uri_query_ptr       &&
+                src_coap_msg_ptr->options_list_ptr->accept == COAP_CT_NONE &&
+                !src_coap_msg_ptr->options_list_ptr->location_query_ptr &&
+                src_coap_msg_ptr->options_list_ptr->block2 == COAP_OPTION_BLOCK_NONE &&
+                src_coap_msg_ptr->options_list_ptr->block1 == COAP_OPTION_BLOCK_NONE &&
+                !src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr      &&
+                src_coap_msg_ptr->options_list_ptr->max_age == COAP_OPTION_MAX_AGE_DEFAULT &&
+                !src_coap_msg_ptr->options_list_ptr->use_size1          &&
+                !src_coap_msg_ptr->options_list_ptr->use_size2) {
+            return 0;
+        }
+
+        if (src_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) {
+            previous_option_number = (COAP_OPTION_URI_HOST);
+        }
+
+        if (src_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) {
+            previous_option_number = (COAP_OPTION_ETAG);
+        }
+
+        if (src_coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
+            previous_option_number = (COAP_OPTION_OBSERVE);
+        }
+
+        if (src_coap_msg_ptr->options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
+            previous_option_number = (COAP_OPTION_URI_PORT);
+        }
+
+        if (src_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) {
+            previous_option_number = (COAP_OPTION_LOCATION_PATH);
+        }
+
+        if (src_coap_msg_ptr->uri_path_ptr != NULL) {
+            previous_option_number = (COAP_OPTION_URI_PATH);
+        }
+        if (src_coap_msg_ptr->content_format != COAP_CT_NONE) {
+            previous_option_number = (COAP_OPTION_CONTENT_FORMAT);
+        }
+        if (src_coap_msg_ptr->options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) {
+            if ((COAP_OPTION_MAX_AGE - previous_option_number) > 12) {
+                needed_space += 1;
+            }
+            previous_option_number = (COAP_OPTION_MAX_AGE);
+        }
+
+        if (src_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) {
+            if ((COAP_OPTION_URI_QUERY - previous_option_number) > 12) {
+                needed_space += 1;
+            }
+            previous_option_number = (COAP_OPTION_URI_QUERY);
+        }
+        if (src_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE) {
+            if ((COAP_OPTION_ACCEPT - previous_option_number) > 12) {
+                needed_space += 1;
+            }
+            previous_option_number = (COAP_OPTION_ACCEPT);
+        }
+        if (src_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) {
+            if ((COAP_OPTION_LOCATION_QUERY - previous_option_number) > 12) {
+                needed_space += 1;
+            }
+            previous_option_number = (COAP_OPTION_LOCATION_QUERY);
+        }
+        if (src_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
+            if ((COAP_OPTION_BLOCK2 - previous_option_number) > 12 ){
+                needed_space += 1;
+            }
+            previous_option_number = (COAP_OPTION_BLOCK2);
+        }
+        if (src_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
+            if ((COAP_OPTION_BLOCK1 - previous_option_number) > 12 ){
+                needed_space += 1;
+            }
+            previous_option_number = (COAP_OPTION_BLOCK1);
+        }
+        if (src_coap_msg_ptr->options_list_ptr->use_size2) {
+            if ((COAP_OPTION_SIZE2 - previous_option_number) > 12) {
+                needed_space += 1;
+            }
+            previous_option_number = (COAP_OPTION_SIZE2);
+        }
+        if (src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) {
+            if ((COAP_OPTION_PROXY_URI - previous_option_number) > 12) {
+                needed_space += 1;
+            }
+            if ((COAP_OPTION_PROXY_URI - previous_option_number) > 269) { //Can not happen
+                needed_space += 1;
+            }
+            previous_option_number = (COAP_OPTION_PROXY_URI);
+        }
+        if (src_coap_msg_ptr->options_list_ptr->use_size1 ) {
+            if ((COAP_OPTION_SIZE1 - previous_option_number) > 12) {
+                needed_space += 1;
+            }
+            previous_option_number = (COAP_OPTION_SIZE1);
+        }
+    }
+
+    else {
+        if (src_coap_msg_ptr->uri_path_ptr != 0) {
+            previous_option_number = (COAP_OPTION_URI_PATH);
+        }
+
+        if (src_coap_msg_ptr->content_format != COAP_CT_NONE) {
+            previous_option_number = (COAP_OPTION_CONTENT_FORMAT);
+        }
+    }
+    return needed_space;
+}
+
+/**
+ * \fn static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
+ *
+ * \brief Builds Header part of Packet data
+ *
+ * \param **dst_packet_data_pptr is destination for built Packet data
+ *
+ * \param *src_coap_msg_ptr is source for building Packet data
+ *
+ * \return Return value is 0 in ok case and -1 in failure case
+ **************************************************************************** */
+static int8_t sn_coap_builder_header_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
+{
+    /* * * * Check validity of Header values * * * */
+    if (sn_coap_header_validity_check(src_coap_msg_ptr, COAP_VERSION) != 0) {
+        tr_error("sn_coap_builder_header_build - header build failed!");
+        return -1;
+    }
+
+    /* * * Add CoAP Version * * */
+    **dst_packet_data_pptr += COAP_VERSION;
+
+    /* * * Add Message type * * */
+    **dst_packet_data_pptr += src_coap_msg_ptr->msg_type;
+
+    /* * * Add Token length * * */
+    **dst_packet_data_pptr += (src_coap_msg_ptr->token_len);
+
+    (*dst_packet_data_pptr) ++;
+    /* * * Add Message code * * */
+    **dst_packet_data_pptr = src_coap_msg_ptr->msg_code;
+    (*dst_packet_data_pptr) ++;
+
+    /* * * Add Message ID * * */
+    **dst_packet_data_pptr = (uint8_t)(src_coap_msg_ptr->msg_id >> COAP_HEADER_MSG_ID_MSB_SHIFT); /* MSB part */
+    (*dst_packet_data_pptr) ++;
+    **dst_packet_data_pptr = (uint8_t)src_coap_msg_ptr->msg_id;                                   /* LSB part */
+    (*dst_packet_data_pptr) ++;
+
+    /* Success */
+    return 0;
+}
+
+/**
+ * \fn static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
+ *
+ * \brief Builds Options part of Packet data
+ *
+ * \param **dst_packet_data_pptr is destination for built Packet data
+ *
+ * \param *src_coap_msg_ptr is source for building Packet data
+ *
+ * \return Return value is 0 in every case
+ */
+static int8_t sn_coap_builder_options_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
+{
+    /* * * * Check if Options are used at all  * * * */
+    if (src_coap_msg_ptr->uri_path_ptr == NULL && src_coap_msg_ptr->token_ptr == NULL &&
+            src_coap_msg_ptr->content_format == COAP_CT_NONE && src_coap_msg_ptr->options_list_ptr == NULL) {
+        tr_error("sn_coap_builder_options_build - options not used!");
+        return 0;
+    }
+
+    /* * * * First add Token option  * * * */
+    if (src_coap_msg_ptr->token_len && src_coap_msg_ptr->token_ptr) {
+        memcpy(*dst_packet_data_pptr, src_coap_msg_ptr->token_ptr, src_coap_msg_ptr->token_len);
+    }
+    (*dst_packet_data_pptr) += src_coap_msg_ptr->token_len;
+
+    /* Then build rest of the options */
+
+    /* * * * Initialize previous Option number for new built message * * * */
+    uint16_t previous_option_number = 0;
+
+    //missing: COAP_OPTION_IF_MATCH, COAP_OPTION_IF_NONE_MATCH, COAP_OPTION_SIZE
+
+    /* Check if less used options are used at all */
+    if (src_coap_msg_ptr->options_list_ptr != NULL) {
+        /* * * * Build Uri-Host option * * * */
+        sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->uri_host_len,
+                     src_coap_msg_ptr->options_list_ptr->uri_host_ptr, COAP_OPTION_URI_HOST, &previous_option_number);
+
+        /* * * * Build ETag option  * * * */
+        sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->etag_ptr,
+                     (uint16_t *)&src_coap_msg_ptr->options_list_ptr->etag_len, COAP_OPTION_ETAG, &previous_option_number);
+
+        /* * * * Build Observe option  * * * * */
+        if (src_coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
+            sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->observe,
+                         COAP_OPTION_OBSERVE, &previous_option_number);
+        }
+
+        /* * * * Build Uri-Port option * * * */
+        if (src_coap_msg_ptr->options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
+            sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->uri_port,
+                         COAP_OPTION_URI_PORT, &previous_option_number);
+        }
+
+        /* * * * Build Location-Path option  * * * */
+        sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->location_path_ptr,
+                     &src_coap_msg_ptr->options_list_ptr->location_path_len, COAP_OPTION_LOCATION_PATH, &previous_option_number);
+    }
+    /* * * * Build Uri-Path option * * * */
+    sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->uri_path_ptr,
+             &src_coap_msg_ptr->uri_path_len, COAP_OPTION_URI_PATH, &previous_option_number);
+
+    /* * * * Build Content-Type option * * * */
+    if (src_coap_msg_ptr->content_format != COAP_CT_NONE) {
+        sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->content_format,
+                     COAP_OPTION_CONTENT_FORMAT, &previous_option_number);
+    }
+
+    if (src_coap_msg_ptr->options_list_ptr != NULL) {
+        /* * * * Build Max-Age option  * * * */
+        if (src_coap_msg_ptr->options_list_ptr->max_age != COAP_OPTION_MAX_AGE_DEFAULT) {
+            sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->max_age,
+                         COAP_OPTION_MAX_AGE, &previous_option_number);
+        }
+
+        /* * * * Build Uri-Query option  * * * * */
+        sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->uri_query_ptr,
+                     &src_coap_msg_ptr->options_list_ptr->uri_query_len, COAP_OPTION_URI_QUERY, &previous_option_number);
+
+        /* * * * Build Accept option  * * * * */
+        if (src_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE) {
+            sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->accept,
+                         COAP_OPTION_ACCEPT, &previous_option_number);
+        }
+    }
+
+    if (src_coap_msg_ptr->options_list_ptr != NULL) {
+        /* * * * Build Location-Query option * * * */
+        sn_coap_builder_options_build_add_multiple_option(dst_packet_data_pptr, &src_coap_msg_ptr->options_list_ptr->location_query_ptr,
+                     &src_coap_msg_ptr->options_list_ptr->location_query_len, COAP_OPTION_LOCATION_QUERY, &previous_option_number);
+
+        /* * * * Build Block2 option * * * * */
+        if (src_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
+            sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->block2,
+                         COAP_OPTION_BLOCK2, &previous_option_number);
+        }
+
+        /* * * * Build Block1 option * * * * */
+        if (src_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
+            sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->block1,
+                         COAP_OPTION_BLOCK1, &previous_option_number);
+        }
+
+        /* * * * Build Size2 option * * * */
+        if (src_coap_msg_ptr->options_list_ptr->use_size2) {
+            sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->size2,
+                         COAP_OPTION_SIZE2, &previous_option_number);
+        }
+
+        /* * * * Build Proxy-Uri option * * * */
+        sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->proxy_uri_len,
+                     src_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, COAP_OPTION_PROXY_URI, &previous_option_number);
+
+
+        /* * * * Build Size1 option * * * */
+        if (src_coap_msg_ptr->options_list_ptr->use_size1) {
+            sn_coap_builder_options_build_add_uint_option(dst_packet_data_pptr, src_coap_msg_ptr->options_list_ptr->size1,
+                         COAP_OPTION_SIZE1, &previous_option_number);
+        }
+    }
+
+    /* Success */
+    return 0;
+}
+
+/**
+ * \fn static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_value_len, uint8_t *option_value_ptr, sn_coap_option_numbers_e option_number)
+ *
+ * \brief Adds Options part of Packet data
+ *
+ * \param **dst_packet_data_pptr is destination for built Packet data
+ *
+ * \param option_value_len is Option value length to be added
+ *
+ * \param *option_value_ptr is pointer to Option value data to be added
+ *
+ * \param option_number is Option number to be added
+ *
+ * \return Return value is 0 if option was not added, 1 if added
+ */
+static int16_t sn_coap_builder_options_build_add_one_option(uint8_t **dst_packet_data_pptr, uint16_t option_len,
+        uint8_t *option_ptr, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number)
+{
+    /* Check if there is option at all */
+    if (option_ptr != NULL) {
+        uint16_t option_delta;
+
+        option_delta = (option_number - *previous_option_number);
+
+        /* * * Build option header * * */
+
+        /* First option length without extended part */
+        if (option_len <= 12) {
+            **dst_packet_data_pptr = option_len;
+        }
+
+        else if (option_len > 12 && option_len < 269) {
+            **dst_packet_data_pptr = 0x0D;
+        }
+
+        else if (option_len >= 269) {
+            **dst_packet_data_pptr = 0x0E;
+        }
+
+        /* Then option delta with extensions, and move pointer */
+        if (option_delta <= 12) {
+            **dst_packet_data_pptr += (option_delta << 4);
+            *dst_packet_data_pptr += 1;
+        }
+
+        else if (option_delta > 12 && option_delta < 269) {
+            **dst_packet_data_pptr += 0xD0;
+            option_delta -= 13;
+
+            *(*dst_packet_data_pptr + 1) = (uint8_t)option_delta;
+            *dst_packet_data_pptr += 2;
+        }
+        //This is currently dead code (but possibly needed in future)
+        else if (option_delta >= 269) {
+            **dst_packet_data_pptr += 0xE0;
+            option_delta -= 269;
+
+            *(*dst_packet_data_pptr + 2) = (uint8_t)option_delta;
+            *(*dst_packet_data_pptr + 1) = (option_delta >> 8);
+            *dst_packet_data_pptr += 3;
+        }
+
+        /* Now option length extensions, if needed */
+        if (option_len > 12 && option_len < 269) {
+            **dst_packet_data_pptr = (uint8_t)(option_len - 13);
+            *dst_packet_data_pptr += 1;
+        }
+
+        else if (option_len >= 269) {
+            *(*dst_packet_data_pptr + 1) = (uint8_t)(option_len - 269);
+            **dst_packet_data_pptr = ((option_len - 269) >> 8);
+            *dst_packet_data_pptr += 2;
+        }
+
+        *previous_option_number = option_number;
+
+        /* Write Option value */
+        memcpy(*dst_packet_data_pptr, option_ptr, option_len);
+
+        /* Increase destination Packet data pointer */
+        (*dst_packet_data_pptr) += option_len;
+
+        return 1;
+    }
+
+    /* Success */
+    return 0;
+}
+
+/**
+ * \brief Constructs a uint Options part of Packet data
+ *
+ * \param **dst_packet_data_pptr is destination for built Packet data; NULL
+ *        to compute size only.
+ *
+ * \param option_value is Option value to be added
+ *
+ * \param option_number is Option number to be added
+ *
+ * \return Return value is total option size, or -1 in write failure case
+ */
+static uint8_t sn_coap_builder_options_build_add_uint_option(uint8_t **dst_packet_data_pptr, uint32_t option_value, sn_coap_option_numbers_e option_number, uint16_t *previous_option_number)
+{
+    uint8_t payload[4];
+    uint8_t len = 0;
+    /* Construct the variable-length payload representing the value */
+    for (uint8_t i = 0; i < 4; i++) {
+        if (len > 0 || (option_value & 0xff000000)) {
+            payload[len++] = option_value >> 24;
+        }
+        option_value <<= 8;
+    }
+
+    /* If output pointer isn't NULL, write it out */
+    if (dst_packet_data_pptr) {
+        int16_t ret = sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, len, payload, option_number, previous_option_number);
+        /* Allow for failure returns when writing (why even permit failure returns?) */
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    /* Return the total option size */
+    return 1 + len;
+}
+
+/**
+ * \fn static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option)
+ *
+ * \brief Builds Option Uri-Query from given CoAP Header structure to Packet data
+ *
+ * \param **dst_packet_data_pptr is destination for built Packet data
+ *
+ * \param uint8_t **src_pptr
+ *
+ *  \param uint16_t *src_len_ptr
+ *
+ *  \paramsn_coap_option_numbers_e option option to be added
+ *
+ * \return Return value is 0 always
+ */
+static int16_t sn_coap_builder_options_build_add_multiple_option(uint8_t **dst_packet_data_pptr, uint8_t **src_pptr, uint16_t *src_len_ptr, sn_coap_option_numbers_e option, uint16_t *previous_option_number)
+{
+    /* Check if there is option at all */
+    if (*src_pptr != NULL) {
+        uint8_t    *query_ptr               = *src_pptr;
+        uint8_t     query_part_count        = 0;
+        uint16_t    query_len               = *src_len_ptr;
+        uint8_t     i                       = 0;
+        uint16_t    query_part_offset       = 0;
+
+        /* Get query part count */
+        query_part_count = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option);
+
+        /* * * * Options by adding all parts to option * * * */
+        for (i = 0; i < query_part_count; i++) {
+            /* Get length of query part */
+            uint16_t one_query_part_len = sn_coap_builder_options_get_option_part_length_from_whole_option_string(query_len, query_ptr, i, option);
+
+            /* Get position of query part */
+            query_part_offset = sn_coap_builder_options_get_option_part_position(query_len, query_ptr, i, option);
+
+            /* Add Uri-query's one part to Options */
+            sn_coap_builder_options_build_add_one_option(dst_packet_data_pptr, one_query_part_len, *src_pptr + query_part_offset, option, previous_option_number);
+        }
+    }
+    /* Success */
+    return 0;
+}
+
+
+/**
+ * \fn static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option)
+ *
+ * \brief Calculates needed Packet data memory size for option
+ *
+ * \param path_len is length of calculated strting(s)
+ *
+ * \param *path_ptr is pointer to calculated options
+ *
+ * \return Return value is count of needed memory as bytes for Uri-query option
+ */
+static uint16_t sn_coap_builder_options_calc_option_size(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option)
+{
+    uint8_t     query_part_count    = sn_coap_builder_options_get_option_part_count(query_len, query_ptr, option);
+    uint8_t     i                   = 0;
+    uint16_t    ret_value           = 0;
+
+    /* * * * * * * * * * * * * * * * * * * * * * * * */
+    /* * * * Calculate Uri-query options length  * * */
+    /* * * * * * * * * * * * * * * * * * * * * * * * */
+    for (i = 0; i < query_part_count; i++) {
+        /* * * Length of Option number and Option value length * * */
+
+        /* Get length of Query part */
+        uint16_t one_query_part_len = sn_coap_builder_options_get_option_part_length_from_whole_option_string(query_len, query_ptr, i, option);
+
+        /* Check option length */
+        switch (option) {
+            case (COAP_OPTION_ETAG):            /* Length 1-8 */
+                if (one_query_part_len < 1 || one_query_part_len > 8) {
+                    return 0;
+                }
+                break;
+            case (COAP_OPTION_LOCATION_PATH):   /* Length 0-255 */
+            case (COAP_OPTION_URI_PATH):        /* Length 0-255 */
+            case (COAP_OPTION_LOCATION_QUERY):  /* Length 0-255 */
+                if (one_query_part_len > 255) {
+                    return 0;
+                }
+                break;
+            case (COAP_OPTION_URI_QUERY):       /* Length 1-255 */
+                if (one_query_part_len < 1 || one_query_part_len > 255) {
+                    return 0;
+                }
+                break;
+//            case (COAP_OPTION_ACCEPT):          /* Length 0-2 */
+//                if (one_query_part_len > 2) {
+//                    return 0;
+//                }
+//                break;
+            default:
+                break; //impossible scenario currently
+        }
+
+        /* Check if 4 bits are enough for writing Option value length */
+        if (one_query_part_len <= 12) {
+            /* 4 bits are enough for Option value length */
+            ret_value++;
+        } else if (one_query_part_len >= 13 && one_query_part_len < 269) {
+            /* Extra byte for Option value length is needed */
+            ret_value += 2;
+        }
+        //This can only happen if we are in default case above, currently is not happening
+        else if (one_query_part_len >= 270 && one_query_part_len < 1034) {
+            /* Extra bytes for Option value length is needed */
+            ret_value += 3;
+        }
+
+
+        /* * * Length of Option value * * */
+
+        /* Increase options length */
+        ret_value += one_query_part_len;
+    }
+
+    /* Success */
+    return ret_value;
+}
+
+
+
+/**
+ * \fn static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option)
+ *
+ * \brief Gets query part count from whole option string
+ *
+ * \param query_len is length of whole Path
+ *
+ * \param *query_ptr is pointer to the start of whole Path
+ *
+ * \return Return value is count of query parts
+ */
+static uint8_t sn_coap_builder_options_get_option_part_count(uint16_t query_len, uint8_t *query_ptr, sn_coap_option_numbers_e option)
+{
+    uint8_t  returned_query_count = 0;
+    uint16_t query_len_index      = 0;
+    uint8_t  char_to_search       = '&';
+
+    if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
+        char_to_search = '/';
+    }
+
+    /* Loop whole query and search '\0' characters (not first and last char) */
+    for (query_len_index = 1; query_len_index < query_len - 1; query_len_index++) {
+        /* If new query part starts */
+        if (*(query_ptr + query_len_index) == char_to_search) { /* If match */
+            returned_query_count++;
+        }
+    }
+
+    returned_query_count++;
+
+    return returned_query_count;
+}
+
+/**
+ * \fn static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len,
+                                                                             uint8_t *query_ptr,
+                                                                             uint8_t query_index, sn_coap_option_numbers_e option)
+ *
+ * \brief Gets one's query part length from whole query string
+ *
+ * \param query_len is length of whole string
+ *
+ * \param *query_ptr is pointer to the start of whole string
+ *
+ * \param query_index is query part index to be found
+ *
+ * \param sn_coap_option_numbers_e option is option number of the option
+ *
+ * \return Return value is length of query part
+ */
+static uint16_t sn_coap_builder_options_get_option_part_length_from_whole_option_string(uint16_t query_len, uint8_t *query_ptr,
+        uint8_t query_index, sn_coap_option_numbers_e option)
+{
+    uint16_t returned_query_part_len = 0;
+    uint8_t  temp_query_index        = 0;
+    uint16_t query_len_index         = 0;
+    uint8_t  char_to_search          = '&';
+
+    if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
+        char_to_search = '/';
+    }
+
+    /* Loop whole query and search '\0' characters */
+    for (query_len_index = 0; query_len_index < query_len; query_len_index++) {
+        /* Store character to temp_char for helping debugging */
+        uint8_t temp_char = *query_ptr;
+
+        /* If new query part starts */
+        if (temp_char == char_to_search && returned_query_part_len > 0) { /* returned_query_part_len > 0 is for querys which start with "\0" */
+            /* If query part index is wanted */
+            if (temp_query_index == query_index) {
+                /* Return length of query part */
+                return returned_query_part_len;
+            } else {
+                /* Reset length of query part because wanted query part finding continues*/
+                returned_query_part_len = 0;
+            }
+
+            /* Next query part is looped */
+            temp_query_index++;
+        } else if (temp_char != char_to_search) { /* Else if query part continues */
+            /* Increase query part length */
+            returned_query_part_len++;
+        }
+
+        query_ptr++;
+    }
+
+    /* Return length of query part in cases that query part does not finish to '\0' character (last query part can be like that) */
+    return returned_query_part_len;
+}
+
+/**
+ * \fn static uint16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len,
+                                                               uint8_t *query_ptr,
+                                                               uint8_t query_index, sn_coap_option_numbers_e option)
+ *
+ * \brief Gets query part position in whole query
+ *
+ * \param query_len is length of whole query
+ *
+ * \param *query_ptr is pointer to the start of whole query
+ *
+ * \param query_index is query part index to be found
+ *
+ * \return Return value is position (= offset) of query part in whole query. In
+ *         fail cases -1 is returned.
+ */
+static int16_t sn_coap_builder_options_get_option_part_position(uint16_t query_len, uint8_t *query_ptr,
+        uint8_t query_index, sn_coap_option_numbers_e option)
+{
+    uint16_t returned_query_part_offset = 0;
+    uint8_t  temp_query_index           = 0;
+    uint16_t query_len_index            = 0;
+    uint8_t  char_to_search             = '&';
+
+    if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
+        char_to_search = '/';
+    }
+
+    if (query_index == 0) {
+        if (*query_ptr == 0 || *query_ptr == char_to_search) {
+            return 1;
+        } else {
+            return 0;
+        }
+    }
+
+    /* Loop whole query and search separator characters */
+    for (query_len_index = 0; query_len_index < query_len; query_len_index++) {
+        /* Store character to temp_char for helping debugging */
+        uint8_t temp_char = *query_ptr;
+
+        /* If new query part starts */
+        if (temp_char == char_to_search && returned_query_part_offset > 0) { /* returned_query_part_offset > 0 is for querys which start with searched char */
+            /* If query part index is wanted */
+            if (temp_query_index == (query_index - 1)) {
+                /* Return offset of query part */
+                return (returned_query_part_offset + 1); /* Plus one is for passing separator */
+            }
+
+            /* Next query part is looped */
+            temp_query_index++;
+        }
+
+        returned_query_part_offset++;
+
+        query_ptr++;
+    }
+
+    return -1; //Dead code?
+}
+
+
+/**
+ * \fn static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
+ *
+ * \brief Builds Options part of Packet data
+ *
+ * \param **dst_packet_data_pptr is destination for built Packet data
+ *
+ * \param *src_coap_msg_ptr is source for building Packet data
+ */
+static void sn_coap_builder_payload_build(uint8_t **dst_packet_data_pptr, sn_coap_hdr_s *src_coap_msg_ptr)
+{
+    /* Check if Payload is used at all */
+    if (src_coap_msg_ptr->payload_len && src_coap_msg_ptr->payload_ptr != NULL) {
+        /* Write Payload marker */
+
+        **dst_packet_data_pptr = 0xff;
+        (*dst_packet_data_pptr)++;
+
+        /* Write Payload */
+        memcpy(*dst_packet_data_pptr, src_coap_msg_ptr->payload_ptr, src_coap_msg_ptr->payload_len);
+
+        /* Increase destination Packet data pointer */
+        (*dst_packet_data_pptr) += src_coap_msg_ptr->payload_len;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/source/sn_coap_header_check.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+ * \file sn_coap_header_check.c
+ *
+ * \brief CoAP Header validity checker
+ *
+ * Functionality: Checks validity of CoAP Header
+ *
+ */
+
+/* * * * INCLUDE FILES * * * */
+#include "ns_types.h"
+#include "mbed-coap/sn_coap_header.h"
+#include "mbed-coap/sn_coap_protocol.h"
+#include "sn_coap_header_internal.h"
+#include "sn_coap_protocol_internal.h"
+#include "mbed-trace/mbed_trace.h"
+
+#define TRACE_GROUP "coap"
+
+/**
+ * \fn int8_t sn_coap_header_validity_check(sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version)
+ *
+ * \brief Checks validity of given Header
+ *
+ * \param *src_coap_msg_ptr is source for building Packet data
+ * \param coap_version is version of used CoAP specification
+ *
+ * \return Return value is status of validity check. In ok cases 0 and in
+ *         failure cases -1
+ */
+int8_t sn_coap_header_validity_check(sn_coap_hdr_s *src_coap_msg_ptr, coap_version_e coap_version)
+{
+    /* * Check validity of CoAP Version * */
+    if (coap_version != COAP_VERSION_1) {
+        return -1;
+    }
+
+    /* * Check validity of Message type * */
+    switch (src_coap_msg_ptr->msg_type) {
+        case COAP_MSG_TYPE_CONFIRMABLE:
+        case COAP_MSG_TYPE_NON_CONFIRMABLE:
+        case COAP_MSG_TYPE_ACKNOWLEDGEMENT:
+        case COAP_MSG_TYPE_RESET:
+            break;      /* Ok cases */
+        default:
+            tr_error("sn_coap_header_validity_check - unknown message type!");
+            return -1;      /* Failed case */
+    }
+
+    /* * Check validity of Message code * */
+    switch (src_coap_msg_ptr->msg_code) {
+        case COAP_MSG_CODE_EMPTY:
+        case COAP_MSG_CODE_REQUEST_GET:
+        case COAP_MSG_CODE_REQUEST_POST:
+        case COAP_MSG_CODE_REQUEST_PUT:
+        case COAP_MSG_CODE_REQUEST_DELETE:
+        case COAP_MSG_CODE_RESPONSE_CREATED:
+        case COAP_MSG_CODE_RESPONSE_DELETED:
+        case COAP_MSG_CODE_RESPONSE_VALID:
+        case COAP_MSG_CODE_RESPONSE_CHANGED:
+        case COAP_MSG_CODE_RESPONSE_CONTENT:
+        case COAP_MSG_CODE_RESPONSE_BAD_REQUEST:
+        case COAP_MSG_CODE_RESPONSE_UNAUTHORIZED:
+        case COAP_MSG_CODE_RESPONSE_BAD_OPTION:
+        case COAP_MSG_CODE_RESPONSE_FORBIDDEN:
+        case COAP_MSG_CODE_RESPONSE_NOT_FOUND:
+        case COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED:
+        case COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE:
+        case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE:
+        case COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED:
+        case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE:
+        case COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT:
+        case COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR:
+        case COAP_MSG_CODE_RESPONSE_NOT_IMPLEMENTED:
+        case COAP_MSG_CODE_RESPONSE_BAD_GATEWAY:
+        case COAP_MSG_CODE_RESPONSE_SERVICE_UNAVAILABLE:
+        case COAP_MSG_CODE_RESPONSE_GATEWAY_TIMEOUT:
+        case COAP_MSG_CODE_RESPONSE_PROXYING_NOT_SUPPORTED:
+        case COAP_MSG_CODE_RESPONSE_CONTINUE:
+            break;      /* Ok cases */
+        default:
+            tr_error("sn_coap_header_validity_check - unknown message code!");
+            return -1;      /* Failed case */
+    }
+
+    /* Success */
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/source/sn_coap_parser.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,794 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+ *\file sn_coap_parser.c
+ *
+ * \brief CoAP Header parser
+ *
+ * Functionality: Parses CoAP Header
+ *
+ */
+
+/* * * * * * * * * * * * * * */
+/* * * * INCLUDE FILES * * * */
+/* * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <string.h> /* For memset() and memcpy() */
+
+#include "ns_types.h"
+#include "mbed-coap/sn_coap_header.h"
+#include "mbed-coap/sn_coap_protocol.h"
+#include "sn_coap_header_internal.h"
+#include "sn_coap_protocol_internal.h"
+#include "mbed-trace/mbed_trace.h"
+
+#define TRACE_GROUP "coap"
+/* * * * * * * * * * * * * * * * * * * * */
+/* * * * LOCAL FUNCTION PROTOTYPES * * * */
+/* * * * * * * * * * * * * * * * * * * * */
+
+static void     sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr);
+static int8_t   sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len);
+static int8_t   sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len,  uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len);
+static int16_t  sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len);
+static int8_t   sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr);
+
+sn_coap_hdr_s *sn_coap_parser_init_message(sn_coap_hdr_s *coap_msg_ptr)
+{
+    /* * * * Check given pointer * * * */
+    if (coap_msg_ptr == NULL) {
+        tr_error("sn_coap_parser_init_message - message null!");
+        return NULL;
+    }
+
+    /* XXX not technically legal to memset pointers to 0 */
+    memset(coap_msg_ptr, 0x00, sizeof(sn_coap_hdr_s));
+
+    coap_msg_ptr->content_format = COAP_CT_NONE;
+
+    return coap_msg_ptr;
+}
+
+sn_coap_hdr_s *sn_coap_parser_alloc_message(struct coap_s *handle)
+{
+    sn_coap_hdr_s *returned_coap_msg_ptr;
+
+    /* * * * Check given pointer * * * */
+    if (handle == NULL) {
+        return NULL;
+    }
+
+    /* * * * Allocate memory for returned CoAP message and initialize allocated memory with with default values  * * * */
+    returned_coap_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_hdr_s));
+
+    return sn_coap_parser_init_message(returned_coap_msg_ptr);
+}
+
+sn_coap_options_list_s *sn_coap_parser_alloc_options(struct coap_s *handle, sn_coap_hdr_s *coap_msg_ptr)
+{
+    /* * * * Check given pointers * * * */
+    if (handle == NULL || coap_msg_ptr == NULL) {
+        return NULL;
+    }
+
+    /* * * * If the message already has options, return them * * * */
+    if (coap_msg_ptr->options_list_ptr) {
+        return coap_msg_ptr->options_list_ptr;
+    }
+
+    /* * * * Allocate memory for options and initialize allocated memory with with default values  * * * */
+    coap_msg_ptr->options_list_ptr = handle->sn_coap_protocol_malloc(sizeof(sn_coap_options_list_s));
+
+    if (coap_msg_ptr->options_list_ptr == NULL) {
+        tr_error("sn_coap_parser_alloc_options - failed to allocate options list!");
+        return NULL;
+    }
+
+    /* XXX not technically legal to memset pointers to 0 */
+    memset(coap_msg_ptr->options_list_ptr, 0x00, sizeof(sn_coap_options_list_s));
+
+    coap_msg_ptr->options_list_ptr->max_age = 0;
+    coap_msg_ptr->options_list_ptr->uri_port = COAP_OPTION_URI_PORT_NONE;
+    coap_msg_ptr->options_list_ptr->observe = COAP_OBSERVE_NONE;
+    coap_msg_ptr->options_list_ptr->accept = COAP_CT_NONE;
+    coap_msg_ptr->options_list_ptr->block2 = COAP_OPTION_BLOCK_NONE;
+    coap_msg_ptr->options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE;
+
+    return coap_msg_ptr->options_list_ptr;
+}
+
+sn_coap_hdr_s *sn_coap_parser(struct coap_s *handle, uint16_t packet_data_len, uint8_t *packet_data_ptr, coap_version_e *coap_version_ptr)
+{
+    uint8_t       *data_temp_ptr                    = packet_data_ptr;
+    sn_coap_hdr_s *parsed_and_returned_coap_msg_ptr = NULL;
+
+    /* * * * Check given pointer * * * */
+    if (packet_data_ptr == NULL || packet_data_len < 4 || handle == NULL) {
+        return NULL;
+    }
+
+    /* * * * Allocate and initialize CoAP message  * * * */
+    parsed_and_returned_coap_msg_ptr = sn_coap_parser_alloc_message(handle);
+
+    if (parsed_and_returned_coap_msg_ptr == NULL) {
+        tr_error("sn_coap_parser - failed to allocate message!");
+        return NULL;
+    }
+
+    /* * * * Header parsing, move pointer over the header...  * * * */
+    sn_coap_parser_header_parse(&data_temp_ptr, parsed_and_returned_coap_msg_ptr, coap_version_ptr);
+
+    /* * * * Options parsing, move pointer over the options... * * * */
+    if (sn_coap_parser_options_parse(handle, &data_temp_ptr, parsed_and_returned_coap_msg_ptr, packet_data_ptr, packet_data_len) != 0) {
+        parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER;
+        return parsed_and_returned_coap_msg_ptr;
+    }
+
+    /* * * * Payload parsing * * * */
+    if (sn_coap_parser_payload_parse(packet_data_len, packet_data_ptr, &data_temp_ptr, parsed_and_returned_coap_msg_ptr) == -1) {
+        parsed_and_returned_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_ERROR_IN_HEADER;
+        return parsed_and_returned_coap_msg_ptr;
+    }
+
+    /* * * * Return parsed CoAP message  * * * * */
+    return parsed_and_returned_coap_msg_ptr;
+}
+
+void sn_coap_parser_release_allocated_coap_msg_mem(struct coap_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr)
+{
+    if (handle == NULL) {
+        return;
+    }
+
+    if (freed_coap_msg_ptr != NULL) {
+        if (freed_coap_msg_ptr->uri_path_ptr != NULL) {
+            handle->sn_coap_protocol_free(freed_coap_msg_ptr->uri_path_ptr);
+        }
+
+        if (freed_coap_msg_ptr->token_ptr != NULL) {
+            handle->sn_coap_protocol_free(freed_coap_msg_ptr->token_ptr);
+        }
+
+        if (freed_coap_msg_ptr->options_list_ptr != NULL) {
+            if (freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr != NULL) {
+                handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->proxy_uri_ptr);
+            }
+
+            if (freed_coap_msg_ptr->options_list_ptr->etag_ptr != NULL) {
+                handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->etag_ptr);
+            }
+
+            if (freed_coap_msg_ptr->options_list_ptr->uri_host_ptr != NULL) {
+                handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_host_ptr);
+            }
+
+            if (freed_coap_msg_ptr->options_list_ptr->location_path_ptr != NULL) {
+                handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->location_path_ptr);
+            }
+
+            if (freed_coap_msg_ptr->options_list_ptr->location_query_ptr != NULL) {
+                handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->location_query_ptr);
+            }
+
+            if (freed_coap_msg_ptr->options_list_ptr->uri_query_ptr != NULL) {
+                handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr->uri_query_ptr);
+            }
+
+            handle->sn_coap_protocol_free(freed_coap_msg_ptr->options_list_ptr);
+        }
+
+        handle->sn_coap_protocol_free(freed_coap_msg_ptr);
+    }
+}
+
+/**
+ * \fn static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr)
+ *
+ * \brief Parses CoAP message's Header part from given Packet data
+ *
+ * \param **packet_data_ptr is source for Packet data to be parsed to CoAP message
+ *
+ * \param *dst_coap_msg_ptr is destination for parsed CoAP message
+ *
+ * \param *coap_version_ptr is destination for parsed CoAP specification version
+ */
+static void sn_coap_parser_header_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, coap_version_e *coap_version_ptr)
+{
+    /* Parse CoAP Version and message type*/
+    *coap_version_ptr = (coap_version_e)(**packet_data_pptr & COAP_HEADER_VERSION_MASK);
+    dst_coap_msg_ptr->msg_type = (sn_coap_msg_type_e)(**packet_data_pptr & COAP_HEADER_MSG_TYPE_MASK);
+    (*packet_data_pptr) += 1;
+
+    /* Parse Message code */
+    dst_coap_msg_ptr->msg_code = (sn_coap_msg_code_e) **packet_data_pptr;
+    (*packet_data_pptr) += 1;
+
+    /* Parse Message ID */
+    dst_coap_msg_ptr->msg_id = *(*packet_data_pptr + 1);
+    dst_coap_msg_ptr->msg_id += **packet_data_pptr << COAP_HEADER_MSG_ID_MSB_SHIFT;
+    (*packet_data_pptr) += 2;
+
+}
+
+/**
+ * \brief Parses a variable-length uint value from an option
+ *
+ * \param **packet_data_pptr is source of option data to be parsed
+ * \param option_len is length of option data (will be 0-4)
+ *
+ * \return Return value is value of uint
+ */
+static uint32_t sn_coap_parser_options_parse_uint(uint8_t **packet_data_pptr, uint8_t option_len)
+{
+    uint32_t value = 0;
+    while (option_len--) {
+        value <<= 8;
+        value |= *(*packet_data_pptr)++;
+    }
+    return value;
+}
+
+/**
+ * \fn static uint8_t sn_coap_parser_options_parse(uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr)
+ *
+ * \brief Parses CoAP message's Options part from given Packet data
+ *
+ * \param **packet_data_pptr is source of Packet data to be parsed to CoAP message
+ * \param *dst_coap_msg_ptr is destination for parsed CoAP message
+ *
+ * \return Return value is 0 in ok case and -1 in failure case
+ */
+static int8_t sn_coap_parser_options_parse(struct coap_s *handle, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr, uint8_t *packet_data_start_ptr, uint16_t packet_len)
+{
+    uint8_t previous_option_number = 0;
+    uint8_t i                      = 0;
+    int8_t  ret_status             = 0;
+    uint16_t message_left          = 0;
+
+    /*  Parse token, if exists  */
+    dst_coap_msg_ptr->token_len = *packet_data_start_ptr & COAP_HEADER_TOKEN_LENGTH_MASK;
+
+    if (dst_coap_msg_ptr->token_len) {
+        if ((dst_coap_msg_ptr->token_len > 8) || dst_coap_msg_ptr->token_ptr) {
+            tr_error("sn_coap_parser_options_parse - token not valid!");
+            return -1;
+        }
+
+        dst_coap_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(dst_coap_msg_ptr->token_len);
+
+        if (dst_coap_msg_ptr->token_ptr == NULL) {
+            tr_error("sn_coap_parser_options_parse - failed to allocate token!");
+            return -1;
+        }
+
+        memcpy(dst_coap_msg_ptr->token_ptr, *packet_data_pptr, dst_coap_msg_ptr->token_len);
+        (*packet_data_pptr) += dst_coap_msg_ptr->token_len;
+    }
+
+    message_left = packet_len - ((*packet_data_pptr) - packet_data_start_ptr);
+
+    /* Loop all Options */
+    while (message_left && (**packet_data_pptr != 0xff)) {
+
+        /* Get option length WITHOUT extensions */
+        uint16_t option_len = (**packet_data_pptr & 0x0F);
+
+        /* Resolve option delta */
+        uint16_t  option_number = (**packet_data_pptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT);
+
+        if (option_number == 13) {
+            option_number = *(*packet_data_pptr + 1) + 13;
+            (*packet_data_pptr)++;
+        } else if (option_number == 14) {
+            option_number = *(*packet_data_pptr + 2);
+            option_number += (*(*packet_data_pptr + 1) << 8) + 269;
+            (*packet_data_pptr) += 2;
+        }
+        /* Option number 15 reserved for payload marker. This is handled as a error! */
+        else if (option_number == 15) {
+            tr_error("sn_coap_parser_options_parse - invalid option number(15)!");
+            return -1;
+        }
+
+        /* Add previous option to option delta and get option number */
+        option_number += previous_option_number;
+
+        /* Add possible option length extension to resolve full length of the option */
+        if (option_len == 13) {
+            option_len = *(*packet_data_pptr + 1) + 13;
+            (*packet_data_pptr)++;
+        } else if (option_len == 14) {
+            option_len = *(*packet_data_pptr + 2);
+            option_len += (*(*packet_data_pptr + 1) << 8) + 269;
+            (*packet_data_pptr) += 2;
+        }
+        /* Option number length 15 is reserved for the future use - ERROR */
+        else if (option_len == 15) {
+            tr_error("sn_coap_parser_options_parse - invalid option len(15)!");
+            return -1;
+        }
+
+        message_left = packet_len - (*packet_data_pptr - packet_data_start_ptr);
+
+        /* * * Parse option itself * * */
+        /* Some options are handled independently in own functions */
+        previous_option_number = option_number;
+        /* Allocate options_list_ptr if needed */
+        switch (option_number) {
+            case COAP_OPTION_MAX_AGE:
+            case COAP_OPTION_PROXY_URI:
+            case COAP_OPTION_ETAG:
+            case COAP_OPTION_URI_HOST:
+            case COAP_OPTION_LOCATION_PATH:
+            case COAP_OPTION_URI_PORT:
+            case COAP_OPTION_LOCATION_QUERY:
+            case COAP_OPTION_OBSERVE:
+            case COAP_OPTION_URI_QUERY:
+            case COAP_OPTION_BLOCK2:
+            case COAP_OPTION_BLOCK1:
+            case COAP_OPTION_ACCEPT:
+            case COAP_OPTION_SIZE1:
+            case COAP_OPTION_SIZE2:
+                if (sn_coap_parser_alloc_options(handle, dst_coap_msg_ptr) == NULL) {
+                    tr_error("sn_coap_parser_options_parse - failed to allocate options!");
+                    return -1;
+                }
+                break;
+        }
+
+        /* Parse option */
+        switch (option_number) {
+            case COAP_OPTION_CONTENT_FORMAT:
+                if ((option_len > 2) || (dst_coap_msg_ptr->content_format != COAP_CT_NONE)) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_CONTENT_FORMAT not valid!");
+                    return -1;
+                }
+                (*packet_data_pptr)++;
+                dst_coap_msg_ptr->content_format = (sn_coap_content_format_e) sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
+                break;
+
+            case COAP_OPTION_MAX_AGE:
+                if (option_len > 4) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_MAX_AGE not valid!");
+                    return -1;
+                }
+                (*packet_data_pptr)++;
+                dst_coap_msg_ptr->options_list_ptr->max_age = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
+                break;
+
+            case COAP_OPTION_PROXY_URI:
+                if ((option_len > 1034) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_PROXY_URI not valid!");
+                    return -1;
+                }
+                dst_coap_msg_ptr->options_list_ptr->proxy_uri_len = option_len;
+                (*packet_data_pptr)++;
+
+                dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr = handle->sn_coap_protocol_malloc(option_len);
+
+                if (dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr == NULL) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_PROXY_URI allocation failed!");
+                    return -1;
+                }
+
+                memcpy(dst_coap_msg_ptr->options_list_ptr->proxy_uri_ptr, *packet_data_pptr, option_len);
+                (*packet_data_pptr) += option_len;
+
+                break;
+
+            case COAP_OPTION_ETAG:
+                /* This is managed independently because User gives this option in one character table */
+
+                ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr,
+                             message_left,
+                             &dst_coap_msg_ptr->options_list_ptr->etag_ptr,
+                             (uint16_t *)&dst_coap_msg_ptr->options_list_ptr->etag_len,
+                             COAP_OPTION_ETAG, option_len);
+                if (ret_status >= 0) {
+                    i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
+                } else {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_ETAG not valid!");
+                    return -1;
+                }
+                break;
+
+            case COAP_OPTION_URI_HOST:
+                if ((option_len > 255) || (option_len < 1) || dst_coap_msg_ptr->options_list_ptr->uri_host_ptr) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_HOST not valid!");
+                    return -1;
+                }
+                dst_coap_msg_ptr->options_list_ptr->uri_host_len = option_len;
+                (*packet_data_pptr)++;
+
+                dst_coap_msg_ptr->options_list_ptr->uri_host_ptr = handle->sn_coap_protocol_malloc(option_len);
+
+                if (dst_coap_msg_ptr->options_list_ptr->uri_host_ptr == NULL) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_HOST allocation failed!");
+                    return -1;
+                }
+                memcpy(dst_coap_msg_ptr->options_list_ptr->uri_host_ptr, *packet_data_pptr, option_len);
+                (*packet_data_pptr) += option_len;
+
+                break;
+
+            case COAP_OPTION_LOCATION_PATH:
+                if (dst_coap_msg_ptr->options_list_ptr->location_path_ptr) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_PATH exists!");
+                    return -1;
+                }
+                /* This is managed independently because User gives this option in one character table */
+                ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
+                             &dst_coap_msg_ptr->options_list_ptr->location_path_ptr, &dst_coap_msg_ptr->options_list_ptr->location_path_len,
+                             COAP_OPTION_LOCATION_PATH, option_len);
+                if (ret_status >= 0) {
+                    i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
+                } else {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_PATH not valid!");
+                    return -1;
+                }
+
+                break;
+
+
+            case COAP_OPTION_URI_PORT:
+                if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->uri_port != COAP_OPTION_URI_PORT_NONE) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_PORT not valid!");
+                    return -1;
+                }
+                (*packet_data_pptr)++;
+
+                dst_coap_msg_ptr->options_list_ptr->uri_port = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
+                break;
+
+            case COAP_OPTION_LOCATION_QUERY:
+                ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
+                             &dst_coap_msg_ptr->options_list_ptr->location_query_ptr, &dst_coap_msg_ptr->options_list_ptr->location_query_len,
+                             COAP_OPTION_LOCATION_QUERY, option_len);
+                if (ret_status >= 0) {
+                    i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
+                } else {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_LOCATION_QUERY not valid!");
+                    return -1;
+                }
+
+                break;
+
+            case COAP_OPTION_URI_PATH:
+                ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
+                             &dst_coap_msg_ptr->uri_path_ptr, &dst_coap_msg_ptr->uri_path_len,
+                             COAP_OPTION_URI_PATH, option_len);
+                if (ret_status >= 0) {
+                    i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
+                } else {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_PATH not valid!");
+                    return -1;
+                }
+
+                break;
+
+            case COAP_OPTION_OBSERVE:
+                if ((option_len > 2) || dst_coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_OBSERVE not valid!");
+                    return -1;
+                }
+
+                (*packet_data_pptr)++;
+
+                dst_coap_msg_ptr->options_list_ptr->observe = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
+
+                break;
+
+            case COAP_OPTION_URI_QUERY:
+                ret_status = sn_coap_parser_options_parse_multiple_options(handle, packet_data_pptr, message_left,
+                             &dst_coap_msg_ptr->options_list_ptr->uri_query_ptr, &dst_coap_msg_ptr->options_list_ptr->uri_query_len,
+                             COAP_OPTION_URI_QUERY, option_len);
+                if (ret_status >= 0) {
+                    i += (ret_status - 1); /* i += is because possible several Options are handled by sn_coap_parser_options_parse_multiple_options() */
+                } else {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_URI_QUERY not valid!");
+                    return -1;
+                }
+
+                break;
+
+            case COAP_OPTION_BLOCK2:
+                if ((option_len > 3) || dst_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_BLOCK2 not valid!");
+                    return -1;
+                }
+                (*packet_data_pptr)++;
+
+                dst_coap_msg_ptr->options_list_ptr->block2 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
+
+                break;
+
+            case COAP_OPTION_BLOCK1:
+                if ((option_len > 3) || dst_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_BLOCK1 not valid!");
+                    return -1;
+                }
+                (*packet_data_pptr)++;
+
+                dst_coap_msg_ptr->options_list_ptr->block1 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
+
+                break;
+
+            case COAP_OPTION_ACCEPT:
+                if ((option_len > 2) || (dst_coap_msg_ptr->options_list_ptr->accept != COAP_CT_NONE)) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_ACCEPT not valid!");
+                    return -1;
+                }
+
+                (*packet_data_pptr)++;
+
+                dst_coap_msg_ptr->options_list_ptr->accept = (sn_coap_content_format_e) sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
+                break;
+
+            case COAP_OPTION_SIZE1:
+                if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->use_size1) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_SIZE1 not valid!");
+                    return -1;
+                }
+                dst_coap_msg_ptr->options_list_ptr->use_size1 = true;
+                (*packet_data_pptr)++;
+                dst_coap_msg_ptr->options_list_ptr->size1 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
+                break;
+
+            case COAP_OPTION_SIZE2:
+                if ((option_len > 4) || dst_coap_msg_ptr->options_list_ptr->use_size2) {
+                    tr_error("sn_coap_parser_options_parse - COAP_OPTION_SIZE2 not valid!");
+                    return -1;
+                }
+                dst_coap_msg_ptr->options_list_ptr->use_size2 = true;
+                (*packet_data_pptr)++;
+                dst_coap_msg_ptr->options_list_ptr->size2 = sn_coap_parser_options_parse_uint(packet_data_pptr, option_len);
+                break;
+
+            default:
+                tr_error("sn_coap_parser_options_parse - unknown option!");
+                return -1;
+        }
+
+        /* Check for overflow */
+        if ((*packet_data_pptr - packet_data_start_ptr) > packet_len) {
+            return -1;
+        }
+
+        message_left = packet_len - (*packet_data_pptr - packet_data_start_ptr);
+
+    }
+
+    return 0;
+}
+
+
+/**
+ * \fn static int8_t sn_coap_parser_options_parse_multiple_options(uint8_t **packet_data_pptr, uint8_t options_count_left, uint8_t *previous_option_number_ptr, uint8_t **dst_pptr,
+ *                                                                  uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len)
+ *
+ * \brief Parses CoAP message's Uri-query options
+ *
+ * \param **packet_data_pptr is source for Packet data to be parsed to CoAP message
+ *
+ * \param *dst_coap_msg_ptr is destination for parsed CoAP message
+ *
+ * \param options_count_left tells how many options are unhandled in Packet data
+ *
+ * \param *previous_option_number_ptr is pointer to used and returned previous Option number
+ *
+ * \return Return value is count of Uri-query optios parsed. In failure case -1 is returned.
+*/
+static int8_t sn_coap_parser_options_parse_multiple_options(struct coap_s *handle, uint8_t **packet_data_pptr, uint16_t packet_left_len,  uint8_t **dst_pptr, uint16_t *dst_len_ptr, sn_coap_option_numbers_e option, uint16_t option_number_len)
+{
+    int16_t     uri_query_needed_heap       = sn_coap_parser_options_count_needed_memory_multiple_option(*packet_data_pptr, packet_left_len, option, option_number_len);
+    uint8_t    *temp_parsed_uri_query_ptr   = NULL;
+    uint8_t     returned_option_counter     = 0;
+
+    if (uri_query_needed_heap == -1) {
+        return -1;
+    }
+
+    if (uri_query_needed_heap) {
+        *dst_pptr = (uint8_t *) handle->sn_coap_protocol_malloc(uri_query_needed_heap);
+
+        if (*dst_pptr == NULL) {
+            tr_error("sn_coap_parser_options_parse_multiple_options - failed to allocate options!");
+            return -1;
+        }
+    }
+
+    *dst_len_ptr = uri_query_needed_heap;
+
+    temp_parsed_uri_query_ptr = *dst_pptr;
+
+    /* Loop all Uri-Query options */
+    while ((temp_parsed_uri_query_ptr - *dst_pptr) < uri_query_needed_heap) {
+        /* Check if this is first Uri-Query option */
+        if (returned_option_counter > 0) {
+            /* Uri-Query is modified to following format: temp1'\0'temp2'\0'temp3 i.e.  */
+            /* Uri-Path is modified to following format: temp1\temp2\temp3 i.e.  */
+            if (option == COAP_OPTION_URI_QUERY || option == COAP_OPTION_LOCATION_QUERY || option == COAP_OPTION_ETAG || option == COAP_OPTION_ACCEPT) {
+                memset(temp_parsed_uri_query_ptr, '&', 1);
+            } else if (option == COAP_OPTION_URI_PATH || option == COAP_OPTION_LOCATION_PATH) {
+                memset(temp_parsed_uri_query_ptr, '/', 1);
+            }
+
+            temp_parsed_uri_query_ptr++;
+        }
+
+        returned_option_counter++;
+
+        (*packet_data_pptr)++;
+
+        if (((temp_parsed_uri_query_ptr - *dst_pptr) + option_number_len) > uri_query_needed_heap) {
+            return -1;
+        }
+
+        memcpy(temp_parsed_uri_query_ptr, *packet_data_pptr, option_number_len);
+
+        (*packet_data_pptr) += option_number_len;
+        temp_parsed_uri_query_ptr += option_number_len;
+
+        if ((temp_parsed_uri_query_ptr - *dst_pptr) >= uri_query_needed_heap || ((**packet_data_pptr >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0)) {
+            return returned_option_counter;
+        }
+
+        option_number_len = (**packet_data_pptr & 0x0F);
+        if (option_number_len == 13) {
+            option_number_len = *(*packet_data_pptr + 1) + 13;
+            (*packet_data_pptr)++;
+        } else if (option_number_len == 14) {
+            option_number_len = *(*packet_data_pptr + 2);
+            option_number_len += (*(*packet_data_pptr + 1) << 8) + 269;
+            (*packet_data_pptr) += 2;
+        }
+    }
+
+    return returned_option_counter;
+}
+
+
+
+
+/**
+ * \fn static uint16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint8_t options_count_left, uint8_t previous_option_number, sn_coap_option_numbers_e option, uint16_t option_number_len)
+ *
+ * \brief Counts needed memory for uri query option
+ *
+ * \param *packet_data_ptr is start of source for Packet data to be parsed to CoAP message
+ *
+ * \param options_count_left tells how many options are unhandled in Packet data
+ *
+ * \param previous_option_number is previous Option number
+ *
+ * \param sn_coap_option_numbers_e option option number to be calculated
+ *
+ * \param uint16_t option_number_len length of the first option part
+ */
+static int16_t sn_coap_parser_options_count_needed_memory_multiple_option(uint8_t *packet_data_ptr, uint16_t packet_left_len, sn_coap_option_numbers_e option, uint16_t option_number_len)
+{
+    uint16_t ret_value              = 0;
+    uint16_t i                      = 1;
+
+    /* Loop all Uri-Query options */
+    while (i <= packet_left_len) {
+        if (option == COAP_OPTION_LOCATION_PATH && option_number_len > 255) {
+            return -1;
+        }
+        if (option == COAP_OPTION_URI_PATH && option_number_len > 255) {
+            return -1;
+        }
+        if (option == COAP_OPTION_URI_QUERY && option_number_len > 255) {
+            return -1;
+        }
+        if (option == COAP_OPTION_LOCATION_QUERY && option_number_len > 255) {
+            return -1;
+        }
+        if (option == COAP_OPTION_ACCEPT && option_number_len > 2) {
+            return -1;
+        }
+        if (option == COAP_OPTION_ETAG && option_number_len > 8) {
+            return -1;
+        }
+
+        i += option_number_len;
+        ret_value += option_number_len + 1; /* + 1 is for separator */
+
+        if( i == packet_left_len ) {
+            break;
+        }
+        else if( i > packet_left_len ) {
+            return -1;
+        }
+
+        if ((*(packet_data_ptr + i) >> COAP_OPTIONS_OPTION_NUMBER_SHIFT) != 0) {
+            return (ret_value - 1);    /* -1 because last Part path does not include separator */
+        }
+
+        option_number_len = (*(packet_data_ptr + i) & 0x0F);
+
+        if (option_number_len == 13) {
+
+            if(i + 1 >= packet_left_len) {
+                return -1;
+            }
+
+            i++;
+            option_number_len = *(packet_data_ptr + i) + 13;
+        } else if (option_number_len == 14) {
+
+            if(i + 2 >= packet_left_len) {
+                return -1;
+            }
+
+            option_number_len = *(packet_data_ptr + i + 2);
+            option_number_len += (*(packet_data_ptr + i + 1) << 8) + 269;
+            i += 2;
+        } else if (option_number_len == 15) {
+            return -1;
+        }
+        i++;
+
+    }
+
+    if (ret_value != 0) {
+        return (ret_value - 1);    /* -1 because last Part path does not include separator */
+    } else {
+        return 0;
+    }
+}
+
+/**
+ * \fn static void sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr)
+ *
+ * \brief Parses CoAP message's Payload part from given Packet data
+ *
+ * \param packet_data_len is length of given Packet data to be parsed to CoAP message
+ *
+ * \param *packet_data_ptr is start of source for Packet data to be parsed to CoAP message
+ *
+ * \param **packet_data_pptr is source for Packet data to be parsed to CoAP message
+ *
+ * \param *dst_coap_msg_ptr is destination for parsed CoAP message
+ *****************************************************************************/
+static int8_t sn_coap_parser_payload_parse(uint16_t packet_data_len, uint8_t *packet_data_start_ptr, uint8_t **packet_data_pptr, sn_coap_hdr_s *dst_coap_msg_ptr)
+{
+    /* If there is payload */
+    if ((*packet_data_pptr - packet_data_start_ptr) < packet_data_len) {
+        if (**packet_data_pptr == 0xff) {
+            (*packet_data_pptr)++;
+            /* Parse Payload length */
+            dst_coap_msg_ptr->payload_len = packet_data_len - (*packet_data_pptr - packet_data_start_ptr);
+
+            /* The presence of a marker followed by a zero-length payload MUST be processed as a message format error */
+            if (dst_coap_msg_ptr->payload_len == 0) {
+                return -1;
+            }
+
+            /* Parse Payload by setting CoAP message's payload_ptr to point Payload in Packet data */
+            dst_coap_msg_ptr->payload_ptr = *packet_data_pptr;
+        }
+        /* No payload marker.. */
+        else {
+            tr_error("sn_coap_parser_payload_parse - payload marker not found!");
+            return -1;
+        }
+    }
+    return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-coap/source/sn_coap_protocol.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2463 @@
+/*
+ * Copyright (c) 2011-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+ * \file sn_coap_protocol.c
+ *
+ * \brief CoAP Protocol implementation
+ *
+ * Functionality: CoAP Protocol
+ *
+ */
+
+
+/* * * * * * * * * * * * * * */
+/* * * * INCLUDE FILES * * * */
+/* * * * * * * * * * * * * * */
+
+#include <stdio.h>
+#include <stdlib.h> /* For libary malloc() */
+#include <string.h> /* For memset() and memcpy() */
+#if defined __linux__ || defined TARGET_LIKE_MBED
+#include <time.h>
+#endif
+
+#include "ns_types.h"
+#include "mbed-coap/sn_coap_protocol.h"
+#include "sn_coap_header_internal.h"
+#include "sn_coap_protocol_internal.h"
+#include "randLIB.h"
+#include "mbed-trace/mbed_trace.h"
+
+#define TRACE_GROUP "coap"
+/* * * * * * * * * * * * * * * * * * * * */
+/* * * * LOCAL FUNCTION PROTOTYPES * * * */
+/* * * * * * * * * * * * * * * * * * * * */
+
+#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT/* If Message duplication detection is not used at all, this part of code will not be compiled */
+static void                  sn_coap_protocol_linked_list_duplication_info_store(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id, void *param);
+static coap_duplication_info_s *sn_coap_protocol_linked_list_duplication_info_search(struct coap_s *handle, sn_nsdl_addr_s *scr_addr_ptr, uint16_t msg_id);
+static void                  sn_coap_protocol_linked_list_duplication_info_remove(struct coap_s *handle, uint8_t *scr_addr_ptr, uint16_t port, uint16_t msg_id);
+static void                  sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle);
+#endif
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */
+static void                  sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr);
+static void                  sn_coap_protocol_linked_list_blockwise_payload_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr, uint16_t stored_payload_len, uint8_t *stored_payload_ptr, uint8_t *token_ptr, uint8_t token_len, uint32_t block_number);
+static uint8_t              *sn_coap_protocol_linked_list_blockwise_payload_search(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length, uint8_t *token_ptr, uint8_t token_len);
+static bool                  sn_coap_protocol_linked_list_blockwise_payload_compare_block_number(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint8_t *token_ptr, uint8_t token_len, uint32_t block_number);
+static void                  sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle, coap_blockwise_payload_s *removed_payload_ptr);
+static void                  sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(struct coap_s *handle, uint8_t *token_ptr, uint8_t token_len);
+static uint32_t              sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint8_t *token_ptr, uint8_t token_len);
+static void                  sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle);
+static sn_coap_hdr_s        *sn_coap_handle_blockwise_message(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr, void *param);
+static sn_coap_hdr_s        *sn_coap_protocol_copy_header(struct coap_s *handle, sn_coap_hdr_s *source_header_ptr);
+#endif
+#if ENABLE_RESENDINGS
+static uint8_t               sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param);
+static sn_nsdl_transmit_s   *sn_coap_protocol_linked_list_send_msg_search(struct coap_s *handle,sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id);
+static void                  sn_coap_protocol_linked_list_send_msg_remove(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id);
+static coap_send_msg_s      *sn_coap_protocol_allocate_mem_for_msg(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t packet_data_len);
+static void                  sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr);
+static uint16_t              sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr);
+static uint32_t              sn_coap_calculate_new_resend_time(const uint32_t current_time, const uint8_t interval, const uint8_t counter);
+#endif
+
+/* * * * * * * * * * * * * * * * * */
+/* * * * GLOBAL DECLARATIONS * * * */
+/* * * * * * * * * * * * * * * * * */
+static uint16_t message_id;
+
+int8_t sn_coap_protocol_destroy(struct coap_s *handle)
+{
+    if (handle == NULL) {
+        return -1;
+    }
+#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */
+
+    sn_coap_protocol_clear_retransmission_buffer(handle);
+
+#endif
+
+#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */
+    ns_list_foreach_safe(coap_duplication_info_s, tmp, &handle->linked_list_duplication_msgs) {
+        if (tmp->coap == handle) {
+            if (tmp->address) {
+                if (tmp->address->addr_ptr) {
+                    handle->sn_coap_protocol_free(tmp->address->addr_ptr);
+                    tmp->address->addr_ptr = 0;
+                }
+                handle->sn_coap_protocol_free(tmp->address);
+                tmp->address = 0;
+            }
+            if (tmp->packet_ptr) {
+                handle->sn_coap_protocol_free(tmp->packet_ptr);
+                tmp->packet_ptr = 0;
+            }
+            ns_list_remove(&handle->linked_list_duplication_msgs, tmp);
+            handle->count_duplication_msgs--;
+            handle->sn_coap_protocol_free(tmp);
+            tmp = 0;
+        }
+    }
+
+#endif
+
+
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwise is not enabled, this part of code will not be compiled */
+    ns_list_foreach_safe(coap_blockwise_msg_s, tmp, &handle->linked_list_blockwise_sent_msgs) {
+        if (tmp->coap == handle) {
+            if (tmp->coap_msg_ptr) {
+                if (tmp->coap_msg_ptr->payload_ptr) {
+                    handle->sn_coap_protocol_free(tmp->coap_msg_ptr->payload_ptr);
+                    tmp->coap_msg_ptr->payload_ptr = 0;
+                }
+                sn_coap_parser_release_allocated_coap_msg_mem(tmp->coap, tmp->coap_msg_ptr);
+            }
+            ns_list_remove(&handle->linked_list_blockwise_sent_msgs, tmp);
+            handle->sn_coap_protocol_free(tmp);
+            tmp = 0;
+        }
+    }
+    ns_list_foreach_safe(coap_blockwise_payload_s, tmp, &handle->linked_list_blockwise_received_payloads) {
+        if (tmp->coap == handle) {
+            if (tmp->addr_ptr) {
+                handle->sn_coap_protocol_free(tmp->addr_ptr);
+                tmp->addr_ptr = 0;
+            }
+            if (tmp->payload_ptr) {
+                handle->sn_coap_protocol_free(tmp->payload_ptr);
+                tmp->payload_ptr = 0;
+            }
+            ns_list_remove(&handle->linked_list_blockwise_received_payloads, tmp);
+            handle->sn_coap_protocol_free(tmp);
+            tmp = 0;
+        }
+    }
+#endif
+
+    handle->sn_coap_protocol_free(handle);
+    handle = 0;
+    return 0;
+}
+
+struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), void (*used_free_func_ptr)(void *),
+                                     uint8_t (*used_tx_callback_ptr)(uint8_t *, uint16_t, sn_nsdl_addr_s *, void *),
+                                     int8_t (*used_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *, void *param))
+{
+    /* Check paramters */
+    if ((used_malloc_func_ptr == NULL) || (used_free_func_ptr == NULL) || (used_tx_callback_ptr == NULL)) {
+        return NULL;
+    }
+
+    struct coap_s *handle;
+    handle = used_malloc_func_ptr(sizeof(struct coap_s));
+    if (handle == NULL) {
+        return NULL;
+    }
+
+    memset(handle, 0, sizeof(struct coap_s));
+
+    /* * * Handle tx callback * * */
+    handle->sn_coap_tx_callback = used_tx_callback_ptr;
+
+    handle->sn_coap_protocol_free = used_free_func_ptr;
+    handle->sn_coap_protocol_malloc = used_malloc_func_ptr;
+
+    /* * * Handle rx callback * * */
+    /* If pointer = 0, then re-sending does not return error when failed */
+    handle->sn_coap_rx_callback = used_rx_callback_ptr;
+
+    // Handles internally all GET req responses
+    handle->sn_coap_internal_block2_resp_handling = true;
+
+#if ENABLE_RESENDINGS  /* If Message resending is not used at all, this part of code will not be compiled */
+    /* * * * Create Linked list for storing active resending messages  * * * */
+    ns_list_init(&handle->linked_list_resent_msgs);
+    handle->sn_coap_resending_queue_msgs = SN_COAP_RESENDING_QUEUE_SIZE_MSGS;
+    handle->sn_coap_resending_queue_bytes = SN_COAP_RESENDING_QUEUE_SIZE_BYTES;
+    handle->sn_coap_resending_intervall = DEFAULT_RESPONSE_TIMEOUT;
+    handle->sn_coap_resending_count = SN_COAP_RESENDING_MAX_COUNT;
+
+
+#endif /* ENABLE_RESENDINGS */
+
+#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */
+    /* * * * Create Linked list for storing Duplication info * * * */
+    ns_list_init(&handle->linked_list_duplication_msgs);
+    handle->sn_coap_duplication_buffer_size = SN_COAP_DUPLICATION_MAX_MSGS_COUNT;
+#endif
+
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */
+
+    ns_list_init(&handle->linked_list_blockwise_sent_msgs);
+    ns_list_init(&handle->linked_list_blockwise_received_payloads);
+    handle->sn_coap_block_data_size = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE;
+
+#endif /* ENABLE_RESENDINGS */
+
+    /* Randomize global message ID */
+    randLIB_seed_random();
+    message_id = randLIB_get_16bit();
+    if (message_id == 0) {
+        message_id = 1;
+    }
+
+    return handle;
+}
+
+int8_t sn_coap_protocol_handle_block2_response_internally(struct coap_s *handle, uint8_t build_response)
+{
+    if (handle == NULL) {
+        return -1;
+    }
+
+    handle->sn_coap_internal_block2_resp_handling = build_response;
+    return 0;
+}
+
+int8_t sn_coap_protocol_set_block_size(struct coap_s *handle, uint16_t block_size)
+{
+    (void) handle;
+    (void) block_size;
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+    if (handle == NULL) {
+        return -1;
+    }
+    switch (block_size) {
+        case 0:
+        case 16:
+        case 32:
+        case 64:
+        case 128:
+        case 256:
+        case 512:
+        case 1024:
+            handle->sn_coap_block_data_size = block_size;
+            return 0;
+        default:
+            break;
+    }
+#endif
+    return -1;
+
+}
+
+void sn_coap_protocol_clear_sent_blockwise_messages(struct coap_s *handle)
+{
+    (void) handle;
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+    if (handle == NULL) {
+        return;
+    }
+
+    /* Loop all stored Blockwise messages in Linked list */
+    ns_list_foreach_safe(coap_blockwise_msg_s, removed_blocwise_msg_ptr, &handle->linked_list_blockwise_sent_msgs) {
+        sn_coap_protocol_linked_list_blockwise_msg_remove(handle, removed_blocwise_msg_ptr);
+    }
+#endif
+}
+
+int8_t sn_coap_protocol_set_duplicate_buffer_size(struct coap_s *handle, uint8_t message_count)
+{
+    (void) handle;
+    (void) message_count;
+#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT
+    if (handle == NULL) {
+        return -1;
+    }
+    if (message_count <= SN_COAP_MAX_ALLOWED_DUPLICATION_MESSAGE_COUNT) {
+        handle->sn_coap_duplication_buffer_size = message_count;
+        return 0;
+    }
+#endif
+    return -1;
+}
+
+int8_t sn_coap_protocol_set_retransmission_parameters(struct coap_s *handle,
+        uint8_t resending_count, uint8_t resending_intervall)
+{
+#if ENABLE_RESENDINGS
+    if (handle == NULL) {
+        return -1;
+    }
+    if (resending_count <= SN_COAP_MAX_ALLOWED_RESENDING_COUNT &&
+            resending_intervall <= SN_COAP_MAX_ALLOWED_RESPONSE_TIMEOUT) {
+        handle->sn_coap_resending_count = resending_count;
+
+        if (resending_intervall == 0) {
+            handle->sn_coap_resending_intervall = 1;
+        } else {
+            handle->sn_coap_resending_intervall = resending_intervall;
+        }
+        return 0;
+    }
+#endif
+    return -1;
+}
+
+int8_t sn_coap_protocol_set_retransmission_buffer(struct coap_s *handle,
+        uint8_t buffer_size_messages, uint16_t buffer_size_bytes)
+{
+#if ENABLE_RESENDINGS
+    if (handle == NULL) {
+        return -1;
+    }
+    if (buffer_size_bytes <= SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_BYTES &&
+        buffer_size_messages <= SN_COAP_MAX_ALLOWED_RESENDING_BUFF_SIZE_MSGS ) {
+        handle->sn_coap_resending_queue_bytes = buffer_size_bytes;
+        handle->sn_coap_resending_queue_msgs = buffer_size_messages;
+        return 0;
+    }
+
+#endif
+    return -1;
+
+}
+
+void sn_coap_protocol_clear_retransmission_buffer(struct coap_s *handle)
+{
+#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */
+    if (handle == NULL) {
+        return;
+    }
+    ns_list_foreach_safe(coap_send_msg_s, tmp, &handle->linked_list_resent_msgs) {
+        ns_list_remove(&handle->linked_list_resent_msgs, tmp);
+        sn_coap_protocol_release_allocated_send_msg_mem(handle, tmp);
+        --handle->count_resent_msgs;
+    }
+#endif
+}
+
+int8_t sn_coap_protocol_delete_retransmission(struct coap_s *handle, uint16_t msg_id)
+{
+#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */
+    if (handle == NULL) {
+        return -1;
+    }
+    ns_list_foreach_safe(coap_send_msg_s, tmp, &handle->linked_list_resent_msgs) {
+        if (tmp->send_msg_ptr && tmp->send_msg_ptr->packet_ptr ) {
+            uint16_t temp_msg_id = (tmp->send_msg_ptr->packet_ptr[2] << 8);
+            temp_msg_id += (uint16_t)tmp->send_msg_ptr->packet_ptr[3];
+            if(temp_msg_id == msg_id){
+                ns_list_remove(&handle->linked_list_resent_msgs, tmp);
+                --handle->count_resent_msgs;
+                sn_coap_protocol_release_allocated_send_msg_mem(handle, tmp);
+                return 0;
+            }
+        }
+    }
+#endif
+    return -2;
+}
+
+
+int8_t prepare_blockwise_message(struct coap_s *handle, sn_coap_hdr_s *src_coap_msg_ptr)
+{
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */
+    if ((src_coap_msg_ptr->payload_len > SN_COAP_MAX_NONBLOCKWISE_PAYLOAD_SIZE) &&
+        (src_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) &&
+        (handle->sn_coap_block_data_size > 0)) {
+        /* * * * Add Blockwise option to send CoAP message * * */
+
+        /* Allocate memory for less used options */
+        if (sn_coap_parser_alloc_options(handle, src_coap_msg_ptr) == NULL) {
+            tr_error("prepare_blockwise_message - failed to allocate options!");
+            return -2;
+        }
+
+        /* Check if Request message */
+        if (src_coap_msg_ptr->msg_code < COAP_MSG_CODE_RESPONSE_CREATED) {
+            /* Add Blockwise option, use Block1 because Request payload */
+            src_coap_msg_ptr->options_list_ptr->block1 = 0x08;      /* First block  (BLOCK NUMBER, 4 MSB bits) + More to come (MORE, 1 bit) */
+            src_coap_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size);
+
+            /* Add size1 parameter */
+
+            src_coap_msg_ptr->options_list_ptr->use_size1 = true;
+            src_coap_msg_ptr->options_list_ptr->use_size2 = false;
+            src_coap_msg_ptr->options_list_ptr->size1 = src_coap_msg_ptr->payload_len;
+        } else { /* Response message */
+            /* Add Blockwise option, use Block2 because Response payload */
+            src_coap_msg_ptr->options_list_ptr->block2 = 0x08;      /* First block  (BLOCK NUMBER, 4 MSB bits) + More to come (MORE, 1 bit) */
+            src_coap_msg_ptr->options_list_ptr->block2 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size);
+
+            src_coap_msg_ptr->options_list_ptr->use_size1 = false;
+            src_coap_msg_ptr->options_list_ptr->use_size2 = true;
+            src_coap_msg_ptr->options_list_ptr->size2 = src_coap_msg_ptr->payload_len;
+        }
+    }
+#endif
+    return 0;
+}
+
+
+int16_t sn_coap_protocol_build(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr,
+                               uint8_t *dst_packet_data_ptr, sn_coap_hdr_s *src_coap_msg_ptr, void *param)
+{
+    int16_t  byte_count_built     = 0;
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */
+    uint16_t original_payload_len = 0;
+#endif
+    /* * * * Check given pointers  * * * */
+    if ((dst_addr_ptr == NULL) || (dst_packet_data_ptr == NULL) || (src_coap_msg_ptr == NULL) || handle == NULL) {
+        return -2;
+    }
+
+    if (dst_addr_ptr->addr_ptr == NULL) {
+        return -2;
+    }
+
+    /* Check if built Message type is else than Acknowledgement or Reset i.e. message type is Confirmable or Non-confirmable */
+    /* (for Acknowledgement and  Reset messages is written same Message ID than was in the Request message) */
+    if (src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_ACKNOWLEDGEMENT &&
+            src_coap_msg_ptr->msg_type != COAP_MSG_TYPE_RESET &&
+            src_coap_msg_ptr->msg_id == 0) {
+        /* * * * Generate new Message ID and increase it by one  * * * */
+        src_coap_msg_ptr->msg_id = message_id;
+        message_id++;
+        if (message_id == 0) {
+            message_id = 1;
+        }
+    }
+
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */
+    /* If blockwising needed */
+    if ((src_coap_msg_ptr->payload_len > SN_COAP_MAX_NONBLOCKWISE_PAYLOAD_SIZE) &&
+        (src_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) &&
+        (handle->sn_coap_block_data_size > 0)) {
+        /* Store original Payload length */
+        original_payload_len = src_coap_msg_ptr->payload_len;
+        /* Change Payload length of send message because Payload is blockwised */
+        src_coap_msg_ptr->payload_len = handle->sn_coap_block_data_size;
+    }
+#endif
+    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+    /* * * * Build Packet data from CoAP message by using CoAP Header builder  * * * */
+    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+    byte_count_built = sn_coap_builder_2(dst_packet_data_ptr, src_coap_msg_ptr, handle->sn_coap_block_data_size);
+
+    if (byte_count_built < 0) {
+        tr_error("sn_coap_protocol_build - failed to build message!");
+        return byte_count_built;
+    }
+
+#if ENABLE_RESENDINGS /* If Message resending is not used at all, this part of code will not be compiled */
+
+    /* Check if built Message type was confirmable, only these messages are resent */
+    if (src_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
+        /* Store message to Linked list for resending purposes */
+        uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0);
+        if (sn_coap_protocol_linked_list_send_msg_store(handle, dst_addr_ptr, byte_count_built, dst_packet_data_ptr,
+                resend_time,
+                param) == 0) {
+            return -4;
+        }
+    }
+
+#endif /* ENABLE_RESENDINGS */
+
+#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT
+    if (src_coap_msg_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT &&
+            handle->sn_coap_duplication_buffer_size != 0) {
+        coap_duplication_info_s* info = sn_coap_protocol_linked_list_duplication_info_search(handle,
+                                                                                             dst_addr_ptr,
+                                                                                             src_coap_msg_ptr->msg_id);
+        /* Update package data to duplication info struct if it's not there yet */
+        if (info && info->packet_ptr == NULL) {
+            info->packet_ptr = handle->sn_coap_protocol_malloc(byte_count_built);
+            if (info->packet_ptr) {
+                memcpy(info->packet_ptr, dst_packet_data_ptr, byte_count_built);
+                info->packet_len = byte_count_built;
+            } else {
+                tr_error("sn_coap_protocol_build - failed to allocate duplication info!");
+                return -4;
+            }
+        }
+    }
+#endif
+
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is not enabled, this part of code will not be compiled */
+
+    /* If blockwising needed */
+    if ((original_payload_len > handle->sn_coap_block_data_size) && (handle->sn_coap_block_data_size > 0)) {
+
+        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+        /* * * * Manage rest blockwise messages sending by storing them to Linked list * * * */
+        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+        coap_blockwise_msg_s *stored_blockwise_msg_ptr;
+
+        stored_blockwise_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_msg_s));
+        if (!stored_blockwise_msg_ptr) {
+            //block paylaod save failed, only first block can be build. Perhaps we should return error.
+            tr_error("sn_coap_protocol_build - blockwise message allocation failed!");
+            return byte_count_built;
+        }
+        memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s));
+
+        /* Fill struct */
+        stored_blockwise_msg_ptr->timestamp = handle->system_time;
+
+        stored_blockwise_msg_ptr->coap_msg_ptr = sn_coap_protocol_copy_header(handle, src_coap_msg_ptr);
+        if( stored_blockwise_msg_ptr->coap_msg_ptr == NULL ){
+            handle->sn_coap_protocol_free(stored_blockwise_msg_ptr);
+            stored_blockwise_msg_ptr = 0;
+            tr_error("sn_coap_protocol_build - block header copy failed!");
+            return -2;
+        }
+
+        stored_blockwise_msg_ptr->coap_msg_ptr->payload_len = original_payload_len;
+        stored_blockwise_msg_ptr->coap_msg_ptr->payload_ptr = handle->sn_coap_protocol_malloc(stored_blockwise_msg_ptr->coap_msg_ptr->payload_len);
+
+        if (!stored_blockwise_msg_ptr->coap_msg_ptr->payload_ptr) {
+            //block payload save failed, only first block can be build. Perhaps we should return error.
+            sn_coap_parser_release_allocated_coap_msg_mem(handle, stored_blockwise_msg_ptr->coap_msg_ptr);
+            handle->sn_coap_protocol_free(stored_blockwise_msg_ptr);
+            stored_blockwise_msg_ptr = 0;
+            tr_error("sn_coap_protocol_build - block payload allocation failed!");
+            return byte_count_built;
+        }
+        memcpy(stored_blockwise_msg_ptr->coap_msg_ptr->payload_ptr, src_coap_msg_ptr->payload_ptr, stored_blockwise_msg_ptr->coap_msg_ptr->payload_len);
+
+        stored_blockwise_msg_ptr->coap = handle;
+        stored_blockwise_msg_ptr->param = param;
+        stored_blockwise_msg_ptr->msg_id = stored_blockwise_msg_ptr->coap_msg_ptr->msg_id;
+        ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr);
+    } else if (src_coap_msg_ptr->msg_code <= COAP_MSG_CODE_REQUEST_DELETE) {
+        /* Add message to linked list - response can be in blocks and we need header to build response.. */
+        coap_blockwise_msg_s *stored_blockwise_msg_ptr;
+
+        stored_blockwise_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_msg_s));
+        if (!stored_blockwise_msg_ptr) {
+            tr_error("sn_coap_protocol_build - blockwise (GET) allocation failed!");
+            return byte_count_built;
+        }
+        memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s));
+
+        /* Fill struct */
+        stored_blockwise_msg_ptr->timestamp = handle->system_time;
+
+        stored_blockwise_msg_ptr->coap_msg_ptr = sn_coap_protocol_copy_header(handle, src_coap_msg_ptr);
+        if( stored_blockwise_msg_ptr->coap_msg_ptr == NULL ){
+            handle->sn_coap_protocol_free(stored_blockwise_msg_ptr);
+            stored_blockwise_msg_ptr = 0;
+            tr_error("sn_coap_protocol_build - blockwise (GET) copy header failed!");
+            return -2;
+        }
+
+        stored_blockwise_msg_ptr->coap = handle;
+        stored_blockwise_msg_ptr->param = param;
+        stored_blockwise_msg_ptr->msg_id = stored_blockwise_msg_ptr->coap_msg_ptr->msg_id;
+        ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr);
+    }
+
+#endif /* SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */
+
+    /* * * * Return built CoAP message Packet data length  * * * */
+    return byte_count_built;
+}
+
+sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t packet_data_len, uint8_t *packet_data_ptr, void *param)
+{
+    sn_coap_hdr_s   *returned_dst_coap_msg_ptr = NULL;
+    coap_version_e   coap_version              = COAP_VERSION_UNKNOWN;
+
+    /* * * * Check given pointer * * * */
+    if (src_addr_ptr == NULL || src_addr_ptr->addr_ptr == NULL ||
+        packet_data_ptr == NULL || handle == NULL) {
+        return NULL;
+    }
+
+    /* * * * Parse Packet data to CoAP message by using CoAP Header parser * * * */
+    returned_dst_coap_msg_ptr = sn_coap_parser(handle, packet_data_len, packet_data_ptr, &coap_version);
+
+    /* Check status of returned pointer */
+    if (returned_dst_coap_msg_ptr == NULL) {
+        /* Memory allocation error in parser */
+        tr_error("sn_coap_protocol_parse - allocation fail in parser!");
+        return NULL;
+    }
+    /* * * * Send bad request response if parsing fails * * * */
+    if (returned_dst_coap_msg_ptr->coap_status == COAP_STATUS_PARSER_ERROR_IN_HEADER) {
+        sn_coap_protocol_send_rst(handle, returned_dst_coap_msg_ptr->msg_id, src_addr_ptr, param);
+        sn_coap_parser_release_allocated_coap_msg_mem(handle, returned_dst_coap_msg_ptr);
+        tr_error("sn_coap_protocol_parse - COAP_STATUS_PARSER_ERROR_IN_HEADER");
+        return NULL;
+    }
+
+    /* * * * Check validity of parsed Header values  * * * */
+    if (sn_coap_header_validity_check(returned_dst_coap_msg_ptr, coap_version) != 0) {
+        /* If message code is in a reserved class (1, 6 or 7), send reset. Message code class is 3 MSB of the message code byte     */
+        if (((returned_dst_coap_msg_ptr->msg_code >> 5) == 1) ||        // if class == 1
+                ((returned_dst_coap_msg_ptr->msg_code >> 5) == 6) ||    // if class == 6
+                ((returned_dst_coap_msg_ptr->msg_code >> 5) == 7)) {    // if class == 7
+            tr_error("sn_coap_protocol_parse - message code not valid!");
+            sn_coap_protocol_send_rst(handle, returned_dst_coap_msg_ptr->msg_id, src_addr_ptr, param);
+        }
+
+        /* Release memory of CoAP message */
+        sn_coap_parser_release_allocated_coap_msg_mem(handle, returned_dst_coap_msg_ptr);
+
+        /* Return NULL because Header validity check failed */
+        return NULL;
+    }
+
+    /* Check if we need to send reset message */
+    /*  A recipient MUST acknowledge a Confirmable message with an Acknowledgement
+        message or, if it lacks context to process the message properly
+        (including the case where the message is Empty, uses a code with a
+        reserved class (1, 6 or 7), or has a message format error), MUST
+        reject it; rejecting a Confirmable message is effected by sending a
+        matching Reset message and otherwise ignoring it. */
+    if (returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
+        /* CoAP ping */
+        if (returned_dst_coap_msg_ptr->msg_code == COAP_MSG_CODE_EMPTY) {
+            sn_coap_protocol_send_rst(handle, returned_dst_coap_msg_ptr->msg_id, src_addr_ptr, param);
+
+            /* Release memory of CoAP message */
+            sn_coap_parser_release_allocated_coap_msg_mem(handle, returned_dst_coap_msg_ptr);
+
+            /* Return NULL because Header validity check failed */
+            return NULL;
+        }
+    }
+
+
+#if !SN_COAP_BLOCKWISE_ENABLED && !SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE /* If Message blockwising is enabled, this part of code will not be compiled */
+    /* If blockwising used in received message */
+    if (returned_dst_coap_msg_ptr->options_list_ptr != NULL &&
+            (returned_dst_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE ||
+             returned_dst_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE)) {
+        /* Set returned status to User */
+        returned_dst_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED;
+        tr_error("sn_coap_protocol_parse - COAP_STATUS_PARSER_BLOCKWISE_MSG_REJECTED!");
+        //todo: send response -> not implemented
+        return returned_dst_coap_msg_ptr;
+    }
+#endif /* !SN_COAP_BLOCKWISE_ENABLED && !SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */
+
+#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT/* If Message duplication is used, this part of code will not be compiled */
+
+    /* * * * Manage received CoAP message duplicate detection  * * * */
+
+    /* If no message duplication detected */
+    if ((returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE ||
+            returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE) &&
+            handle->sn_coap_duplication_buffer_size != 0) {
+        if (sn_coap_protocol_linked_list_duplication_info_search(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id) == NULL) {
+            /* * * No Message duplication: Store received message for detecting later duplication * * */
+
+            /* Get count of stored duplication messages */
+            uint16_t stored_duplication_msgs_count = handle->count_duplication_msgs;
+
+            /* Check if there is no room to store message for duplication detection purposes */
+            if (stored_duplication_msgs_count >= handle->sn_coap_duplication_buffer_size) {
+                tr_debug("sn_coap_protocol_parse - duplicate list full, dropping oldest");
+
+                /* Get oldest stored duplication message */
+                coap_duplication_info_s *stored_duplication_info_ptr = ns_list_get_first(&handle->linked_list_duplication_msgs);
+
+                /* Remove oldest stored duplication message for getting room for new duplication message */
+                sn_coap_protocol_linked_list_duplication_info_remove(handle,
+                                                                     stored_duplication_info_ptr->address->addr_ptr,
+                                                                     stored_duplication_info_ptr->address->port,
+                                                                     stored_duplication_info_ptr->msg_id);
+            }
+
+            /* Store Duplication info to Linked list */
+            sn_coap_protocol_linked_list_duplication_info_store(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id, param);
+        } else { /* * * Message duplication detected * * */
+            /* Set returned status to User */
+            returned_dst_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_DUPLICATED_MSG;
+            coap_duplication_info_s* response = sn_coap_protocol_linked_list_duplication_info_search(handle,
+                                                                                                     src_addr_ptr,
+                                                                                                     returned_dst_coap_msg_ptr->msg_id);
+            /* Send ACK response */
+            if (response) {
+                /* Check that response has been created */
+                if (response->packet_ptr) {
+                    response->coap->sn_coap_tx_callback(response->packet_ptr,
+                            response->packet_len, response->address, response->param);
+                }
+            }
+
+            return returned_dst_coap_msg_ptr;
+        }
+    }
+#endif
+
+    /*** And here we check if message was block message ***/
+    /*** If so, we call own block handling function and ***/
+    /*** return to caller.                              ***/
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+
+    if (returned_dst_coap_msg_ptr->options_list_ptr != NULL &&
+            (returned_dst_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE ||
+             returned_dst_coap_msg_ptr->options_list_ptr->block2 != COAP_OPTION_BLOCK_NONE)) {
+        returned_dst_coap_msg_ptr = sn_coap_handle_blockwise_message(handle, src_addr_ptr, returned_dst_coap_msg_ptr, param);
+    } else {
+        /* Get ... */
+        coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = NULL;
+
+        ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) {
+            if (returned_dst_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) {
+                stored_blockwise_msg_temp_ptr = msg;
+                break;
+            }
+        }
+        /* Remove from the list if not an notification message.
+         * Initial notification message is needed for sending rest of the blocks (GET request).
+        */
+        bool remove_from_the_list = false;
+        if (stored_blockwise_msg_temp_ptr) {
+            if (stored_blockwise_msg_temp_ptr->coap_msg_ptr &&
+                stored_blockwise_msg_temp_ptr->coap_msg_ptr->options_list_ptr &&
+                stored_blockwise_msg_temp_ptr->coap_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
+                remove_from_the_list = false;
+            } else {
+                remove_from_the_list = true;
+            }
+        }
+        if (remove_from_the_list) {
+            ns_list_remove(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_temp_ptr);
+            if (stored_blockwise_msg_temp_ptr->coap_msg_ptr) {
+                if(stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr){
+                    handle->sn_coap_protocol_free(stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr);
+                    stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr = 0;
+                }
+                sn_coap_parser_release_allocated_coap_msg_mem(stored_blockwise_msg_temp_ptr->coap, stored_blockwise_msg_temp_ptr->coap_msg_ptr);
+            }
+
+            handle->sn_coap_protocol_free(stored_blockwise_msg_temp_ptr);
+            stored_blockwise_msg_temp_ptr = 0;
+        }
+    }
+
+    if (!returned_dst_coap_msg_ptr) {
+        tr_error("sn_coap_protocol_parse - returned_dst_coap_msg_ptr null!");
+        return NULL;
+    }
+
+#endif
+
+
+#if ENABLE_RESENDINGS  /* If Message resending is not used at all, this part of code will not be compiled */
+
+    /* Check if received Message type was acknowledgement */
+    if ((returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_ACKNOWLEDGEMENT) || (returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_RESET)) {
+        /* * * * Manage CoAP message resending by removing active resending message from Linked list * * */
+
+        /* Get node count i.e. count of active resending messages */
+        uint16_t stored_resending_msgs_count = handle->count_resent_msgs;
+
+        /* Check if there is ongoing active message resendings */
+        if (stored_resending_msgs_count > 0) {
+            sn_nsdl_transmit_s *removed_msg_ptr = NULL;
+
+            /* Check if received message was confirmation for some active resending message */
+            removed_msg_ptr = sn_coap_protocol_linked_list_send_msg_search(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id);
+
+            if (removed_msg_ptr != NULL) {
+                /* Remove resending message from active message resending Linked list */
+                sn_coap_protocol_linked_list_send_msg_remove(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id);
+            }
+        }
+    }
+#endif /* ENABLE_RESENDINGS */
+
+    /* * * * Return parsed CoAP message  * * * */
+    return returned_dst_coap_msg_ptr;
+}
+
+
+int8_t sn_coap_protocol_exec(struct coap_s *handle, uint32_t current_time)
+{
+    if( !handle ){
+       return -1;
+    }
+
+    /* * * * Store current System time * * * */
+    handle->system_time = current_time;
+
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+    /* * * * Handle block transfer timed outs * * * */
+    sn_coap_protocol_handle_blockwise_timout(handle);
+#endif
+
+#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT
+    /* * * * Remove old duplication messages * * * */
+    sn_coap_protocol_linked_list_duplication_info_remove_old_ones(handle);
+#endif
+
+#if ENABLE_RESENDINGS
+    /* Check if there is ongoing active message sendings */
+    /* foreach_safe isn't sufficient because callback routine could cancel messages. */
+rescan:
+    ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) {
+        // First check that msg belongs to handle
+        if( stored_msg_ptr->coap == handle ){
+            /* Check if it is time to send this message */
+            if (current_time >= stored_msg_ptr->resending_time) {
+                /* * * Increase Resending counter  * * */
+                stored_msg_ptr->resending_counter++;
+
+                /* Check if all re-sendings have been done */
+                if (stored_msg_ptr->resending_counter > handle->sn_coap_resending_count) {
+                    coap_version_e coap_version = COAP_VERSION_UNKNOWN;
+
+                    /* Get message ID from stored sending message */
+                    uint16_t temp_msg_id = (stored_msg_ptr->send_msg_ptr->packet_ptr[2] << 8);
+                    temp_msg_id += (uint16_t)stored_msg_ptr->send_msg_ptr->packet_ptr[3];
+
+                    /* Remove message from Linked list */
+                    ns_list_remove(&handle->linked_list_resent_msgs, stored_msg_ptr);
+                    --handle->count_resent_msgs;
+
+                    /* If RX callback have been defined.. */
+                    if (stored_msg_ptr->coap->sn_coap_rx_callback != 0) {
+                        sn_coap_hdr_s *tmp_coap_hdr_ptr;
+                        /* Parse CoAP message, set status and call RX callback */
+                        tmp_coap_hdr_ptr = sn_coap_parser(stored_msg_ptr->coap, stored_msg_ptr->send_msg_ptr->packet_len, stored_msg_ptr->send_msg_ptr->packet_ptr, &coap_version);
+
+                        if (tmp_coap_hdr_ptr != 0) {
+                            tmp_coap_hdr_ptr->coap_status = COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED;
+                            stored_msg_ptr->coap->sn_coap_rx_callback(tmp_coap_hdr_ptr, stored_msg_ptr->send_msg_ptr->dst_addr_ptr, stored_msg_ptr->param);
+
+                            sn_coap_parser_release_allocated_coap_msg_mem(stored_msg_ptr->coap, tmp_coap_hdr_ptr);
+                        }
+                    }
+
+                    /* Free memory of stored message */
+                    sn_coap_protocol_release_allocated_send_msg_mem(handle, stored_msg_ptr);
+                } else {
+                    /* Send message  */
+                    stored_msg_ptr->coap->sn_coap_tx_callback(stored_msg_ptr->send_msg_ptr->packet_ptr,
+                            stored_msg_ptr->send_msg_ptr->packet_len, stored_msg_ptr->send_msg_ptr->dst_addr_ptr, stored_msg_ptr->param);
+
+                    /* * * Count new Resending time  * * */
+                    stored_msg_ptr->resending_time = sn_coap_calculate_new_resend_time(current_time,
+                                                                                       handle->sn_coap_resending_intervall,
+                                                                                       stored_msg_ptr->resending_counter);
+                }
+                /* Callback routine could have wiped the list (eg as a response to sending failed) */
+                /* Be super cautious and rescan from the start */
+                goto rescan;
+            }
+        }
+    }
+
+#endif /* ENABLE_RESENDINGS */
+
+    return 0;
+}
+
+#if ENABLE_RESENDINGS  /* If Message resending is not used at all, this part of code will not be compiled */
+
+/**************************************************************************//**
+ * \fn static uint8_t sn_coap_protocol_linked_list_send_msg_store(sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len, uint8_t *send_packet_data_ptr, uint32_t sending_time)
+ *
+ * \brief Stores message to Linked list for sending purposes.
+
+ * \param *dst_addr_ptr is pointer to destination address where CoAP message will be sent
+ *
+ * \param send_packet_data_len is length of Packet data to be stored
+ *
+ * \param *send_packet_data_ptr is Packet data to be stored
+ *
+ * \param sending_time is stored sending time
+ *
+ * \return 0 Allocation or buffer limit reached
+ *
+ * \return 1 Msg stored properly
+ *****************************************************************************/
+
+static uint8_t sn_coap_protocol_linked_list_send_msg_store(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t send_packet_data_len,
+        uint8_t *send_packet_data_ptr, uint32_t sending_time, void *param)
+{
+
+    coap_send_msg_s *stored_msg_ptr              = NULL;
+
+    /* If both queue parameters are "0" or resending count is "0", then re-sending is disabled */
+    if (((handle->sn_coap_resending_queue_msgs == 0) && (handle->sn_coap_resending_queue_bytes == 0)) || (handle->sn_coap_resending_count == 0)) {
+        return 1;
+    }
+
+    if (handle->sn_coap_resending_queue_msgs > 0) {
+        if (handle->count_resent_msgs >= handle->sn_coap_resending_queue_msgs) {
+            tr_error("sn_coap_protocol_linked_list_send_msg_store - resend queue full!");
+            return 0;
+        }
+    }
+
+    /* Count resending queue size, if buffer size is defined */
+    if (handle->sn_coap_resending_queue_bytes > 0) {
+        if ((sn_coap_count_linked_list_size(&handle->linked_list_resent_msgs) + send_packet_data_len) > handle->sn_coap_resending_queue_bytes) {
+            tr_error("sn_coap_protocol_linked_list_send_msg_store - resend buffer size reached!");
+            return 0;
+        }
+    }
+
+    /* Allocating memory for stored message */
+    stored_msg_ptr = sn_coap_protocol_allocate_mem_for_msg(handle, dst_addr_ptr, send_packet_data_len);
+
+    if (stored_msg_ptr == 0) {
+        tr_error("sn_coap_protocol_linked_list_send_msg_store - failed to allocate message!");
+        return 0;
+    }
+
+    /* Filling of coap_send_msg_s with initialization values */
+    stored_msg_ptr->resending_counter = 0;
+    stored_msg_ptr->resending_time = sending_time;
+
+    /* Filling of sn_nsdl_transmit_s */
+    stored_msg_ptr->send_msg_ptr->protocol = SN_NSDL_PROTOCOL_COAP;
+    stored_msg_ptr->send_msg_ptr->packet_len = send_packet_data_len;
+    memcpy(stored_msg_ptr->send_msg_ptr->packet_ptr, send_packet_data_ptr, send_packet_data_len);
+
+    /* Filling of sn_nsdl_addr_s */
+    stored_msg_ptr->send_msg_ptr->dst_addr_ptr->type = dst_addr_ptr->type;
+    stored_msg_ptr->send_msg_ptr->dst_addr_ptr->addr_len = dst_addr_ptr->addr_len;
+    memcpy(stored_msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr, dst_addr_ptr->addr_ptr, dst_addr_ptr->addr_len);
+    stored_msg_ptr->send_msg_ptr->dst_addr_ptr->port = dst_addr_ptr->port;
+
+    stored_msg_ptr->coap = handle;
+    stored_msg_ptr->param = param;
+
+    /* Storing Resending message to Linked list */
+    ns_list_add_to_end(&handle->linked_list_resent_msgs, stored_msg_ptr);
+    ++handle->count_resent_msgs;
+    return 1;
+}
+
+/**************************************************************************//**
+ * \fn static sn_nsdl_transmit_s *sn_coap_protocol_linked_list_send_msg_search(sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id)
+ *
+ * \brief Searches stored resending message from Linked list
+ *
+ * \param *src_addr_ptr is searching key for searched message
+ *
+ * \param msg_id is searching key for searched message
+ *
+ * \return Return value is pointer to found stored resending message in Linked
+ *         list or NULL if message not found
+ *****************************************************************************/
+
+static sn_nsdl_transmit_s *sn_coap_protocol_linked_list_send_msg_search(struct coap_s *handle,
+        sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id)
+{
+    /* Loop all stored resending messages Linked list */
+    ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) {
+        /* Get message ID from stored resending message */
+        uint16_t temp_msg_id = (stored_msg_ptr->send_msg_ptr->packet_ptr[2] << 8);
+        temp_msg_id += (uint16_t)stored_msg_ptr->send_msg_ptr->packet_ptr[3];
+
+        /* If message's Message ID is same than is searched */
+        if (temp_msg_id == msg_id) {
+            /* If message's Source address is same than is searched */
+            if (0 == memcmp(src_addr_ptr->addr_ptr, stored_msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr, src_addr_ptr->addr_len)) {
+                /* If message's Source address port is same than is searched */
+                if (stored_msg_ptr->send_msg_ptr->dst_addr_ptr->port == src_addr_ptr->port) {
+                    /* * * Message found, return pointer to that stored resending message * * * */
+                    return stored_msg_ptr->send_msg_ptr;
+                }
+            }
+        }
+    }
+
+    /* Message not found */
+    return NULL;
+}
+/**************************************************************************//**
+ * \fn static void sn_coap_protocol_linked_list_send_msg_remove(sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id)
+ *
+ * \brief Removes stored resending message from Linked list
+ *
+ * \param *src_addr_ptr is searching key for searched message
+ * \param msg_id is searching key for removed message
+ *****************************************************************************/
+
+static void sn_coap_protocol_linked_list_send_msg_remove(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t msg_id)
+{
+    /* Loop all stored resending messages in Linked list */
+    ns_list_foreach(coap_send_msg_s, stored_msg_ptr, &handle->linked_list_resent_msgs) {
+        /* Get message ID from stored resending message */
+        uint16_t temp_msg_id = (stored_msg_ptr->send_msg_ptr->packet_ptr[2] << 8);
+        temp_msg_id += (uint16_t)stored_msg_ptr->send_msg_ptr->packet_ptr[3];
+
+        /* If message's Message ID is same than is searched */
+        if (temp_msg_id == msg_id) {
+            /* If message's Source address is same than is searched */
+            if (0 == memcmp(src_addr_ptr->addr_ptr, stored_msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr, src_addr_ptr->addr_len)) {
+                /* If message's Source address port is same than is searched */
+                if (stored_msg_ptr->send_msg_ptr->dst_addr_ptr->port == src_addr_ptr->port) {
+                    /* * * Message found * * */
+
+                    /* Remove message from Linked list */
+                    ns_list_remove(&handle->linked_list_resent_msgs, stored_msg_ptr);
+                    --handle->count_resent_msgs;
+
+                    /* Free memory of stored message */
+                    sn_coap_protocol_release_allocated_send_msg_mem(handle, stored_msg_ptr);
+
+                    return;
+                }
+            }
+        }
+    }
+}
+
+uint32_t sn_coap_calculate_new_resend_time(const uint32_t current_time, const uint8_t interval, const uint8_t counter)
+{
+    uint32_t resend_time = interval << counter;
+    uint16_t random_factor = randLIB_get_random_in_range(100, RESPONSE_RANDOM_FACTOR * 100);
+    return current_time + ((resend_time * random_factor) / 100);
+}
+
+#endif /* ENABLE_RESENDINGS */
+
+void sn_coap_protocol_send_rst(struct coap_s *handle, uint16_t msg_id, sn_nsdl_addr_s *addr_ptr, void *param)
+{
+    uint8_t packet_ptr[4];
+
+    /* Add CoAP version and message type */
+    packet_ptr[0] = COAP_VERSION_1;
+    packet_ptr[0] |= COAP_MSG_TYPE_RESET;
+
+    /* Add message code */
+    packet_ptr[1] = COAP_MSG_CODE_EMPTY;
+
+    /* Add message ID */
+    packet_ptr[2] = msg_id >> 8;
+    packet_ptr[3] = (uint8_t)msg_id;
+
+    /* Send RST */
+    handle->sn_coap_tx_callback(packet_ptr, 4, addr_ptr, param);
+
+}
+
+uint16_t sn_coap_protocol_get_configured_blockwise_size(struct coap_s *handle)
+{
+    return handle->sn_coap_block_data_size;
+}
+
+#if SN_COAP_DUPLICATION_MAX_MSGS_COUNT /* If Message duplication detection is not used at all, this part of code will not be compiled */
+
+/**************************************************************************//**
+ * \fn static void sn_coap_protocol_linked_list_duplication_info_store(sn_nsdl_addr_s *addr_ptr, uint16_t msg_id)
+ *
+ * \brief Stores Duplication info to Linked list
+ *
+ * \param msg_id is Message ID to be stored
+ * \param *addr_ptr is pointer to Address information to be stored
+ *****************************************************************************/
+
+static void sn_coap_protocol_linked_list_duplication_info_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr,
+        uint16_t msg_id, void *param)
+{
+    coap_duplication_info_s *stored_duplication_info_ptr = NULL;
+
+    /* * * * Allocating memory for stored Duplication info * * * */
+
+    /* Allocate memory for stored Duplication info's structure */
+    stored_duplication_info_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_duplication_info_s));
+
+    if (stored_duplication_info_ptr == NULL) {
+        tr_error("sn_coap_protocol_linked_list_duplication_info_store - failed to allocate duplication info!");
+        return;
+    }
+    memset(stored_duplication_info_ptr, 0, sizeof(coap_duplication_info_s));
+
+    /* Allocate memory for stored Duplication info's address */
+    stored_duplication_info_ptr->address = handle->sn_coap_protocol_malloc(sizeof(sn_nsdl_addr_s));
+    if (stored_duplication_info_ptr->address == NULL) {
+        tr_error("sn_coap_protocol_linked_list_duplication_info_store - failed to allocate address!");
+        handle->sn_coap_protocol_free(stored_duplication_info_ptr);
+        stored_duplication_info_ptr = 0;
+        return;
+    }
+    memset(stored_duplication_info_ptr->address, 0, sizeof(sn_nsdl_addr_s));
+
+    stored_duplication_info_ptr->address->addr_ptr = handle->sn_coap_protocol_malloc(addr_ptr->addr_len);
+
+    if (stored_duplication_info_ptr->address->addr_ptr == NULL) {
+        tr_error("sn_coap_protocol_linked_list_duplication_info_store - failed to allocate address pointer!");
+        handle->sn_coap_protocol_free(stored_duplication_info_ptr->address);
+        stored_duplication_info_ptr->address = 0;
+        handle->sn_coap_protocol_free(stored_duplication_info_ptr);
+        stored_duplication_info_ptr = 0;
+        return;
+    }
+
+    /* * * * Filling fields of stored Duplication info * * * */
+    stored_duplication_info_ptr->timestamp = handle->system_time;
+    stored_duplication_info_ptr->address->addr_len = addr_ptr->addr_len;
+    memcpy(stored_duplication_info_ptr->address->addr_ptr, addr_ptr->addr_ptr, addr_ptr->addr_len);
+    stored_duplication_info_ptr->address->port = addr_ptr->port;
+    stored_duplication_info_ptr->msg_id = msg_id;
+
+    stored_duplication_info_ptr->coap = handle;
+
+    stored_duplication_info_ptr->param = param;
+    /* * * * Storing Duplication info to Linked list * * * */
+
+    ns_list_add_to_end(&handle->linked_list_duplication_msgs, stored_duplication_info_ptr);
+    ++handle->count_duplication_msgs;
+}
+
+/**************************************************************************//**
+ * \fn static int8_t sn_coap_protocol_linked_list_duplication_info_search(sn_nsdl_addr_s *addr_ptr, uint16_t msg_id)
+ *
+ * \brief Searches stored message from Linked list (Address and Message ID as key)
+ *
+ * \param *addr_ptr is pointer to Address key to be searched
+ * \param msg_id is Message ID key to be searched
+ *
+ * \return Return value is 0 when message found and -1 if not found
+ *****************************************************************************/
+
+static coap_duplication_info_s* sn_coap_protocol_linked_list_duplication_info_search(struct coap_s *handle,
+        sn_nsdl_addr_s *addr_ptr, uint16_t msg_id)
+{
+    /* Loop all nodes in Linked list for searching Message ID */
+    ns_list_foreach(coap_duplication_info_s, stored_duplication_info_ptr, &handle->linked_list_duplication_msgs) {
+        /* If message's Message ID is same than is searched */
+        if (stored_duplication_info_ptr->msg_id == msg_id) {
+            /* If message's Source address is same than is searched */
+            if (0 == memcmp(addr_ptr->addr_ptr, stored_duplication_info_ptr->address->addr_ptr, addr_ptr->addr_len)) {
+                /* If message's Source address port is same than is searched */
+                if (stored_duplication_info_ptr->address->port == addr_ptr->port) {
+                    /* * * Correct Duplication info found * * * */
+                    return stored_duplication_info_ptr;
+                }
+            }
+        }
+    }
+    return NULL;
+}
+
+/**************************************************************************//**
+ * \fn static void sn_coap_protocol_linked_list_duplication_info_remove(struct coap_s *handle, uint8_t *addr_ptr, uint16_t port, uint16_t msg_id)
+ *
+ * \brief Removes stored Duplication info from Linked list
+ *
+ * \param *addr_ptr is pointer to Address key to be removed
+ *
+ * \param port is Port key to be removed
+ *
+ * \param msg_id is Message ID key to be removed
+ *****************************************************************************/
+
+static void sn_coap_protocol_linked_list_duplication_info_remove(struct coap_s *handle, uint8_t *addr_ptr, uint16_t port, uint16_t msg_id)
+{
+    /* Loop all stored duplication messages in Linked list */
+    ns_list_foreach(coap_duplication_info_s, removed_duplication_info_ptr, &handle->linked_list_duplication_msgs) {
+        /* If message's Address is same than is searched */
+        if (handle == removed_duplication_info_ptr->coap && 0 == memcmp(addr_ptr,
+                                                                        removed_duplication_info_ptr->address->addr_ptr,
+                                                                        removed_duplication_info_ptr->address->addr_len)) {
+            /* If message's Address prt is same than is searched */
+            if (removed_duplication_info_ptr->address->port == port) {
+                /* If Message ID is same than is searched */
+                if (removed_duplication_info_ptr->msg_id == msg_id) {
+                    /* * * * Correct Duplication info found, remove it from Linked list * * * */
+                    ns_list_remove(&handle->linked_list_duplication_msgs, removed_duplication_info_ptr);
+                    --handle->count_duplication_msgs;
+
+                    /* Free memory of stored Duplication info */
+                    handle->sn_coap_protocol_free(removed_duplication_info_ptr->address->addr_ptr);
+                    removed_duplication_info_ptr->address->addr_ptr = 0;
+                    handle->sn_coap_protocol_free(removed_duplication_info_ptr->address);
+                    removed_duplication_info_ptr->address = 0;
+                    handle->sn_coap_protocol_free(removed_duplication_info_ptr->packet_ptr);
+                    removed_duplication_info_ptr->packet_ptr = 0;
+                    handle->sn_coap_protocol_free(removed_duplication_info_ptr);
+                    removed_duplication_info_ptr = 0;
+                    return;
+                }
+            }
+        }
+    }
+}
+
+/**************************************************************************//**
+ * \fn static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle)
+ *
+ * \brief Removes old stored Duplication detection infos from Linked list
+ *****************************************************************************/
+
+static void sn_coap_protocol_linked_list_duplication_info_remove_old_ones(struct coap_s *handle)
+{
+    /* Loop all stored duplication messages in Linked list */
+    ns_list_foreach_safe(coap_duplication_info_s, removed_duplication_info_ptr, &handle->linked_list_duplication_msgs) {
+        if ((handle->system_time - removed_duplication_info_ptr->timestamp)  > SN_COAP_DUPLICATION_MAX_TIME_MSGS_STORED) {
+            /* * * * Old Duplication info found, remove it from Linked list * * * */
+            ns_list_remove(&handle->linked_list_duplication_msgs, removed_duplication_info_ptr);
+            --handle->count_duplication_msgs;
+
+            /* Free memory of stored Duplication info */
+            handle->sn_coap_protocol_free(removed_duplication_info_ptr->address->addr_ptr);
+            removed_duplication_info_ptr->address->addr_ptr = 0;
+            handle->sn_coap_protocol_free(removed_duplication_info_ptr->address);
+            removed_duplication_info_ptr->address = 0;
+            handle->sn_coap_protocol_free(removed_duplication_info_ptr->packet_ptr);
+            removed_duplication_info_ptr->packet_ptr = 0;
+            handle->sn_coap_protocol_free(removed_duplication_info_ptr);
+            removed_duplication_info_ptr = 0;
+        }
+    }
+}
+
+#endif /* SN_COAP_DUPLICATION_MAX_MSGS_COUNT */
+
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+/**************************************************************************//**
+ * \fn static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr)
+ *
+ * \brief Removes stored blockwise message from Linked list
+ *
+ * \param removed_msg_ptr is message to be removed
+ *****************************************************************************/
+
+static void sn_coap_protocol_linked_list_blockwise_msg_remove(struct coap_s *handle, coap_blockwise_msg_s *removed_msg_ptr)
+{
+    if( removed_msg_ptr->coap == handle ){
+        ns_list_remove(&handle->linked_list_blockwise_sent_msgs, removed_msg_ptr);
+
+        if( removed_msg_ptr->coap_msg_ptr ){
+            if (removed_msg_ptr->coap_msg_ptr->payload_ptr) {
+                handle->sn_coap_protocol_free(removed_msg_ptr->coap_msg_ptr->payload_ptr);
+                removed_msg_ptr->coap_msg_ptr->payload_ptr = 0;
+            }
+
+            sn_coap_parser_release_allocated_coap_msg_mem(handle, removed_msg_ptr->coap_msg_ptr);
+        }
+
+        handle->sn_coap_protocol_free(removed_msg_ptr);
+        removed_msg_ptr = 0;
+    }
+}
+
+/**************************************************************************//**
+ * \fn static void sn_coap_protocol_linked_list_blockwise_payload_store(sn_nsdl_addr_s *addr_ptr, uint16_t stored_payload_len, uint8_t *stored_payload_ptr)
+ *
+ * \brief Stores blockwise payload to Linked list
+ *
+ * \param *addr_ptr is pointer to Address information to be stored
+ * \param stored_payload_len is length of stored Payload
+ * \param *stored_payload_ptr is pointer to stored Payload
+ *****************************************************************************/
+
+static void sn_coap_protocol_linked_list_blockwise_payload_store(struct coap_s *handle, sn_nsdl_addr_s *addr_ptr,
+        uint16_t stored_payload_len,
+        uint8_t *stored_payload_ptr,
+        uint8_t *token_ptr,
+        uint8_t token_len,
+        uint32_t block_number)
+{
+    if (!addr_ptr || !stored_payload_len || !stored_payload_ptr) {
+        return;
+    }
+
+    // Do not add duplicates to list, this could happen if server needs to retransmit block message again
+    ns_list_foreach(coap_blockwise_payload_s, payload_info_ptr, &handle->linked_list_blockwise_received_payloads) {
+        if ((0 == memcmp(addr_ptr->addr_ptr, payload_info_ptr->addr_ptr, addr_ptr->addr_len)) && (payload_info_ptr->port == addr_ptr->port)) {
+            if (token_ptr) {
+                if (!payload_info_ptr->token_ptr || (payload_info_ptr->token_len != token_len) || (memcmp(payload_info_ptr->token_ptr, token_ptr, token_len))) {
+                    continue;
+                }
+            } else if (payload_info_ptr->token_ptr) {
+                continue;
+            }
+            if (payload_info_ptr->block_number == block_number) {
+                return;
+            }
+        }
+    }
+
+    coap_blockwise_payload_s *stored_blockwise_payload_ptr = NULL;
+
+    /* * * * Allocating memory for stored Payload  * * * */
+
+    /* Allocate memory for stored Payload's structure */
+    stored_blockwise_payload_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_payload_s));
+
+    if (stored_blockwise_payload_ptr == NULL) {
+        tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate blockwise!");
+        return;
+    }
+
+
+    /* Allocate memory for stored Payload's data */
+    stored_blockwise_payload_ptr->payload_ptr = handle->sn_coap_protocol_malloc(stored_payload_len);
+
+    if (stored_blockwise_payload_ptr->payload_ptr == NULL) {
+        tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate payload!");
+        handle->sn_coap_protocol_free(stored_blockwise_payload_ptr);
+        stored_blockwise_payload_ptr = 0;
+        return;
+    }
+
+    /* Allocate memory for stored Payload's address */
+    stored_blockwise_payload_ptr->addr_ptr = handle->sn_coap_protocol_malloc(addr_ptr->addr_len);
+
+    if (stored_blockwise_payload_ptr->addr_ptr == NULL) {
+        tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate address pointer!");
+        handle->sn_coap_protocol_free(stored_blockwise_payload_ptr->payload_ptr);
+        stored_blockwise_payload_ptr->payload_ptr = 0;
+        handle->sn_coap_protocol_free(stored_blockwise_payload_ptr);
+        stored_blockwise_payload_ptr = 0;
+
+        return;
+    }
+
+    /* Allocate & copy token number */
+    if (token_ptr && token_len) {
+        stored_blockwise_payload_ptr->token_ptr = handle->sn_coap_protocol_malloc(token_len);
+
+        if(!stored_blockwise_payload_ptr->token_ptr) {
+            tr_error("sn_coap_protocol_linked_list_blockwise_payload_store - failed to allocate token pointer!");
+            handle->sn_coap_protocol_free(stored_blockwise_payload_ptr->addr_ptr);
+            handle->sn_coap_protocol_free(stored_blockwise_payload_ptr->payload_ptr);
+            handle->sn_coap_protocol_free(stored_blockwise_payload_ptr);
+            return;
+        }
+
+        memcpy(stored_blockwise_payload_ptr->token_ptr, token_ptr, token_len);
+        stored_blockwise_payload_ptr->token_len = token_len;
+    } else {
+        stored_blockwise_payload_ptr->token_ptr = NULL;
+        stored_blockwise_payload_ptr->token_len = 0;
+    }
+
+    /* * * * Filling fields of stored Payload  * * * */
+
+    stored_blockwise_payload_ptr->timestamp = handle->system_time;
+
+    memcpy(stored_blockwise_payload_ptr->addr_ptr, addr_ptr->addr_ptr, addr_ptr->addr_len);
+    stored_blockwise_payload_ptr->port = addr_ptr->port;
+    memcpy(stored_blockwise_payload_ptr->payload_ptr, stored_payload_ptr, stored_payload_len);
+    stored_blockwise_payload_ptr->payload_len = stored_payload_len;
+
+    stored_blockwise_payload_ptr->coap = handle;
+
+    stored_blockwise_payload_ptr->block_number = block_number;
+
+    /* * * * Storing Payload to Linked list  * * * */
+    ns_list_add_to_end(&handle->linked_list_blockwise_received_payloads, stored_blockwise_payload_ptr);
+}
+
+/**************************************************************************//**
+ * \fn static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length)
+ *
+ * \brief Searches stored blockwise payload from Linked list (Address as key)
+ *
+ * \param *addr_ptr is pointer to Address key to be searched
+ * \param *payload_length is pointer to returned Payload length
+ *
+ * \return Return value is pointer to found stored blockwise payload in Linked
+ *         list or NULL if payload not found
+ *****************************************************************************/
+
+static uint8_t *sn_coap_protocol_linked_list_blockwise_payload_search(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint16_t *payload_length, uint8_t *token_ptr, uint8_t token_len)
+{
+    /* Loop all stored blockwise payloads in Linked list */
+    ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) {
+        /* If payload's Source address and port is same than is searched */
+        if ((0 == memcmp(src_addr_ptr->addr_ptr, stored_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) && (stored_payload_info_ptr->port == src_addr_ptr->port)) {
+            /* Check token */
+            if (token_ptr) {
+                if (!stored_payload_info_ptr->token_ptr || (token_len != stored_payload_info_ptr->token_len) || (memcmp(stored_payload_info_ptr->token_ptr, token_ptr, token_len))) {
+                    continue;
+                }
+            } else if (stored_payload_info_ptr->token_ptr) {
+                continue;
+            }
+            /* * * Correct Payload found * * * */
+            *payload_length = stored_payload_info_ptr->payload_len;
+            return stored_payload_info_ptr->payload_ptr;
+        }
+    }
+
+    return NULL;
+}
+
+static bool sn_coap_protocol_linked_list_blockwise_payload_compare_block_number(struct coap_s *handle,
+                                                                                   sn_nsdl_addr_s *src_addr_ptr,
+                                                                                   uint8_t *token_ptr,
+                                                                                   uint8_t token_len,
+                                                                                   uint32_t block_number)
+{
+    /* Loop all stored blockwise payloads in Linked list */
+    ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) {
+        /* If payload's Source address and port is same than is searched */
+        if ((0 == memcmp(src_addr_ptr->addr_ptr, stored_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) && (stored_payload_info_ptr->port == src_addr_ptr->port)) {
+            /* Check token number */
+            if (token_ptr) {
+                if (!stored_payload_info_ptr->token_ptr || (token_len != stored_payload_info_ptr->token_len) || (memcmp(stored_payload_info_ptr->token_ptr, token_ptr, token_len))) {
+                    continue;
+                }
+            } else if (stored_payload_info_ptr->token_ptr) {
+                continue;
+            }
+            // Check that incoming block number matches to last received one
+            if (block_number - 1 == stored_payload_info_ptr->block_number) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+/**************************************************************************//**
+ * \fn static void sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(struct coap_s *handle)
+ *
+ * \brief Removes current stored blockwise paylod from Linked list
+ *****************************************************************************/
+
+static void sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(struct coap_s *handle, uint8_t *token_ptr, uint8_t token_len)
+{
+    /* Remove oldest node in Linked list*/
+    if (token_ptr) {
+        ns_list_foreach(coap_blockwise_payload_s, removed_payload_ptr, &handle->linked_list_blockwise_received_payloads) {
+            if ((token_len == removed_payload_ptr->token_len) && !memcmp(removed_payload_ptr->token_ptr, token_ptr, token_len)) {
+                sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_payload_ptr);
+                return;
+            }
+        }
+    } else {
+        ns_list_foreach(coap_blockwise_payload_s, removed_payload_ptr, &handle->linked_list_blockwise_received_payloads) {
+            if (!removed_payload_ptr->token_ptr) {
+                sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_payload_ptr);
+                return;
+            }
+        }
+    }
+}
+
+/**************************************************************************//**
+ * \fn static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle,
+ *                                                      coap_blockwise_msg_s *removed_msg_ptr)
+ *
+ * \brief Removes stored blockwise payload from Linked list
+ *
+ * \param removed_payload_ptr is payload to be removed
+ *****************************************************************************/
+
+static void sn_coap_protocol_linked_list_blockwise_payload_remove(struct coap_s *handle,
+                                                                  coap_blockwise_payload_s *removed_payload_ptr)
+{
+    ns_list_remove(&handle->linked_list_blockwise_received_payloads, removed_payload_ptr);
+    /* Free memory of stored payload */
+    if (removed_payload_ptr->addr_ptr != NULL) {
+        handle->sn_coap_protocol_free(removed_payload_ptr->addr_ptr);
+        removed_payload_ptr->addr_ptr = 0;
+    }
+
+    if (removed_payload_ptr->payload_ptr != NULL) {
+        handle->sn_coap_protocol_free(removed_payload_ptr->payload_ptr);
+        removed_payload_ptr->payload_ptr = 0;
+    }
+
+    if (removed_payload_ptr->token_ptr != NULL) {
+        handle->sn_coap_protocol_free(removed_payload_ptr->token_ptr);
+        removed_payload_ptr->token_ptr = 0;
+    }
+
+    handle->sn_coap_protocol_free(removed_payload_ptr);
+    removed_payload_ptr = 0;
+}
+
+/**************************************************************************//**
+ * \fn static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(sn_nsdl_addr_s *src_addr_ptr)
+ *
+ * \brief Counts length of Payloads in Linked list (Address as key)
+ *
+ * \param *addr_ptr is pointer to Address key
+ *
+ * \return Return value is length of Payloads as bytes
+ *****************************************************************************/
+
+static uint32_t sn_coap_protocol_linked_list_blockwise_payloads_get_len(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, uint8_t *token_ptr, uint8_t token_len)
+{
+    uint32_t ret_whole_payload_len = 0;
+    /* Loop all stored blockwise payloads in Linked list */
+    ns_list_foreach(coap_blockwise_payload_s, searched_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) {
+        /* If payload's Source address and port is same than is searched */
+        if ((0 == memcmp(src_addr_ptr->addr_ptr, searched_payload_info_ptr->addr_ptr, src_addr_ptr->addr_len)) && (searched_payload_info_ptr->port == src_addr_ptr->port)) {
+            /* Check token */
+            if (token_ptr) {
+                if(!searched_payload_info_ptr->token_ptr || (token_len != searched_payload_info_ptr->token_len) || (memcmp(searched_payload_info_ptr->token_ptr, token_ptr, token_len))) {
+                    continue;
+                }
+            } else if (searched_payload_info_ptr->token_ptr) {
+                continue;
+            }
+            /* * * Correct Payload found * * * */
+            ret_whole_payload_len += searched_payload_info_ptr->payload_len;
+        }
+    }
+
+    return ret_whole_payload_len;
+}
+
+/**************************************************************************//**
+ * \fn static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle)
+ *
+ * \brief Check incoming and outgoing blockwise messages for time out.
+ *        Remove timed out messages from lists. Notify application if
+ *        outgoing message times out.
+ *****************************************************************************/
+
+static void sn_coap_protocol_handle_blockwise_timout(struct coap_s *handle)
+{
+    /* Loop all outgoing blockwise messages */
+    ns_list_foreach_safe(coap_blockwise_msg_s, removed_blocwise_msg_ptr, &handle->linked_list_blockwise_sent_msgs) {
+        if ((handle->system_time - removed_blocwise_msg_ptr->timestamp)  > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) {
+
+            // Item must be removed from the list before calling the rx_callback function.
+            // Callback could actually clear the list and free the item and cause a use after free when callback returns.
+            ns_list_remove(&handle->linked_list_blockwise_sent_msgs, removed_blocwise_msg_ptr);
+
+            /* * * * This messages has timed out, remove it from Linked list * * * */
+            if( removed_blocwise_msg_ptr->coap_msg_ptr ){
+                if (handle->sn_coap_rx_callback) {
+                    /* Notify the application about the time out */
+                    removed_blocwise_msg_ptr->coap_msg_ptr->coap_status = COAP_STATUS_BUILDER_BLOCK_SENDING_FAILED;
+                    removed_blocwise_msg_ptr->coap_msg_ptr->msg_id = removed_blocwise_msg_ptr->msg_id;
+                    handle->sn_coap_rx_callback(removed_blocwise_msg_ptr->coap_msg_ptr, NULL, removed_blocwise_msg_ptr->param);
+                }
+
+                handle->sn_coap_protocol_free(removed_blocwise_msg_ptr->coap_msg_ptr->payload_ptr);
+                sn_coap_parser_release_allocated_coap_msg_mem(handle, removed_blocwise_msg_ptr->coap_msg_ptr);
+            }
+
+            handle->sn_coap_protocol_free(removed_blocwise_msg_ptr);
+        }
+    }
+
+
+    /* Loop all incoming Blockwise messages */
+    ns_list_foreach_safe(coap_blockwise_payload_s, removed_blocwise_payload_ptr, &handle->linked_list_blockwise_received_payloads) {
+        if ((handle->system_time - removed_blocwise_payload_ptr->timestamp)  > SN_COAP_BLOCKWISE_MAX_TIME_DATA_STORED) {
+            /* * * * This messages has timed out, remove it from Linked list * * * */
+            sn_coap_protocol_linked_list_blockwise_payload_remove(handle, removed_blocwise_payload_ptr);
+        }
+    }
+}
+
+#endif /* SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE */
+
+
+#if ENABLE_RESENDINGS  /* If Message resending is not used at all, this part of code will not be compiled */
+/***************************************************************************//**
+ * \fn int8_t sn_coap_protocol_allocate_mem_for_msg(sn_nsdl_addr_s *dst_addr_ptr, uint16_t packet_data_len, coap_send_msg_s *msg_ptr)
+ *
+ * \brief Allocates memory for given message (send or blockwise message)
+ *
+ * \param *dst_addr_ptr is pointer to destination address where message will be sent
+ * \param packet_data_len is length of allocated Packet data
+ * \param uri_path_len is length of messages path url
+ *
+ * \return pointer to allocated struct
+ *****************************************************************************/
+
+coap_send_msg_s *sn_coap_protocol_allocate_mem_for_msg(struct coap_s *handle, sn_nsdl_addr_s *dst_addr_ptr, uint16_t packet_data_len)
+{
+
+    coap_send_msg_s *msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_send_msg_s));
+
+    if (msg_ptr == NULL) {
+        return NULL;
+    }
+
+    //Locall structure for 1 malloc for send msg
+    struct
+    {
+        sn_nsdl_transmit_s transmit;
+        sn_nsdl_addr_s addr;
+        uint8_t trail_data[];
+    } *m;
+    int trail_size = dst_addr_ptr->addr_len + packet_data_len;
+
+    m = handle->sn_coap_protocol_malloc(sizeof *m + trail_size);
+    if (!m) {
+        handle->sn_coap_protocol_free(msg_ptr);
+        return NULL;
+    }
+    //Init data
+    memset(m, 0, sizeof(*m) + trail_size);
+    memset(msg_ptr, 0, sizeof(coap_send_msg_s));
+
+    msg_ptr->send_msg_ptr = &m->transmit;
+    msg_ptr->send_msg_ptr->dst_addr_ptr = &m->addr;
+
+    msg_ptr->send_msg_ptr->dst_addr_ptr->addr_ptr = m->trail_data;
+    if (packet_data_len) {
+        msg_ptr->send_msg_ptr->packet_ptr = m->trail_data + dst_addr_ptr->addr_len;
+    }
+
+    return msg_ptr;
+}
+
+
+/**************************************************************************//**
+ * \fn static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr)
+ *
+ * \brief Releases memory of given Sending message (coap_send_msg_s)
+ *
+ * \param *freed_send_msg_ptr is pointer to released Sending message
+ *****************************************************************************/
+
+static void sn_coap_protocol_release_allocated_send_msg_mem(struct coap_s *handle, coap_send_msg_s *freed_send_msg_ptr)
+{
+    if (freed_send_msg_ptr != NULL) {
+        handle->sn_coap_protocol_free(freed_send_msg_ptr->send_msg_ptr);
+        freed_send_msg_ptr->send_msg_ptr = NULL;
+        handle->sn_coap_protocol_free(freed_send_msg_ptr);
+        freed_send_msg_ptr = NULL;
+    }
+}
+
+/**************************************************************************//**
+ * \fn static uint16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr)
+ *
+ * \brief Counts total message size of all messages in linked list
+ *
+ * \param const coap_send_msg_list_t *linked_list_ptr pointer to linked list
+ *****************************************************************************/
+static uint16_t sn_coap_count_linked_list_size(const coap_send_msg_list_t *linked_list_ptr)
+{
+    uint16_t total_size = 0;
+
+    ns_list_foreach(coap_send_msg_s, stored_msg_ptr, linked_list_ptr) {
+        if (stored_msg_ptr->send_msg_ptr) {
+            total_size += stored_msg_ptr->send_msg_ptr->packet_len;
+        }
+    }
+
+    return total_size;
+}
+
+#endif
+
+#if SN_COAP_BLOCKWISE_ENABLED || SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE
+void sn_coap_protocol_remove_sent_blockwise_message(struct coap_s *handle, uint16_t msg_id)
+{
+    if (!handle) {
+        return;
+    }
+
+    ns_list_foreach_safe(coap_blockwise_msg_s, tmp, &handle->linked_list_blockwise_sent_msgs) {
+        if (tmp->coap == handle && tmp->coap_msg_ptr && tmp->coap_msg_ptr->msg_id == msg_id) {
+            handle->sn_coap_protocol_free(tmp->coap_msg_ptr->payload_ptr);
+            sn_coap_parser_release_allocated_coap_msg_mem(tmp->coap, tmp->coap_msg_ptr);
+            ns_list_remove(&handle->linked_list_blockwise_sent_msgs, tmp);
+            handle->sn_coap_protocol_free(tmp);
+            break;
+        }
+    }
+}
+
+void sn_coap_protocol_block_remove(struct coap_s *handle, sn_nsdl_addr_s *source_address, uint16_t payload_length, void *payload)
+{
+    if (!handle || !source_address || !payload) {
+        return;
+    }
+
+    /* Loop all stored blockwise payloads in Linked list */
+    ns_list_foreach(coap_blockwise_payload_s, stored_payload_info_ptr, &handle->linked_list_blockwise_received_payloads) {
+        /* If payload's Source address is not the same than is searched */
+        if (memcmp(source_address->addr_ptr, stored_payload_info_ptr->addr_ptr, source_address->addr_len)) {
+            continue;
+        }
+
+        /* If payload's Source address port is not the same than is searched */
+        if (stored_payload_info_ptr->port != source_address->port) {
+            continue;
+        }
+
+        /* Check the payload */
+        if(payload_length != stored_payload_info_ptr->payload_len){
+            continue;
+        }
+
+        if(!memcmp(stored_payload_info_ptr->payload_ptr, payload, stored_payload_info_ptr->payload_len))
+        {
+            /* Everything matches, remove and return. */
+            sn_coap_protocol_linked_list_blockwise_payload_remove(handle, stored_payload_info_ptr);
+            return;
+        }
+    }
+}
+
+/****************************************************************************
+ * \fn coap_blockwise_msg_s *sn_coap_stored_blockwise_msg_get(struct coap_s *handle, sn_coap_hdr_s *received_coap_msg_ptr)
+ *
+ * \brief Get blockwise message from list
+ *
+ * \param *handle Pointer to the coap handle structure
+ * \param *received_coap_msg_ptr Pointer to parsed CoAP message structure
+ *****************************************************************************/
+static coap_blockwise_msg_s *sn_coap_stored_blockwise_msg_get(struct coap_s *handle, sn_coap_hdr_s *received_coap_msg_ptr)
+{
+    ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) {
+        if (!received_coap_msg_ptr->token_ptr && !msg->coap_msg_ptr->token_ptr) {
+            return msg;
+        } else if ((received_coap_msg_ptr->token_len == msg->coap_msg_ptr->token_len) && (!memcmp(received_coap_msg_ptr->token_ptr, msg->coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len))) {
+            return msg;
+        }
+    }
+
+    return NULL;
+}
+
+/**************************************************************************//**
+ * \fn static int8_t sn_coap_handle_blockwise_message(void)
+ *
+ * \brief Handles all received blockwise messages
+ *
+ * \param *src_addr_ptr pointer to source address information struct
+ * \param *received_coap_msg_ptr pointer to parsed CoAP message structure
+ *****************************************************************************/
+
+static sn_coap_hdr_s *sn_coap_handle_blockwise_message(struct coap_s *handle, sn_nsdl_addr_s *src_addr_ptr, sn_coap_hdr_s *received_coap_msg_ptr, void *param)
+{
+    sn_coap_hdr_s *src_coap_blockwise_ack_msg_ptr = NULL;
+    uint16_t dst_packed_data_needed_mem = 0;
+    uint8_t *dst_ack_packet_data_ptr = NULL;
+    uint8_t block_temp = 0;
+
+    uint16_t original_payload_len = 0;
+    uint8_t *original_payload_ptr = NULL;
+
+    /* Block1 Option in a request (e.g., PUT or POST) */
+    // Blocked request sending, received ACK, sending next block..
+    if (received_coap_msg_ptr->options_list_ptr->block1 != COAP_OPTION_BLOCK_NONE) {
+        if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) {
+            if (received_coap_msg_ptr->options_list_ptr->block1 & 0x08) {
+                coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = NULL;
+
+                /* Get  */
+                ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) {
+                    if (msg->coap_msg_ptr && received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) {
+                        stored_blockwise_msg_temp_ptr = msg;
+                        break;
+                    }
+                }
+
+                if (stored_blockwise_msg_temp_ptr) {
+                    /* Build response message */
+
+                    uint16_t block_size;
+                    uint32_t block_number;
+
+                    /* Get block option parameters from received message */
+                    block_number = received_coap_msg_ptr->options_list_ptr->block1 >> 4;
+                    block_temp = received_coap_msg_ptr->options_list_ptr->block1 & 0x07;
+                    block_size = 1u << (block_temp + 4);
+
+                    /* Build next block message */
+                    src_coap_blockwise_ack_msg_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr;
+
+                    if (src_coap_blockwise_ack_msg_ptr->options_list_ptr) {
+                        src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE;
+                        src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = COAP_OPTION_BLOCK_NONE;
+                    } else {
+                        if (!sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr)) {
+                            tr_error("sn_coap_handle_blockwise_message - (send block1) failed to allocate ack message!");
+                            sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
+                            return 0;
+                        }
+                    }
+
+                    block_number++;
+                    src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = (block_number << 4) | block_temp;
+
+                    original_payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len;
+                    original_payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr;
+
+                    if ((block_size * (block_number + 1)) > stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len) {
+                        src_coap_blockwise_ack_msg_ptr->payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len - (block_size * (block_number));
+                        src_coap_blockwise_ack_msg_ptr->payload_ptr = src_coap_blockwise_ack_msg_ptr->payload_ptr + (block_size * block_number);
+                    }
+
+                    /* Not last block */
+                    else {
+                        /* set more - bit */
+                        src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= 0x08;
+                        src_coap_blockwise_ack_msg_ptr->payload_len = block_size;
+                        src_coap_blockwise_ack_msg_ptr->payload_ptr = src_coap_blockwise_ack_msg_ptr->payload_ptr + (block_size * block_number);
+                    }
+                    /* Build and send block message */
+                    dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size);
+
+                    dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem);
+                    if (!dst_ack_packet_data_ptr) {
+                        tr_error("sn_coap_handle_blockwise_message - (send block1) failed to allocate ack message!");
+                        handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
+                        src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
+                        handle->sn_coap_protocol_free(original_payload_ptr);
+                        original_payload_ptr = 0;
+                        handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
+                        src_coap_blockwise_ack_msg_ptr = 0;
+                        stored_blockwise_msg_temp_ptr->coap_msg_ptr = NULL;
+                        sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
+                        return NULL;
+                    }
+                    src_coap_blockwise_ack_msg_ptr->msg_id = message_id++;
+                    if (message_id == 0) {
+                        message_id = 1;
+                    }
+
+                    sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size);
+
+                    handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param);
+
+#if ENABLE_RESENDINGS
+                    uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0);
+                    if (src_coap_blockwise_ack_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE) {
+                        sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr,
+                                dst_packed_data_needed_mem,
+                                dst_ack_packet_data_ptr,
+                                resend_time, param);
+                    }
+#endif
+
+                    handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
+                    dst_ack_packet_data_ptr = 0;
+
+                    stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len = original_payload_len;
+                    stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr = original_payload_ptr;
+
+                    received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_ACK;
+
+                    // Remove original message from the list when last block has been sent.
+                    if (!((src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1) & 0x08)) {
+                        sn_coap_protocol_remove_sent_blockwise_message(handle, stored_blockwise_msg_temp_ptr->coap_msg_ptr->msg_id);
+                    }
+                }
+            } else {
+                // XXX what was this trying to free?
+                received_coap_msg_ptr->coap_status = COAP_STATUS_OK;
+
+            }
+        }
+
+        // Blocked request receiving
+        else {
+            if (received_coap_msg_ptr->payload_len > handle->sn_coap_block_data_size) {
+                received_coap_msg_ptr->payload_len = handle->sn_coap_block_data_size;
+            }
+
+            // Check that incoming block number is in order.
+            uint32_t block_number = received_coap_msg_ptr->options_list_ptr->block1 >> 4;
+            bool blocks_in_order = true;
+
+            if (block_number > 0 &&
+                !sn_coap_protocol_linked_list_blockwise_payload_compare_block_number(handle,
+                                                                                     src_addr_ptr,
+                                                                                     received_coap_msg_ptr->token_ptr,
+                                                                                     received_coap_msg_ptr->token_len,
+                                                                                     block_number)) {
+                blocks_in_order = false;
+            }
+
+            sn_coap_protocol_linked_list_blockwise_payload_store(handle,
+                                                                 src_addr_ptr,
+                                                                 received_coap_msg_ptr->payload_len,
+                                                                 received_coap_msg_ptr->payload_ptr,
+                                                                 received_coap_msg_ptr->token_ptr,
+                                                                 received_coap_msg_ptr->token_len,
+                                                                 block_number);
+
+            /* If not last block (more value is set) */
+            /* Block option length can be 1-3 bytes. First 4-20 bits are for block number. Last 4 bits are ALWAYS more bit + block size. */
+            if (received_coap_msg_ptr->options_list_ptr->block1 & 0x08) {
+                src_coap_blockwise_ack_msg_ptr = sn_coap_parser_alloc_message(handle);
+                if (src_coap_blockwise_ack_msg_ptr == NULL) {
+                    tr_error("sn_coap_handle_blockwise_message - (recv block1) failed to allocate ack message!");
+                    sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
+                    return NULL;
+                }
+
+                if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) {
+                   tr_error("sn_coap_handle_blockwise_message - (recv block1) failed to allocate options!");
+                    handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
+                    src_coap_blockwise_ack_msg_ptr = 0;
+                    sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
+                    return NULL;
+                }
+
+                if (!blocks_in_order) {
+                    tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE!");
+                    src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE;
+                } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_GET) {
+                    src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
+                } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_POST) {
+                    src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTINUE;
+                } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_PUT) {
+                    src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTINUE;
+                } else if (received_coap_msg_ptr->msg_code == COAP_MSG_CODE_REQUEST_DELETE) {
+                    src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_DELETED;
+                }
+
+                // Response with COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE if the payload size is more than we can handle
+                if (received_coap_msg_ptr->options_list_ptr->size1 > SN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE) {
+                    // Include maximum size that stack can handle into response
+                    tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE!");
+                    src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
+                }
+                else {
+                    src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = received_coap_msg_ptr->options_list_ptr->block1;
+                    src_coap_blockwise_ack_msg_ptr->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
+
+                    /* Check block size */
+                    block_temp = (src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 & 0x07);
+                    uint16_t block_size = 1u << (block_temp + 4);
+                    if (block_size >  handle->sn_coap_block_data_size) {
+                         // Include maximum size that stack can handle into response
+                         tr_error("sn_coap_handle_blockwise_message - (recv block1) COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE!");
+                         src_coap_blockwise_ack_msg_ptr->msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
+                         src_coap_blockwise_ack_msg_ptr->options_list_ptr->size1 = handle->sn_coap_block_data_size;
+                         sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
+                    }
+
+                    if (block_temp > sn_coap_convert_block_size(handle->sn_coap_block_data_size)) {
+                        src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 &= 0xFFFFF8;
+                        src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 |= sn_coap_convert_block_size(handle->sn_coap_block_data_size);
+                    }
+                }
+
+                src_coap_blockwise_ack_msg_ptr->msg_id = received_coap_msg_ptr->msg_id;
+
+                // Copy token to response
+                src_coap_blockwise_ack_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(received_coap_msg_ptr->token_len);
+                if (src_coap_blockwise_ack_msg_ptr->token_ptr) {
+                    memcpy(src_coap_blockwise_ack_msg_ptr->token_ptr, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
+                    src_coap_blockwise_ack_msg_ptr->token_len = received_coap_msg_ptr->token_len;
+                }
+
+                dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size);
+
+                dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem);
+                if (!dst_ack_packet_data_ptr) {
+                    tr_error("sn_coap_handle_blockwise_message - (recv block1) message allocation failed!");
+                    sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
+                    handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->options_list_ptr);
+                    src_coap_blockwise_ack_msg_ptr->options_list_ptr = 0;
+                    handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
+                    src_coap_blockwise_ack_msg_ptr = 0;
+                    return NULL;
+                }
+
+                sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size);
+                handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param);
+
+                sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
+                handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
+                dst_ack_packet_data_ptr = 0;
+
+                received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING;
+
+            } else {
+                /* * * This is the last block when whole Blockwise payload from received * * */
+                /* * * blockwise messages is gathered and returned to User               * * */
+
+                /* Store last Blockwise payload to Linked list */
+                uint16_t payload_len            = 0;
+                uint8_t *payload_ptr            = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
+                uint32_t whole_payload_len      = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
+                uint8_t *temp_whole_payload_ptr = NULL;
+
+                temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len);
+                if (temp_whole_payload_ptr == NULL || whole_payload_len > UINT16_MAX) {
+                    tr_error("sn_coap_handle_blockwise_message - (recv block1) failed to allocate all blocks!");
+                    sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
+                    handle->sn_coap_protocol_free(temp_whole_payload_ptr);
+                    return 0;
+                }
+
+                // In block message case, payload_ptr freeing must be done in application level
+                received_coap_msg_ptr->payload_ptr = temp_whole_payload_ptr;
+                received_coap_msg_ptr->payload_len = whole_payload_len;
+
+                /* Copy stored Blockwise payloads to returned whole Blockwise payload pointer */
+                while (payload_ptr != NULL) {
+                    memcpy(temp_whole_payload_ptr, payload_ptr, payload_len);
+                    temp_whole_payload_ptr += payload_len;
+                    sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
+                    payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
+                }
+                received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED;
+            }
+        }
+    }
+
+
+    /* Block2 Option in a response (e.g., a 2.05 response for GET) */
+    /* Message ID must be same than in received message */
+    else {
+        //This is response to request we made
+        if (received_coap_msg_ptr->msg_code > COAP_MSG_CODE_REQUEST_DELETE) {
+            if (handle->sn_coap_internal_block2_resp_handling) {
+                uint32_t block_number = 0;
+
+                /* Store blockwise payload to Linked list */
+                //todo: add block number to stored values - just to make sure all packets are in order
+                sn_coap_protocol_linked_list_blockwise_payload_store(handle,
+                                                                     src_addr_ptr,
+                                                                     received_coap_msg_ptr->payload_len,
+                                                                     received_coap_msg_ptr->payload_ptr,
+                                                                     received_coap_msg_ptr->token_ptr,
+                                                                     received_coap_msg_ptr->token_len,
+                                                                     received_coap_msg_ptr->options_list_ptr->block2 >> 4);
+                /* If not last block (more value is set) */
+                if (received_coap_msg_ptr->options_list_ptr->block2 & 0x08) {
+                    coap_blockwise_msg_s *previous_blockwise_msg_ptr = NULL;
+                    //build and send ack
+                    received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING;
+
+                    ns_list_foreach(coap_blockwise_msg_s, msg, &handle->linked_list_blockwise_sent_msgs) {
+                        if (received_coap_msg_ptr->msg_id == msg->coap_msg_ptr->msg_id) {
+                            previous_blockwise_msg_ptr = msg;
+                            break;
+                        }
+                    }
+
+                    if (!previous_blockwise_msg_ptr || !previous_blockwise_msg_ptr->coap_msg_ptr) {
+                        tr_error("sn_coap_handle_blockwise_message - (send block2) previous message null!");
+                        sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
+                        return 0;
+                    }
+
+                    src_coap_blockwise_ack_msg_ptr = sn_coap_parser_alloc_message(handle);
+                    if (src_coap_blockwise_ack_msg_ptr == NULL) {
+                        tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate message!");
+                        return 0;
+                    }
+
+                    /* * * Then build CoAP Acknowledgement message * * */
+
+                    if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) {
+                        tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate options!");
+                        handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr);
+                        src_coap_blockwise_ack_msg_ptr = 0;
+                        sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
+                        return NULL;
+                    }
+
+                    src_coap_blockwise_ack_msg_ptr->msg_id = message_id++;
+                    if (message_id == 0) {
+                        message_id = 1;
+                    }
+
+                    /* Update block option */
+                    block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07;
+
+                    block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4;
+                    block_number ++;
+
+                    src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = (block_number << 4) | block_temp;
+
+
+                    /* Set BLOCK2 (subsequent) GET msg code and copy uri path from previous msg*/
+                    src_coap_blockwise_ack_msg_ptr->msg_code = previous_blockwise_msg_ptr->coap_msg_ptr->msg_code;
+                    if (previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_ptr) {
+                        src_coap_blockwise_ack_msg_ptr->uri_path_len = previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len;
+                        src_coap_blockwise_ack_msg_ptr->uri_path_ptr = handle->sn_coap_protocol_malloc(previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len);
+                        if (!src_coap_blockwise_ack_msg_ptr->uri_path_ptr) {
+                            sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
+                            tr_error("sn_coap_handle_blockwise_message - failed to allocate for uri path ptr!");
+                            return NULL;
+                        }
+                        memcpy(src_coap_blockwise_ack_msg_ptr->uri_path_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->uri_path_len);
+                    }
+                    if (previous_blockwise_msg_ptr->coap_msg_ptr->token_ptr) {
+                        src_coap_blockwise_ack_msg_ptr->token_len = previous_blockwise_msg_ptr->coap_msg_ptr->token_len;
+                        src_coap_blockwise_ack_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(previous_blockwise_msg_ptr->coap_msg_ptr->token_len);
+                        if (!src_coap_blockwise_ack_msg_ptr->token_ptr) {
+                            sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
+                            tr_error("sn_coap_handle_blockwise_message - failed to allocate for token ptr!");
+                            return NULL;
+                        }
+                        memcpy(src_coap_blockwise_ack_msg_ptr->token_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->token_ptr, previous_blockwise_msg_ptr->coap_msg_ptr->token_len);
+                    }
+
+                    ns_list_remove(&handle->linked_list_blockwise_sent_msgs, previous_blockwise_msg_ptr);
+                    if (previous_blockwise_msg_ptr->coap_msg_ptr) {
+                        if (previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr) {
+                            handle->sn_coap_protocol_free(previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr);
+                            previous_blockwise_msg_ptr->coap_msg_ptr->payload_ptr = 0;
+                        }
+                        sn_coap_parser_release_allocated_coap_msg_mem(handle, previous_blockwise_msg_ptr->coap_msg_ptr);
+                        previous_blockwise_msg_ptr->coap_msg_ptr = 0;
+                    }
+                    handle->sn_coap_protocol_free(previous_blockwise_msg_ptr);
+                    previous_blockwise_msg_ptr = 0;
+
+                    /* Then get needed memory count for Packet data */
+                    dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr ,handle->sn_coap_block_data_size);
+
+                    /* Then allocate memory for Packet data */
+                    dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem);
+
+                    if (dst_ack_packet_data_ptr == NULL) {
+                        tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate packet!");
+                        sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
+                        sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
+                        return NULL;
+                    }
+                    memset(dst_ack_packet_data_ptr, 0, dst_packed_data_needed_mem);
+
+                    /* * * Then build Acknowledgement message to Packed data * * */
+                    if ((sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size)) < 0) {
+                        tr_error("sn_coap_handle_blockwise_message - (send block2) builder failed!");
+                        handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
+                        dst_ack_packet_data_ptr = 0;
+                        sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
+                        sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
+                        return NULL;
+                    }
+
+                    /* * * Save to linked list * * */
+                    coap_blockwise_msg_s *stored_blockwise_msg_ptr;
+
+                    stored_blockwise_msg_ptr = handle->sn_coap_protocol_malloc(sizeof(coap_blockwise_msg_s));
+                    if (!stored_blockwise_msg_ptr) {
+                        tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate blockwise message!");
+                        handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
+                        dst_ack_packet_data_ptr = 0;
+                        sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
+                        sn_coap_parser_release_allocated_coap_msg_mem(handle, received_coap_msg_ptr);
+                        return 0;
+                    }
+                    memset(stored_blockwise_msg_ptr, 0, sizeof(coap_blockwise_msg_s));
+
+                    stored_blockwise_msg_ptr->timestamp = handle->system_time;
+
+                    stored_blockwise_msg_ptr->coap_msg_ptr = src_coap_blockwise_ack_msg_ptr;
+                    stored_blockwise_msg_ptr->coap = handle;
+                    stored_blockwise_msg_ptr->param = param;
+                    stored_blockwise_msg_ptr->msg_id = stored_blockwise_msg_ptr->coap_msg_ptr->msg_id;
+                    ns_list_add_to_end(&handle->linked_list_blockwise_sent_msgs, stored_blockwise_msg_ptr);
+
+                    /* * * Then release memory of CoAP Acknowledgement message * * */
+                    handle->sn_coap_tx_callback(dst_ack_packet_data_ptr,
+                                                dst_packed_data_needed_mem, src_addr_ptr, param);
+
+#if ENABLE_RESENDINGS
+                    uint32_t resend_time = sn_coap_calculate_new_resend_time(handle->system_time, handle->sn_coap_resending_intervall, 0);
+                    sn_coap_protocol_linked_list_send_msg_store(handle, src_addr_ptr,
+                            dst_packed_data_needed_mem,
+                            dst_ack_packet_data_ptr,
+                            resend_time, param);
+#endif
+                    handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
+                    dst_ack_packet_data_ptr = 0;
+                }
+
+                //Last block received
+                else {
+                    /* * * This is the last block when whole Blockwise payload from received * * */
+                    /* * * blockwise messages is gathered and returned to User               * * */
+
+                    /* Store last Blockwise payload to Linked list */
+                    uint16_t payload_len            = 0;
+                    uint8_t *payload_ptr            = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
+                    uint16_t whole_payload_len      = sn_coap_protocol_linked_list_blockwise_payloads_get_len(handle, src_addr_ptr, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
+                    uint8_t *temp_whole_payload_ptr = NULL;
+
+                    temp_whole_payload_ptr = handle->sn_coap_protocol_malloc(whole_payload_len);
+                    if (!temp_whole_payload_ptr) {
+                        tr_error("sn_coap_handle_blockwise_message - (send block2) failed to allocate whole payload!");
+                        return 0;
+                    }
+
+                    received_coap_msg_ptr->payload_ptr = temp_whole_payload_ptr;
+                    received_coap_msg_ptr->payload_len = whole_payload_len;
+
+                    /* Copy stored Blockwise payloads to returned whole Blockwise payload pointer */
+                    while (payload_ptr != NULL) {
+                        memcpy(temp_whole_payload_ptr, payload_ptr, payload_len);
+
+                        temp_whole_payload_ptr += payload_len;
+
+                        sn_coap_protocol_linked_list_blockwise_payload_remove_oldest(handle, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
+                        payload_ptr = sn_coap_protocol_linked_list_blockwise_payload_search(handle, src_addr_ptr, &payload_len, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
+                    }
+                    received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED;
+
+                    //todo: remove previous msg from list
+                }
+            }
+        }
+
+        //Now we send data to request
+        else {
+            //Get message by using block number
+            //NOTE: Getting the first from list might not be correct one
+            coap_blockwise_msg_s *stored_blockwise_msg_temp_ptr = sn_coap_stored_blockwise_msg_get(handle, received_coap_msg_ptr);
+            if (stored_blockwise_msg_temp_ptr) {
+                uint16_t block_size;
+                uint32_t block_number;
+
+                /* Resolve block parameters */
+                block_number = received_coap_msg_ptr->options_list_ptr->block2 >> 4;
+                block_temp = received_coap_msg_ptr->options_list_ptr->block2 & 0x07;
+                block_size = 1u << (block_temp + 4);
+                /* Build response message */
+                src_coap_blockwise_ack_msg_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr;
+
+                if (src_coap_blockwise_ack_msg_ptr->options_list_ptr) {
+                    src_coap_blockwise_ack_msg_ptr->options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE;
+                    src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = COAP_OPTION_BLOCK_NONE;
+                } else {
+                    if (sn_coap_parser_alloc_options(handle, src_coap_blockwise_ack_msg_ptr) == NULL) {
+                        tr_error("sn_coap_handle_blockwise_message - (recv block2) failed to allocate options!");
+                        return 0;
+                    }
+                }
+
+                src_coap_blockwise_ack_msg_ptr->msg_id = received_coap_msg_ptr->msg_id;
+
+                src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 = received_coap_msg_ptr->options_list_ptr->block2;
+
+                /* * Payload part * */
+
+                /* Check if last block */
+
+                original_payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len;
+                original_payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr;
+
+                if ((block_size * (block_number + 1)) >= stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len) {
+                    src_coap_blockwise_ack_msg_ptr->payload_len = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len - (block_size * block_number);
+                    src_coap_blockwise_ack_msg_ptr->payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr + (block_size * block_number);
+                }
+                /* Not last block */
+                else {
+                    /* set more - bit */
+                    src_coap_blockwise_ack_msg_ptr->options_list_ptr->block2 |= 0x08;
+                    src_coap_blockwise_ack_msg_ptr->payload_len = block_size;
+                    src_coap_blockwise_ack_msg_ptr->payload_ptr = stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr + (block_size * block_number);
+                }
+
+                /* Update token to match one which is in GET request.
+                 * This is needed only in case of notification message.
+                */
+                if (src_coap_blockwise_ack_msg_ptr->options_list_ptr &&
+                    src_coap_blockwise_ack_msg_ptr->options_list_ptr->observe != COAP_OBSERVE_NONE) {
+                    if (received_coap_msg_ptr->token_len && src_coap_blockwise_ack_msg_ptr->token_ptr) {
+                        handle->sn_coap_protocol_free(src_coap_blockwise_ack_msg_ptr->token_ptr);
+                        src_coap_blockwise_ack_msg_ptr->token_ptr = handle->sn_coap_protocol_malloc(received_coap_msg_ptr->token_len);
+                        if (src_coap_blockwise_ack_msg_ptr->token_ptr) {
+                            memcpy(src_coap_blockwise_ack_msg_ptr->token_ptr, received_coap_msg_ptr->token_ptr, received_coap_msg_ptr->token_len);
+                            src_coap_blockwise_ack_msg_ptr->token_len = received_coap_msg_ptr->token_len;
+                        }
+                    }
+                }
+
+                /* Build and send block message */
+                dst_packed_data_needed_mem = sn_coap_builder_calc_needed_packet_data_size_2(src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size);
+
+                dst_ack_packet_data_ptr = handle->sn_coap_protocol_malloc(dst_packed_data_needed_mem);
+                if (!dst_ack_packet_data_ptr) {
+                    tr_error("sn_coap_handle_blockwise_message - (recv block2) failed to allocate packet!");
+                    if(original_payload_ptr){
+                        handle->sn_coap_protocol_free(original_payload_ptr);
+                        original_payload_ptr = NULL;
+                    }
+                    sn_coap_parser_release_allocated_coap_msg_mem(handle, src_coap_blockwise_ack_msg_ptr);
+                    stored_blockwise_msg_temp_ptr->coap_msg_ptr = NULL;
+                    return NULL;
+                }
+
+                sn_coap_builder_2(dst_ack_packet_data_ptr, src_coap_blockwise_ack_msg_ptr, handle->sn_coap_block_data_size);
+                handle->sn_coap_tx_callback(dst_ack_packet_data_ptr, dst_packed_data_needed_mem, src_addr_ptr, param);
+
+                handle->sn_coap_protocol_free(dst_ack_packet_data_ptr);
+                dst_ack_packet_data_ptr = 0;
+
+                stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len = original_payload_len;
+                stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_ptr = original_payload_ptr;
+
+                if ((block_size * (block_number + 1)) >= stored_blockwise_msg_temp_ptr->coap_msg_ptr->payload_len) {
+
+                    if (handle->sn_coap_rx_callback) {
+                        stored_blockwise_msg_temp_ptr->coap_msg_ptr->coap_status = COAP_STATUS_BUILDER_BLOCK_SENDING_DONE;
+                        stored_blockwise_msg_temp_ptr->coap_msg_ptr->msg_id = stored_blockwise_msg_temp_ptr->msg_id;
+                        handle->sn_coap_rx_callback(stored_blockwise_msg_temp_ptr->coap_msg_ptr, NULL, stored_blockwise_msg_temp_ptr->param);
+                    }
+
+                    sn_coap_protocol_linked_list_blockwise_msg_remove(handle, stored_blockwise_msg_temp_ptr);
+                }
+
+                received_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_ACK;
+            }
+        }
+    }
+    return received_coap_msg_ptr;
+}
+
+int8_t sn_coap_convert_block_size(uint16_t block_size)
+{
+    if (block_size == 16) {
+        return 0;
+    } else if (block_size == 32) {
+        return 1;
+    } else if (block_size == 64) {
+        return 2;
+    } else if (block_size == 128) {
+        return 3;
+    } else if (block_size == 256) {
+        return 4;
+    } else if (block_size == 512) {
+        return 5;
+    } else if (block_size == 1024) {
+        return 6;
+    }
+
+    return 0;
+}
+
+static sn_coap_hdr_s *sn_coap_protocol_copy_header(struct coap_s *handle, sn_coap_hdr_s *source_header_ptr)
+{
+    sn_coap_hdr_s *destination_header_ptr;
+
+    destination_header_ptr = sn_coap_parser_alloc_message(handle);
+    if (!destination_header_ptr) {
+        tr_error("sn_coap_protocol_copy_header - failed to allocate message!");
+        return 0;
+    }
+
+    destination_header_ptr->coap_status = source_header_ptr->coap_status;
+    destination_header_ptr->msg_type = source_header_ptr->msg_type;
+    destination_header_ptr->msg_code = source_header_ptr->msg_code;
+    destination_header_ptr->msg_id = source_header_ptr->msg_id;
+
+    if (source_header_ptr->uri_path_ptr) {
+        destination_header_ptr->uri_path_len = source_header_ptr->uri_path_len;
+        destination_header_ptr->uri_path_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->uri_path_len);
+        if (!destination_header_ptr->uri_path_ptr) {
+            tr_error("sn_coap_protocol_copy_header - failed to allocate uri path!");
+            sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
+            return 0;
+        }
+        memcpy(destination_header_ptr->uri_path_ptr, source_header_ptr->uri_path_ptr, source_header_ptr->uri_path_len);
+    }
+
+    if (source_header_ptr->token_ptr) {
+        destination_header_ptr->token_len = source_header_ptr->token_len;
+        destination_header_ptr->token_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->token_len);
+        if (!destination_header_ptr->token_ptr) {
+            sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
+            tr_error("sn_coap_protocol_copy_header - failed to allocate token!");
+            return 0;
+        }
+        memcpy(destination_header_ptr->token_ptr, source_header_ptr->token_ptr, source_header_ptr->token_len);
+    }
+
+    destination_header_ptr->content_format = source_header_ptr->content_format;
+
+    /* Options list */
+    if (source_header_ptr->options_list_ptr) {
+        if (sn_coap_parser_alloc_options(handle, destination_header_ptr) == NULL) {
+            sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
+            tr_error("sn_coap_protocol_copy_header - failed to allocate options!");
+            return 0;
+        }
+
+        destination_header_ptr->options_list_ptr->max_age = source_header_ptr->options_list_ptr->max_age;
+
+        if (source_header_ptr->options_list_ptr->proxy_uri_ptr) {
+            destination_header_ptr->options_list_ptr->proxy_uri_len = source_header_ptr->options_list_ptr->proxy_uri_len;
+            destination_header_ptr->options_list_ptr->proxy_uri_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->proxy_uri_len);
+            if (!destination_header_ptr->options_list_ptr->proxy_uri_ptr) {
+                sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
+                tr_error("sn_coap_protocol_copy_header - failed to allocate proxy uri!");
+                return 0;
+            }
+            memcpy(destination_header_ptr->options_list_ptr->proxy_uri_ptr, source_header_ptr->options_list_ptr->proxy_uri_ptr, source_header_ptr->options_list_ptr->proxy_uri_len);
+        }
+
+        if (source_header_ptr->options_list_ptr->etag_ptr) {
+            destination_header_ptr->options_list_ptr->etag_len = source_header_ptr->options_list_ptr->etag_len;
+            destination_header_ptr->options_list_ptr->etag_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->etag_len);
+            if (!destination_header_ptr->options_list_ptr->etag_ptr) {
+                sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
+                tr_error("sn_coap_protocol_copy_header - failed to allocate etag!");
+                return 0;
+            }
+            memcpy(destination_header_ptr->options_list_ptr->etag_ptr, source_header_ptr->options_list_ptr->etag_ptr, source_header_ptr->options_list_ptr->etag_len);
+        }
+
+        if (source_header_ptr->options_list_ptr->uri_host_ptr) {
+            destination_header_ptr->options_list_ptr->uri_host_len = source_header_ptr->options_list_ptr->uri_host_len;
+            destination_header_ptr->options_list_ptr->uri_host_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->uri_host_len);
+            if (!destination_header_ptr->options_list_ptr->uri_host_ptr) {
+                sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
+                tr_error("sn_coap_protocol_copy_header - failed to allocate uri host!");
+                return 0;
+            }
+            memcpy(destination_header_ptr->options_list_ptr->uri_host_ptr, source_header_ptr->options_list_ptr->uri_host_ptr, source_header_ptr->options_list_ptr->uri_host_len);
+        }
+
+        if (source_header_ptr->options_list_ptr->location_path_ptr) {
+            destination_header_ptr->options_list_ptr->location_path_len = source_header_ptr->options_list_ptr->location_path_len;
+            destination_header_ptr->options_list_ptr->location_path_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->location_path_len);
+            if (!destination_header_ptr->options_list_ptr->location_path_ptr) {
+                tr_error("sn_coap_protocol_copy_header - failed to allocate location path!");
+                sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
+                return 0;
+            }
+            memcpy(destination_header_ptr->options_list_ptr->location_path_ptr, source_header_ptr->options_list_ptr->location_path_ptr, source_header_ptr->options_list_ptr->location_path_len);
+        }
+
+        destination_header_ptr->options_list_ptr->uri_port = source_header_ptr->options_list_ptr->uri_port;
+
+        if (source_header_ptr->options_list_ptr->location_query_ptr) {
+            destination_header_ptr->options_list_ptr->location_query_len = source_header_ptr->options_list_ptr->location_query_len;
+            destination_header_ptr->options_list_ptr->location_query_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->location_query_len);
+            if (!destination_header_ptr->options_list_ptr->location_query_ptr) {
+                sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
+                tr_error("sn_coap_protocol_copy_header - failed to allocate location query!");
+                return 0;
+            }
+            memcpy(destination_header_ptr->options_list_ptr->location_query_ptr, source_header_ptr->options_list_ptr->location_query_ptr, source_header_ptr->options_list_ptr->location_query_len);
+        }
+
+        destination_header_ptr->options_list_ptr->observe = source_header_ptr->options_list_ptr->observe;
+        destination_header_ptr->options_list_ptr->accept = source_header_ptr->options_list_ptr->accept;
+
+        if (source_header_ptr->options_list_ptr->uri_query_ptr) {
+            destination_header_ptr->options_list_ptr->uri_query_len = source_header_ptr->options_list_ptr->uri_query_len;
+            destination_header_ptr->options_list_ptr->uri_query_ptr = handle->sn_coap_protocol_malloc(source_header_ptr->options_list_ptr->uri_query_len);
+            if (!destination_header_ptr->options_list_ptr->uri_query_ptr) {
+                sn_coap_parser_release_allocated_coap_msg_mem(handle, destination_header_ptr);
+                tr_error("sn_coap_protocol_copy_header - failed to allocate uri query!");
+                return 0;
+            }
+            memcpy(destination_header_ptr->options_list_ptr->uri_query_ptr, source_header_ptr->options_list_ptr->uri_query_ptr, source_header_ptr->options_list_ptr->uri_query_len);
+        }
+
+        destination_header_ptr->options_list_ptr->block1 = source_header_ptr->options_list_ptr->block1;
+        destination_header_ptr->options_list_ptr->block2 = source_header_ptr->options_list_ptr->block2;
+    }
+
+    return destination_header_ptr;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,4 @@
+build/*
+yotta_modules/*
+yotta_targets/*
+test/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/CMakeLists.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,18 @@
+INCLUDE(CMakeForceCompiler)
+
+cmake_minimum_required (VERSION 2.8)
+SET(CMAKE_SYSTEM_NAME Generic)
+
+project(mbedTrace)
+
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/mbed-trace/)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../nanostack-libservice/mbed-client-libservice/)
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../nanostack-libservice/)
+
+set (MBED_TRACE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/source/mbed_trace.c)
+
+
+CREATE_LIBRARY(mbedTrace "${MBED_TRACE_SRC}" "")
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,201 @@
+Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/mbed-trace/mbed_trace.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+ * \file mbed_trace.h
+ * Trace interface for MbedOS applications.
+ * This file provide simple but flexible way to handle software traces.
+ * Trace library are abstract layer, which use stdout (printf) by default,
+ * but outputs can be easily redirect to custom function, for example to
+ * store traces to memory or other interfaces.
+ *
+ *  usage example:
+ * \code(main.c:)
+ *      #include "mbed_trace.h"
+ *      #define TRACE_GROUP  "main"
+ *
+ *      int main(void){
+ *          mbed_trace_init();   // initialize trace library
+ *          tr_debug("this is debug msg");  //print debug message to stdout: "[DBG]
+ *          tr_info("this is info msg");
+ *          tr_warn("this is warning msg");
+ *          tr_err("this is error msg");
+ *          return 0;
+ *      }
+ * \endcode
+ * Activate with compiler flag: YOTTA_CFG_MBED_TRACE
+ * Configure trace line buffer size with compiler flag: YOTTA_CFG_MBED_TRACE_LINE_LENGTH. Default length: 1024.
+ * Limit the size of flash by setting MBED_TRACE_MAX_LEVEL value. Default is TRACE_LEVEL_DEBUG (all included)
+ *
+ */
+#ifndef MBED_TRACE_H_
+#define MBED_TRACE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef YOTTA_CFG
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.h>
+#else
+#include "ns_types.h"
+#endif
+
+#include <stdarg.h>
+
+#ifndef YOTTA_CFG_MBED_TRACE
+#define YOTTA_CFG_MBED_TRACE 0
+#endif
+
+#ifndef YOTTA_CFG_MBED_TRACE_FEA_IPV6
+#define YOTTA_CFG_MBED_TRACE_FEA_IPV6 1
+#else
+#warning YOTTA_CFG_MBED_TRACE_FEA_IPV6 is deprecated and will be removed in the future! Use MBED_CONF_MBED_TRACE_FEA_IPV6 instead.
+#define MBED_CONF_MBED_TRACE_FEA_IPV6 YOTTA_CFG_MBED_TRACE_FEA_IPV6
+#endif
+
+#ifndef MBED_CONF_MBED_TRACE_ENABLE
+#define MBED_CONF_MBED_TRACE_ENABLE 0
+#endif
+
+#ifndef MBED_CONF_MBED_TRACE_FEA_IPV6
+#define MBED_CONF_MBED_TRACE_FEA_IPV6 1
+#endif
+
+/** 3 upper bits are trace modes related,
+    and 5 lower bits are trace level configuration */
+
+/** Config mask */
+#define TRACE_MASK_CONFIG         0xE0
+/** Trace level mask */
+#define TRACE_MASK_LEVEL          0x1F
+
+/** plain trace data instead of "headers" */
+#define TRACE_MODE_PLAIN          0x80
+/** color mode */
+#define TRACE_MODE_COLOR          0x40
+/** Use print CR before trace line */
+#define TRACE_CARRIAGE_RETURN     0x20
+
+/** used to activate all trace levels */
+#define TRACE_ACTIVE_LEVEL_ALL    0x1F
+/** print all traces same as above */
+#define TRACE_ACTIVE_LEVEL_DEBUG  0x1f
+/** print info,warn and error traces */
+#define TRACE_ACTIVE_LEVEL_INFO   0x0f
+/** print warn and error traces */
+#define TRACE_ACTIVE_LEVEL_WARN   0x07
+/** print only error trace */
+#define TRACE_ACTIVE_LEVEL_ERROR  0x03
+/** print only cmd line data */
+#define TRACE_ACTIVE_LEVEL_CMD    0x01
+/** trace nothing  */
+#define TRACE_ACTIVE_LEVEL_NONE   0x00
+
+/** this print is some deep information for debug purpose */
+#define TRACE_LEVEL_DEBUG         0x10
+/** Info print, for general purpose prints */
+#define TRACE_LEVEL_INFO          0x08
+/** warning prints, which shouldn't causes any huge problems */
+#define TRACE_LEVEL_WARN          0x04
+/** Error prints, which causes probably problems, e.g. out of mem. */
+#define TRACE_LEVEL_ERROR         0x02
+/** special level for cmdline. Behaviours like "plain mode" */
+#define TRACE_LEVEL_CMD           0x01
+
+#ifndef MBED_TRACE_MAX_LEVEL
+#define MBED_TRACE_MAX_LEVEL TRACE_LEVEL_DEBUG
+#endif
+
+//usage macros:
+#if MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_DEBUG
+#define tr_debug(...)           mbed_tracef(TRACE_LEVEL_DEBUG,   TRACE_GROUP, __VA_ARGS__)   //!< Print debug message
+#else
+#define tr_debug(...)
+#endif
+
+#if MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_INFO
+#define tr_info(...)            mbed_tracef(TRACE_LEVEL_INFO,    TRACE_GROUP, __VA_ARGS__)   //!< Print info message
+#else
+#define tr_info(...)
+#endif
+
+#if MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_WARN
+#define tr_warning(...)         mbed_tracef(TRACE_LEVEL_WARN,    TRACE_GROUP, __VA_ARGS__)   //!< Print warning message
+#define tr_warn(...)            mbed_tracef(TRACE_LEVEL_WARN,    TRACE_GROUP, __VA_ARGS__)   //!< Alternative warning message
+#else
+#define tr_warning(...)
+#define tr_warn(...)
+#endif
+
+#if MBED_TRACE_MAX_LEVEL >= TRACE_LEVEL_ERROR
+#define tr_error(...)           mbed_tracef(TRACE_LEVEL_ERROR,   TRACE_GROUP, __VA_ARGS__)   //!< Print Error Message
+#define tr_err(...)             mbed_tracef(TRACE_LEVEL_ERROR,   TRACE_GROUP, __VA_ARGS__)   //!< Alternative error message
+#else
+#define tr_error(...)
+#define tr_err(...)
+#endif
+
+#define tr_cmdline(...)         mbed_tracef(TRACE_LEVEL_CMD,     TRACE_GROUP, __VA_ARGS__)   //!< Special print for cmdline. See more from TRACE_LEVEL_CMD -level
+
+//aliases for the most commonly used functions and the helper functions
+#define tracef(dlevel, grp, ...)                mbed_tracef(dlevel, grp, __VA_ARGS__)       //!< Alias for mbed_tracef()
+#define vtracef(dlevel, grp, fmt, ap)           mbed_vtracef(dlevel, grp, fmt, ap)          //!< Alias for mbed_vtracef()
+#define tr_array(buf, len)                      mbed_trace_array(buf, len)                  //!< Alias for mbed_trace_array()
+#define tr_ipv6(addr_ptr)                       mbed_trace_ipv6(addr_ptr)                   //!< Alias for mbed_trace_ipv6()
+#define tr_ipv6_prefix(prefix, prefix_len)      mbed_trace_ipv6_prefix(prefix, prefix_len)  //!< Alias for mbed_trace_ipv6_prefix()
+#define trace_array(buf, len)                   mbed_trace_array(buf, len)                  //!< Alias for mbed_trace_array()
+#define trace_ipv6(addr_ptr)                    mbed_trace_ipv6(addr_ptr)                   //!< Alias for mbed_trace_ipv6()
+#define trace_ipv6_prefix(prefix, prefix_len)   mbed_trace_ipv6_prefix(prefix, prefix_len)  //!< Alias for mbed_trace_ipv6_prefix()
+
+
+/**
+ * Allow specification of default TRACE_GROUP to be used if not specified by application
+ */
+
+#ifndef TRACE_GROUP
+#ifdef YOTTA_CFG_MBED_TRACE_GROUP
+#define TRACE_GROUP_STR_HELPER(x) #x
+#define TRACE_GROUP_STR(x) TRACE_GROUP_STR_HELPER(x)
+#define TRACE_GROUP TRACE_GROUP_STR(YOTTA_CFG_MBED_TRACE_GROUP)
+#endif
+#endif
+
+/**
+ * Initialize trace functionality
+ * @return 0 when all success, otherwise non zero
+ */
+int mbed_trace_init( void );
+/**
+ * Free trace memory
+ */
+void mbed_trace_free( void );
+/**
+ * Resize buffers (line / tmp ) sizes
+ * @param lineLength    new maximum length for trace line (0 = do no resize)
+ * @param tmpLength     new maximum length for trace tmp buffer (used for trace_array, etc) (0 = do no resize)
+ */
+void mbed_trace_buffer_sizes(int lineLength, int tmpLength);
+/**
+ *  Set trace configurations
+ *  Possible parameters:
+ *
+ *   TRACE_MODE_COLOR
+ *   TRACE_MODE_PLAIN (this exclude color mode)
+ *   TRACE_CARRIAGE_RETURN (print CR before trace line)
+ *
+ *   TRACE_ACTIVE_LEVEL_ALL - to activate all trace levels
+ *   or TRACE_ACTIVE_LEVEL_DEBUG (alternative)
+ *   TRACE_ACTIVE_LEVEL_INFO
+ *   TRACE_ACTIVE_LEVEL_WARN
+ *   TRACE_ACTIVE_LEVEL_ERROR
+ *   TRACE_ACTIVE_LEVEL_CMD
+ *   TRACE_LEVEL_NONE - to deactivate all traces
+ *
+ * @param config  Byte size Bit-mask. Bits are descripted above.
+ * usage e.g.
+ * @code
+ *  mbed_trace_config_set( TRACE_ACTIVE_LEVEL_ALL|TRACE_MODE_COLOR );
+ * @endcode
+ */
+void mbed_trace_config_set(uint8_t config);
+/** get trace configurations
+ * @return trace configuration byte
+ */
+uint8_t mbed_trace_config_get(void);
+/**
+ * Set trace prefix function
+ * pref_f -function return string with null terminated
+ * Can be used for e.g. time string
+ * e.g.
+ *   char* trace_time(){ return "rtc-time-in-string"; }
+ *   mbed_trace_prefix_function_set( &trace_time );
+ */
+void mbed_trace_prefix_function_set( char* (*pref_f)(size_t) );
+/**
+ * Set trace suffix function
+ * suffix -function return string with null terminated
+ * Can be used for e.g. time string
+ * e.g.
+ *   char* trace_suffix(){ return " END"; }
+ *   mbed_trace_suffix_function_set( &trace_suffix );
+ */
+void mbed_trace_suffix_function_set(char* (*suffix_f)(void) );
+/**
+ * Set trace print function
+ * By default, trace module print using printf() function,
+ * but with this you can write own print function,
+ * for e.g. to other IO device.
+ */
+void mbed_trace_print_function_set( void (*print_f)(const char*) );
+/**
+ * Set trace print function for tr_cmdline()
+ */
+void mbed_trace_cmdprint_function_set( void (*printf)(const char*) );
+/**
+ * Set trace mutex wait function
+ * By default, trace calls are not thread safe.
+ * If thread safety is required this can be used to set a callback function that will be called before each trace call.
+ * The specific implementation is up to the application developer, but the mutex must count so it can
+ * be acquired from a single thread repeatedly.
+ */
+void mbed_trace_mutex_wait_function_set(void (*mutex_wait_f)(void));
+/**
+ * Set trace mutex release function
+ * By default, trace calls are not thread safe.
+ * If thread safety is required this can be used to set a callback function that will be called before returning from
+ * each trace call. The specific implementation is up to the application developer, but the mutex must count so it can
+ * be acquired from a single thread repeatedly.
+ */
+void mbed_trace_mutex_release_function_set(void (*mutex_release_f)(void));
+/**
+ * When trace group contains text in filters,
+ * trace print will be ignored.
+ * e.g.:
+ *  mbed_trace_exclude_filters_set("mygr");
+ *  mbed_tracef(TRACE_ACTIVE_LEVEL_DEBUG, "ougr", "This is not printed");
+ */
+void mbed_trace_exclude_filters_set(char* filters);
+/** get trace exclude filters
+ */
+const char* mbed_trace_exclude_filters_get(void);
+/**
+ * When trace group contains text in filter,
+ * trace will be printed.
+ * e.g.:
+ *  set_trace_include_filters("mygr");
+ *  mbed_tracef(TRACE_ACTIVE_LEVEL_DEBUG, "mygr", "Hi There");
+ *  mbed_tracef(TRACE_ACTIVE_LEVEL_DEBUG, "grp2", "This is not printed");
+ */
+void mbed_trace_include_filters_set(char* filters);
+/** get trace include filters
+ */
+const char* mbed_trace_include_filters_get(void);
+/**
+ * General trace function
+ * This should be used every time when user want to print out something important thing
+ * Usage e.g.
+ *   mbed_tracef( TRACE_LEVEL_INFO, "mygr", "Hello world!");
+ *
+ * @param dlevel debug level
+ * @param grp    trace group
+ * @param fmt    trace format (like printf)
+ * @param ...    variable arguments related to fmt
+ */
+#if defined(__GNUC__) || defined(__CC_ARM)
+void mbed_tracef(uint8_t dlevel, const char* grp, const char *fmt, ...) __attribute__ ((__format__(__printf__, 3, 4)));
+#else
+void mbed_tracef(uint8_t dlevel, const char* grp, const char *fmt, ...);
+#endif
+/**
+ * General trace function
+ * This should be used every time when user want to print out something important thing
+ * and vprintf functionality is desired
+ * Usage e.g.
+ *   va_list ap;
+ *   va_start (ap, fmt);
+ *   mbed_vtracef( TRACE_LEVEL_INFO, "mygr", fmt, ap );
+ *   va_end (ap);
+ *
+ * @param dlevel debug level
+ * @param grp    trace group
+ * @param fmt    trace format (like vprintf)
+ * @param ap     variable arguments list (like vprintf)
+ */
+#if defined(__GNUC__) || defined(__CC_ARM)
+void mbed_vtracef(uint8_t dlevel, const char* grp, const char *fmt, va_list ap) __attribute__ ((__format__(__printf__, 3, 0)));
+#else
+void mbed_vtracef(uint8_t dlevel, const char* grp, const char *fmt, va_list ap);
+#endif
+
+
+/**
+ *  Get last trace from buffer
+ */
+const char* mbed_trace_last(void);
+#if MBED_CONF_MBED_TRACE_FEA_IPV6 == 1
+/**
+ * mbed_tracef helping function for convert ipv6
+ * table to human readable string.
+ * usage e.g.
+ * char ipv6[16] = {...}; // ! array length is 16 bytes !
+ * mbed_tracef(TRACE_LEVEL_INFO, "mygr", "ipv6 addr: %s", mbed_trace_ipv6(ipv6));
+ *
+ * @param add_ptr  IPv6 Address pointer
+ * @return temporary buffer where ipv6 is in string format
+ */
+char* mbed_trace_ipv6(const void *addr_ptr);
+/**
+ * mbed_tracef helping function for print ipv6 prefix
+ * usage e.g.
+ * char ipv6[16] = {...}; // ! array length is 16 bytes !
+ * mbed_tracef(TRACE_LEVEL_INFO, "mygr", "ipv6 addr: %s", mbed_trace_ipv6_prefix(ipv6, 4));
+ *
+ * @param prefix        IPv6 Address pointer
+ * @param prefix_len    prefix length
+ * @return temporary buffer where ipv6 is in string format
+ */
+char* mbed_trace_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len);
+#endif
+/**
+ * mbed_tracef helping function for convert hex-array to string.
+ * usage e.g.
+ *  char myarr[] = {0x10, 0x20};
+ *  mbed_tracef(TRACE_LEVEL_INFO, "mygr", "arr: %s", mbed_trace_array(myarr, 2));
+ *
+ * @param buf  hex array pointer
+ * @param len  buffer length
+ * @return temporary buffer where string copied
+ * if array as string not fit to temp buffer, this function write '*' as last character,
+ * which indicate that buffer is too small for array.
+ */
+char* mbed_trace_array(const uint8_t* buf, uint16_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBED_TRACE_H_ */
+
+/* These macros are outside the inclusion guard so they will be re-evaluated for every inclusion of the header.
+ * If tracing is disabled, the dummies will hide the real functions. The real functions can still be reached by
+ * surrounding the name of the function with brackets, e.g. "(mbed_tracef)(dlevel, grp, "like so");"
+ * */
+#if defined(FEA_TRACE_SUPPORT) || MBED_CONF_MBED_TRACE_ENABLE || YOTTA_CFG_MBED_TRACE || (defined(YOTTA_CFG) && !defined(NDEBUG))
+// Make sure FEA_TRACE_SUPPORT is always set whenever traces are enabled.
+#ifndef FEA_TRACE_SUPPORT
+#define FEA_TRACE_SUPPORT
+#endif
+// undefine dummies, revealing the real functions
+#undef MBED_TRACE_DUMMIES_DEFINED
+#undef mbed_trace_init
+#undef mbed_trace_free
+#undef mbed_trace_buffer_sizes
+#undef mbed_trace_config_set
+#undef mbed_trace_config_get
+#undef mbed_trace_prefix_function_set
+#undef mbed_trace_suffix_function_set
+#undef mbed_trace_print_function_set
+#undef mbed_trace_cmdprint_function_set
+#undef mbed_trace_mutex_wait_function_set
+#undef mbed_trace_mutex_release_function_set
+#undef mbed_trace_exclude_filters_set
+#undef mbed_trace_exclude_filters_get
+#undef mbed_trace_include_filters_set
+#undef mbed_trace_include_filters_get
+#undef mbed_tracef
+#undef mbed_vtracef
+#undef mbed_trace_last
+#undef mbed_trace_ipv6
+#undef mbed_trace_ipv6_prefix
+#undef mbed_trace_array
+
+#elif !defined(MBED_TRACE_DUMMIES_DEFINED)
+// define dummies, hiding the real functions
+#define MBED_TRACE_DUMMIES_DEFINED
+#define mbed_trace_init(...)                        ((int) 0)
+#define mbed_trace_free(...)                        ((void) 0)
+#define mbed_trace_buffer_sizes(...)                ((void) 0)
+#define mbed_trace_config_set(...)                  ((void) 0)
+#define mbed_trace_config_get(...)                  ((uint8_t) 0)
+#define mbed_trace_prefix_function_set(...)         ((void) 0)
+#define mbed_trace_suffix_function_set(...)         ((void) 0)
+#define mbed_trace_print_function_set(...)          ((void) 0)
+#define mbed_trace_cmdprint_function_set(...)       ((void) 0)
+#define mbed_trace_mutex_wait_function_set(...)     ((void) 0)
+#define mbed_trace_mutex_release_function_set(...)  ((void) 0)
+#define mbed_trace_exclude_filters_set(...)         ((void) 0)
+#define mbed_trace_exclude_filters_get(...)         ((const char *) 0)
+#define mbed_trace_include_filters_set(...)         ((void) 0)
+#define mbed_trace_include_filters_get(...)         ((const char *) 0)
+#define mbed_trace_last(...)                        ((const char *) 0)
+#define mbed_tracef(...)                            ((void) 0)
+#define mbed_vtracef(...)                           ((void) 0)
+/**
+ * These helper functions accumulate strings in a buffer that is only flushed by actual trace calls. Using these
+ * functions outside trace calls could cause the buffer to overflow.
+ */
+#define mbed_trace_ipv6(...)                dont_use_trace_helpers_outside_trace_calls
+#define mbed_trace_ipv6_prefix(...)         dont_use_trace_helpers_outside_trace_calls
+#define mbed_trace_array(...)               dont_use_trace_helpers_outside_trace_calls
+
+#endif /* FEA_TRACE_SUPPORT */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/mbed_lib.json	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,14 @@
+{
+    "name": "mbed-trace",
+    "config": {
+        "enable": {
+            "help": "Used to globally enable traces.",
+            "value": null
+        },
+        "fea-ipv6": {
+            "help": "Used to globally disable ipv6 tracing features.",
+            "value": null
+        }
+
+    }    
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/source/CMakeLists.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,12 @@
+if(DEFINED TARGET_LIKE_X86_LINUX_NATIVE)
+    add_library( mbed-trace
+        mbed_trace.c
+    )
+    add_definitions("-g -O0 -fprofile-arcs -ftest-coverage")
+    target_link_libraries(mbed-trace gcov nanostack-libservice)
+else()
+    add_library( mbed-trace
+        mbed_trace.c
+    )
+    target_link_libraries(mbed-trace nanostack-libservice)
+endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed-trace/source/mbed_trace.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#ifdef MBED_CONF_MBED_TRACE_ENABLE
+#undef MBED_CONF_MBED_TRACE_ENABLE
+#endif
+#define MBED_CONF_MBED_TRACE_ENABLE 1
+#ifndef MBED_CONF_MBED_TRACE_FEA_IPV6
+#define MBED_CONF_MBED_TRACE_FEA_IPV6 1
+#endif
+
+#include "mbed-trace/mbed_trace.h"
+#if MBED_CONF_MBED_TRACE_FEA_IPV6 == 1
+#include "mbed-client-libservice/ip6string.h"
+#include "mbed-client-libservice/common_functions.h"
+#endif
+
+#if defined(YOTTA_CFG_MBED_TRACE_MEM)
+#define MBED_TRACE_MEM_INCLUDE      YOTTA_CFG_MBED_TRACE_MEM_INCLUDE
+#define MBED_TRACE_MEM_ALLOC        YOTTA_CFG_MBED_TRACE_MEM_ALLOC
+#define MBED_TRACE_MEM_FREE         YOTTA_CFG_MBED_TRACE_MEM_FREE
+#else /* YOTTA_CFG_MEMLIB */
+// Default options
+#ifndef MBED_TRACE_MEM_INCLUDE
+#define MBED_TRACE_MEM_INCLUDE   <stdlib.h>
+#endif
+#include MBED_TRACE_MEM_INCLUDE
+#ifndef MBED_TRACE_MEM_ALLOC
+#define MBED_TRACE_MEM_ALLOC malloc
+#endif
+#ifndef MBED_TRACE_MEM_FREE
+#define MBED_TRACE_MEM_FREE  free
+#endif
+#endif /* YOTTA_CFG_MEMLIB */
+
+#define VT100_COLOR_ERROR "\x1b[31m"
+#define VT100_COLOR_WARN  "\x1b[33m"
+#define VT100_COLOR_INFO  "\x1b[39m"
+#define VT100_COLOR_DEBUG "\x1b[90m"
+
+/** default max trace line size in bytes */
+#ifdef MBED_TRACE_LINE_LENGTH
+#define DEFAULT_TRACE_LINE_LENGTH         MBED_TRACE_LINE_LENGTH
+#elif defined YOTTA_CFG_MBED_TRACE_LINE_LENGTH
+#warning YOTTA_CFG_MBED_TRACE_LINE_LENGTH is deprecated and will be removed in the future! Use MBED_TRACE_LINE_LENGTH instead.
+#define DEFAULT_TRACE_LINE_LENGTH         YOTTA_CFG_MBED_TRACE_LINE_LENGTH
+#else
+#define DEFAULT_TRACE_LINE_LENGTH         1024
+#endif
+
+/** default max temporary buffer size in bytes, used in
+    trace_ipv6, trace_ipv6_prefix and trace_array */
+#ifdef MBED_TRACE_TMP_LINE_LENGTH
+#define DEFAULT_TRACE_TMP_LINE_LEN        MBED_TRACE_TMP_LINE_LENGTH
+#elif defined YOTTA_CFG_MBED_TRACE_TMP_LINE_LEN
+#warning The YOTTA_CFG_MBED_TRACE_TMP_LINE_LEN flag is deprecated and will be removed in the future! Use MBED_TRACE_TMP_LINE_LENGTH instead.
+#define DEFAULT_TRACE_TMP_LINE_LEN        YOTTA_CFG_MBED_TRACE_TMP_LINE_LEN
+#elif defined YOTTA_CFG_MTRACE_TMP_LINE_LEN
+#warning The YOTTA_CFG_MTRACE_TMP_LINE_LEN flag is deprecated and will be removed in the future! Use MBED_TRACE_TMP_LINE_LENGTH instead.
+#define DEFAULT_TRACE_TMP_LINE_LEN        YOTTA_CFG_MTRACE_TMP_LINE_LEN
+#else
+#define DEFAULT_TRACE_TMP_LINE_LEN        128
+#endif
+
+/** default max filters (include/exclude) length in bytes */
+#ifdef MBED_TRACE_FILTER_LENGTH
+#define DEFAULT_TRACE_FILTER_LENGTH       MBED_TRACE_FILTER_LENGTH
+#else
+#define DEFAULT_TRACE_FILTER_LENGTH       24
+#endif
+
+/** default trace configuration bitmask */
+#ifdef MBED_TRACE_CONFIG
+#define DEFAULT_TRACE_CONFIG              MBED_TRACE_CONFIG
+#else
+#define DEFAULT_TRACE_CONFIG              TRACE_MODE_COLOR | TRACE_ACTIVE_LEVEL_ALL | TRACE_CARRIAGE_RETURN
+#endif
+
+/** default print function, just redirect str to printf */
+static void mbed_trace_realloc( char **buffer, int *length_ptr, int new_length);
+static void mbed_trace_default_print(const char *str);
+static void mbed_trace_reset_tmp(void);
+
+typedef struct trace_s {
+    /** trace configuration bits */
+    uint8_t trace_config;
+    /** exclude filters list, related group name */
+    char *filters_exclude;
+    /** include filters list, related group name */
+    char *filters_include;
+    /** Filters length */
+    int filters_length;
+    /** trace line */
+    char *line;
+    /** trace line length */
+    int line_length;
+    /** temporary data */
+    char *tmp_data;
+    /** temporary data array length */
+    int tmp_data_length;
+    /** temporary data pointer */
+    char *tmp_data_ptr;
+
+    /** prefix function, which can be used to put time to the trace line */
+    char *(*prefix_f)(size_t);
+    /** suffix function, which can be used to some string to the end of trace line */
+    char *(*suffix_f)(void);
+    /** print out function. Can be redirect to flash for example. */
+    void (*printf)(const char *);
+    /** print out function for TRACE_LEVEL_CMD */
+    void (*cmd_printf)(const char *);
+    /** mutex wait function which can be called to lock against a mutex. */
+    void (*mutex_wait_f)(void);
+    /** mutex release function which must be used to release the mutex locked by mutex_wait_f. */
+    void (*mutex_release_f)(void);
+    /** number of times the mutex has been locked */
+    int mutex_lock_count;
+} trace_t;
+
+static trace_t m_trace = {
+    .trace_config = DEFAULT_TRACE_CONFIG,
+    .filters_exclude = 0,
+    .filters_include = 0,
+    .filters_length = DEFAULT_TRACE_FILTER_LENGTH,
+    .line = 0,
+    .line_length = DEFAULT_TRACE_LINE_LENGTH,
+    .tmp_data = 0,
+    .tmp_data_length = DEFAULT_TRACE_TMP_LINE_LEN,
+    .prefix_f = 0,
+    .suffix_f = 0,
+    .printf  = mbed_trace_default_print,
+    .cmd_printf = 0,
+    .mutex_wait_f = 0,
+    .mutex_release_f = 0,
+    .mutex_lock_count = 0
+};
+
+int mbed_trace_init(void)
+{
+    if (m_trace.line == NULL) {
+        m_trace.line = MBED_TRACE_MEM_ALLOC(m_trace.line_length);
+    }
+
+    if (m_trace.tmp_data == NULL) {
+        m_trace.tmp_data = MBED_TRACE_MEM_ALLOC(m_trace.tmp_data_length);
+    }
+    m_trace.tmp_data_ptr = m_trace.tmp_data;
+
+    if (m_trace.filters_exclude == NULL) {
+        m_trace.filters_exclude = MBED_TRACE_MEM_ALLOC(m_trace.filters_length);
+    }
+    if (m_trace.filters_include == NULL) {
+        m_trace.filters_include = MBED_TRACE_MEM_ALLOC(m_trace.filters_length);
+    }
+
+    if (m_trace.line == NULL ||
+            m_trace.tmp_data == NULL ||
+            m_trace.filters_exclude == NULL  ||
+            m_trace.filters_include == NULL) {
+        //memory allocation fail
+        mbed_trace_free();
+        return -1;
+    }
+    memset(m_trace.tmp_data, 0, m_trace.tmp_data_length);
+    memset(m_trace.filters_exclude, 0, m_trace.filters_length);
+    memset(m_trace.filters_include, 0, m_trace.filters_length);
+    memset(m_trace.line, 0, m_trace.line_length);
+
+    return 0;
+}
+void mbed_trace_free(void)
+{
+    // release memory
+    MBED_TRACE_MEM_FREE(m_trace.line);
+    MBED_TRACE_MEM_FREE(m_trace.tmp_data);
+    MBED_TRACE_MEM_FREE(m_trace.filters_exclude);
+    MBED_TRACE_MEM_FREE(m_trace.filters_include);
+
+    // reset to default values
+    m_trace.trace_config = DEFAULT_TRACE_CONFIG;
+    m_trace.filters_exclude = 0;
+    m_trace.filters_include = 0;
+    m_trace.filters_length = DEFAULT_TRACE_FILTER_LENGTH;
+    m_trace.line = 0;
+    m_trace.line_length = DEFAULT_TRACE_LINE_LENGTH;
+    m_trace.tmp_data = 0;
+    m_trace.tmp_data_length = DEFAULT_TRACE_TMP_LINE_LEN;
+    m_trace.prefix_f = 0;
+    m_trace.suffix_f = 0;
+    m_trace.printf  = mbed_trace_default_print;
+    m_trace.cmd_printf = 0;
+    m_trace.mutex_wait_f = 0;
+    m_trace.mutex_release_f = 0;
+    m_trace.mutex_lock_count = 0;
+}
+static void mbed_trace_realloc( char **buffer, int *length_ptr, int new_length)
+{
+    MBED_TRACE_MEM_FREE(*buffer);
+    *buffer  = MBED_TRACE_MEM_ALLOC(new_length);
+    *length_ptr = new_length;
+}
+void mbed_trace_buffer_sizes(int lineLength, int tmpLength)
+{
+    if( lineLength > 0 ) {
+        mbed_trace_realloc( &(m_trace.line), &m_trace.line_length, lineLength );
+    }
+    if( tmpLength > 0 ) {
+        mbed_trace_realloc( &(m_trace.tmp_data), &m_trace.tmp_data_length, tmpLength);
+        mbed_trace_reset_tmp();
+    }
+}
+void mbed_trace_config_set(uint8_t config)
+{
+    m_trace.trace_config = config;
+}
+uint8_t mbed_trace_config_get(void)
+{
+    return m_trace.trace_config;
+}
+void mbed_trace_prefix_function_set(char *(*pref_f)(size_t))
+{
+    m_trace.prefix_f = pref_f;
+}
+void mbed_trace_suffix_function_set(char *(*suffix_f)(void))
+{
+    m_trace.suffix_f = suffix_f;
+}
+void mbed_trace_print_function_set(void (*printf)(const char *))
+{
+    m_trace.printf = printf;
+}
+void mbed_trace_cmdprint_function_set(void (*printf)(const char *))
+{
+    m_trace.cmd_printf = printf;
+}
+void mbed_trace_mutex_wait_function_set(void (*mutex_wait_f)(void))
+{
+    m_trace.mutex_wait_f = mutex_wait_f;
+}
+void mbed_trace_mutex_release_function_set(void (*mutex_release_f)(void))
+{
+    m_trace.mutex_release_f = mutex_release_f;
+}
+void mbed_trace_exclude_filters_set(char *filters)
+{
+    if (filters) {
+        (void)strncpy(m_trace.filters_exclude, filters, m_trace.filters_length);
+    } else {
+        m_trace.filters_exclude[0] = 0;
+    }
+}
+const char *mbed_trace_exclude_filters_get(void)
+{
+    return m_trace.filters_exclude;
+}
+const char *mbed_trace_include_filters_get(void)
+{
+    return m_trace.filters_include;
+}
+void mbed_trace_include_filters_set(char *filters)
+{
+    if (filters) {
+        (void)strncpy(m_trace.filters_include, filters, m_trace.filters_length);
+    } else {
+        m_trace.filters_include[0] = 0;
+    }
+}
+static int8_t mbed_trace_skip(int8_t dlevel, const char *grp)
+{
+    if (dlevel >= 0 && grp != 0) {
+        // filter debug prints only when dlevel is >0 and grp is given
+
+        /// @TODO this could be much better..
+        if (m_trace.filters_exclude[0] != '\0' &&
+                strstr(m_trace.filters_exclude, grp) != 0) {
+            //grp was in exclude list
+            return 1;
+        }
+        if (m_trace.filters_include[0] != '\0' &&
+                strstr(m_trace.filters_include, grp) == 0) {
+            //grp was in include list
+            return 1;
+        }
+    }
+    return 0;
+}
+static void mbed_trace_default_print(const char *str)
+{
+    puts(str);
+}
+void mbed_tracef(uint8_t dlevel, const char *grp, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    mbed_vtracef(dlevel, grp, fmt, ap);
+    va_end(ap);
+}
+void mbed_vtracef(uint8_t dlevel, const char* grp, const char *fmt, va_list ap)
+{
+    if ( m_trace.mutex_wait_f ) {
+        m_trace.mutex_wait_f();
+        m_trace.mutex_lock_count++;
+    }
+
+    if (NULL == m_trace.line) {
+        goto end;
+    }
+
+    m_trace.line[0] = 0; //by default trace is empty
+
+    if (mbed_trace_skip(dlevel, grp) || fmt == 0 || grp == 0 || !m_trace.printf) {
+        //return tmp data pointer back to the beginning
+        mbed_trace_reset_tmp();
+        goto end;
+    }
+    if ((m_trace.trace_config & TRACE_MASK_LEVEL) &  dlevel) {
+        bool color = (m_trace.trace_config & TRACE_MODE_COLOR) != 0;
+        bool plain = (m_trace.trace_config & TRACE_MODE_PLAIN) != 0;
+        bool cr    = (m_trace.trace_config & TRACE_CARRIAGE_RETURN) != 0;
+
+        int retval = 0, bLeft = m_trace.line_length;
+        char *ptr = m_trace.line;
+        if (plain == true || dlevel == TRACE_LEVEL_CMD) {
+            //add trace data
+            retval = vsnprintf(ptr, bLeft, fmt, ap);
+            if (dlevel == TRACE_LEVEL_CMD && m_trace.cmd_printf) {
+                m_trace.cmd_printf(m_trace.line);
+                m_trace.cmd_printf("\n");
+            } else {
+                //print out whole data
+                m_trace.printf(m_trace.line);
+            }
+        } else {
+            if (color) {
+                if (cr) {
+                    retval = snprintf(ptr, bLeft, "\r\x1b[2K");
+                    if (retval >= bLeft) {
+                        retval = 0;
+                    }
+                    if (retval > 0) {
+                        ptr += retval;
+                        bLeft -= retval;
+                    }
+                }
+                if (bLeft > 0) {
+                    //include color in ANSI/VT100 escape code
+                    switch (dlevel) {
+                        case (TRACE_LEVEL_ERROR):
+                            retval = snprintf(ptr, bLeft, "%s", VT100_COLOR_ERROR);
+                            break;
+                        case (TRACE_LEVEL_WARN):
+                            retval = snprintf(ptr, bLeft, "%s", VT100_COLOR_WARN);
+                            break;
+                        case (TRACE_LEVEL_INFO):
+                            retval = snprintf(ptr, bLeft, "%s", VT100_COLOR_INFO);
+                            break;
+                        case (TRACE_LEVEL_DEBUG):
+                            retval = snprintf(ptr, bLeft, "%s", VT100_COLOR_DEBUG);
+                            break;
+                        default:
+                            color = 0; //avoid unneeded color-terminate code
+                            retval = 0;
+                            break;
+                    }
+                    if (retval >= bLeft) {
+                        retval = 0;
+                    }
+                    if (retval > 0 && color) {
+                        ptr += retval;
+                        bLeft -= retval;
+                    }
+                }
+
+            }
+            if (bLeft > 0 && m_trace.prefix_f) {
+                //find out length of body
+                size_t sz = 0;
+                va_list ap2;
+                va_copy(ap2, ap);
+                sz = vsnprintf(NULL, 0, fmt, ap2) + retval + (retval ? 4 : 0);
+                va_end(ap2);
+                //add prefix string
+                retval = snprintf(ptr, bLeft, "%s", m_trace.prefix_f(sz));
+                if (retval >= bLeft) {
+                    retval = 0;
+                }
+                if (retval > 0) {
+                    ptr += retval;
+                    bLeft -= retval;
+                }
+            }
+            if (bLeft > 0) {
+                //add group tag
+                switch (dlevel) {
+                    case (TRACE_LEVEL_ERROR):
+                        retval = snprintf(ptr, bLeft, "[ERR ][%-4s]: ", grp);
+                        break;
+                    case (TRACE_LEVEL_WARN):
+                        retval = snprintf(ptr, bLeft, "[WARN][%-4s]: ", grp);
+                        break;
+                    case (TRACE_LEVEL_INFO):
+                        retval = snprintf(ptr, bLeft, "[INFO][%-4s]: ", grp);
+                        break;
+                    case (TRACE_LEVEL_DEBUG):
+                        retval = snprintf(ptr, bLeft, "[DBG ][%-4s]: ", grp);
+                        break;
+                    default:
+                        retval = snprintf(ptr, bLeft, "              ");
+                        break;
+                }
+                if (retval >= bLeft) {
+                    retval = 0;
+                }
+                if (retval > 0) {
+                    ptr += retval;
+                    bLeft -= retval;
+                }
+            }
+            if (retval > 0 && bLeft > 0) {
+                //add trace text
+                retval = vsnprintf(ptr, bLeft, fmt, ap);
+                if (retval >= bLeft) {
+                    retval = 0;
+                }
+                if (retval > 0) {
+                    ptr += retval;
+                    bLeft -= retval;
+                }
+            }
+
+            if (retval > 0 && bLeft > 0  && m_trace.suffix_f) {
+                //add suffix string
+                retval = snprintf(ptr, bLeft, "%s", m_trace.suffix_f());
+                if (retval >= bLeft) {
+                    retval = 0;
+                }
+                if (retval > 0) {
+                    ptr += retval;
+                    bLeft -= retval;
+                }
+            }
+
+            if (retval > 0 && bLeft > 0  && color) {
+                //add zero color VT100 when color mode
+                retval = snprintf(ptr, bLeft, "\x1b[0m");
+                if (retval >= bLeft) {
+                    retval = 0;
+                }
+                if (retval > 0) {
+                    // not used anymore
+                    //ptr += retval;
+                    //bLeft -= retval;
+                }
+            }
+            //print out whole data
+            m_trace.printf(m_trace.line);
+        }
+        //return tmp data pointer back to the beginning
+        mbed_trace_reset_tmp();
+    }
+
+end:
+    if ( m_trace.mutex_release_f ) {
+        // Store the mutex lock count to temp variable so that it won't get
+        // clobbered during last loop iteration when mutex gets released
+        int count = m_trace.mutex_lock_count;
+        m_trace.mutex_lock_count = 0;
+        // Since the helper functions (eg. mbed_trace_array) are used like this:
+        //   mbed_tracef(TRACE_LEVEL_INFO, "grp", "%s", mbed_trace_array(some_array))
+        // The helper function MUST acquire the mutex if it modifies any buffers. However
+        // it CANNOT unlock the mutex because that would allow another thread to acquire
+        // the mutex after helper function unlocks it and before mbed_tracef acquires it
+        // for itself. This means that here we have to unlock the mutex as many times
+        // as it was acquired by trace function and any possible helper functions.
+        do {
+            m_trace.mutex_release_f();
+        } while (--count > 0);
+    }
+}
+static void mbed_trace_reset_tmp(void)
+{
+    m_trace.tmp_data_ptr = m_trace.tmp_data;
+}
+const char *mbed_trace_last(void)
+{
+    return m_trace.line;
+}
+/* Helping functions */
+#define tmp_data_left()  m_trace.tmp_data_length-(m_trace.tmp_data_ptr-m_trace.tmp_data)
+#if MBED_CONF_MBED_TRACE_FEA_IPV6 == 1
+char *mbed_trace_ipv6(const void *addr_ptr)
+{
+    /** Acquire mutex. It is released before returning from mbed_vtracef. */
+    if ( m_trace.mutex_wait_f ) {
+        m_trace.mutex_wait_f();
+        m_trace.mutex_lock_count++;
+    }
+    char *str = m_trace.tmp_data_ptr;
+    if (str == NULL) {
+        return "";
+    }
+    if (tmp_data_left() < 41) {
+        return "";
+    }
+    if (addr_ptr == NULL) {
+        return "<null>";
+    }
+    str[0] = 0;
+    m_trace.tmp_data_ptr += ip6tos(addr_ptr, str) + 1;
+    return str;
+}
+char *mbed_trace_ipv6_prefix(const uint8_t *prefix, uint8_t prefix_len)
+{
+    /** Acquire mutex. It is released before returning from mbed_vtracef. */
+    if ( m_trace.mutex_wait_f ) {
+        m_trace.mutex_wait_f();
+        m_trace.mutex_lock_count++;
+    }
+    char *str = m_trace.tmp_data_ptr;
+    if (str == NULL) {
+        return "";
+    }
+    if (tmp_data_left() < 45) {
+        return "";
+    }
+
+    if ((prefix_len != 0 && prefix == NULL) || prefix_len > 128) {
+        return "<err>";
+    }
+
+    m_trace.tmp_data_ptr += ip6_prefix_tos(prefix, prefix_len, str) + 1;
+    return str;
+}
+#endif //MBED_CONF_MBED_TRACE_FEA_IPV6
+char *mbed_trace_array(const uint8_t *buf, uint16_t len)
+{
+    /** Acquire mutex. It is released before returning from mbed_vtracef. */
+    if ( m_trace.mutex_wait_f ) {
+        m_trace.mutex_wait_f();
+        m_trace.mutex_lock_count++;
+    }
+    int i, bLeft = tmp_data_left();
+    char *str, *wptr;
+    str = m_trace.tmp_data_ptr;
+    if (len == 0 || str == NULL || bLeft == 0) {
+        return "";
+    }
+    if (buf == NULL) {
+        return "<null>";
+    }
+    wptr = str;
+    wptr[0] = 0;
+    const uint8_t *ptr = buf;
+    char overflow = 0;
+    for (i = 0; i < len; i++) {
+        if (bLeft <= 3) {
+            overflow = 1;
+            break;
+        }
+        int retval = snprintf(wptr, bLeft, "%02x:", *ptr++);
+        if (retval <= 0 || retval > bLeft) {
+            break;
+        }
+        bLeft -= retval;
+        wptr += retval;
+    }
+    if (wptr > str) {
+        if( overflow ) {
+            // replace last character as 'star',
+            // which indicate buffer len is not enough
+            *(wptr - 1) = '*';
+        } else {
+            //null to replace last ':' character
+            *(wptr - 1) = 0;
+        }
+    }
+    m_trace.tmp_data_ptr = wptr;
+    return str;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/mbed_lib.json	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,18 @@
+{
+    "name": "mbed-cloud-client",
+    "macros" : [
+        "MBEDTLS_PEM_WRITE_C",
+        "MBEDTLS_CMAC_C",
+        "MBEDTLS_CIPHER_MODE_CTR",
+        "SA_PV_PLAT_K64F_MBEDOS_GNUC",
+        "PB_FIELD_32BIT",
+        "PB_ENABLE_MALLOC",
+        "PB_BUFFER_ONLY",
+        "PV_PROFILE_STD"
+    ],
+    "target_overrides": {
+        "*": {
+            "target.features_add": ["COMMON_PAL"]
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+test/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+Unless specifically indicated otherwise in a file, files are licensed
+under the Apache 2.0 license, as can be found in: apache-2.0.txt
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/apache-2.0.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,56 @@
+
+
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+    You must give any other recipients of the Work or Derivative Works a copy of this License; and
+    You must cause any modified files to carry prominent notices stating that You changed the files; and
+    You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+    If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+    You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/common_functions.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,598 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef COMMON_FUNCTIONS_H_
+#define COMMON_FUNCTIONS_H_
+
+#include "ns_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Common write 64-bit variable to 8-bit pointer.
+ *
+ * Write 64 bits in big-endian (network) byte order.
+ *
+ * \param value 64-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_64_bit(uint64_t value, uint8_t ptr[__static 8]);
+
+/*
+ * Common read 64-bit variable from 8-bit pointer.
+ *
+ * Read 64 bits in big-endian (network) byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 64-bit variable
+ */
+NS_INLINE uint64_t common_read_64_bit(const uint8_t data_buf[__static 8]);
+
+/*
+ * Common write 32-bit variable to 8-bit pointer.
+ *
+ * Write 32 bits in big-endian (network) byte order.
+ *
+ * \param value 32-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_32_bit(uint32_t value, uint8_t ptr[__static 4]);
+
+/*
+ * Common read 32-bit variable from 8-bit pointer.
+ *
+ * Read 32 bits in big-endian (network) byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 32-bit variable
+ */
+NS_INLINE uint32_t common_read_32_bit(const uint8_t data_buf[__static 4]);
+
+/*
+ * Common write 32-bit variable to 8-bit pointer.
+ *
+ * Write 32 bits in little-endian byte order.
+ *
+ * \param value 32-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_32_bit_inverse(uint32_t value, uint8_t ptr[__static 4]);
+
+/*
+ * Common read 32-bit variable from 8-bit pointer.
+ *
+ * Read 32 bits in little-endian byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 32-bit variable
+ */
+NS_INLINE uint32_t common_read_32_bit_inverse(const uint8_t data_buf[__static 4]);
+
+/*
+ * Common write 24-bit variable to 8-bit pointer.
+ *
+ * Write 24 bits in big-endian (network) byte order.
+ *
+ * \param value 24-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_24_bit(uint_fast24_t value, uint8_t ptr[__static 3]);
+
+/*
+ * Common read 24-bit variable from 8-bit pointer.
+ *
+ * Read 24 bits in big-endian (network) byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 24-bit variable
+ */
+NS_INLINE uint_fast24_t common_read_24_bit(const uint8_t data_buf[__static 3]);
+
+/*
+ * Common write 16-bit variable to 8-bit pointer.
+ *
+ * Write 16 bits in big-endian (network) byte order.
+ *
+ * \param value 16-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_16_bit(uint16_t value, uint8_t ptr[__static 2]);
+
+/*
+ * Common read 16-bit variable from 8-bit pointer.
+ *
+ * Read 16 bits in big-endian (network) byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 16-bit variable
+ */
+NS_INLINE uint16_t common_read_16_bit(const uint8_t data_buf[__static 2]);
+
+/*
+ * Common write 16-bit variable to 8-bit pointer.
+ *
+ * Write 16 bits in little-endian byte order.
+ *
+ * \param value 16-bit variable
+ * \param ptr pointer where data to be written
+ *
+ * \return updated pointer
+ */
+NS_INLINE uint8_t *common_write_16_bit_inverse(uint16_t value, uint8_t ptr[__static 2]);
+
+/*
+ * Common read 16-bit variable from 8-bit pointer.
+ *
+ * Read 16 bits in little-endian byte order.
+ *
+ * \param data_buf pointer where data to be read
+ *
+ * \return 16-bit variable
+ */
+NS_INLINE uint16_t common_read_16_bit_inverse(const uint8_t data_buf[__static 2]);
+
+/*
+ * Count bits in a byte
+ *
+ * \param byte byte to inspect
+ *
+ * \return number of 1-bits in byte
+ */
+NS_INLINE uint_fast8_t common_count_bits(uint8_t byte);
+
+/*
+ * Count leading zeros in a byte
+ *
+ * \deprecated Use common_count_leading_zeros_8
+ *
+ * \param byte byte to inspect
+ *
+ * \return number of leading zeros in byte (0-8)
+ */
+NS_INLINE uint_fast8_t common_count_leading_zeros(uint8_t byte);
+
+/*
+ * Count leading zeros in a byte
+ *
+ * \param byte byte to inspect
+ *
+ * \return number of leading zeros in byte (0-8)
+ */
+NS_INLINE uint_fast8_t common_count_leading_zeros_8(uint8_t byte);
+
+/*
+ * Count leading zeros in a 16-bit value
+ *
+ * \param value value to inspect
+ *
+ * \return number of leading zeros in byte (0-16)
+ */
+NS_INLINE uint_fast8_t common_count_leading_zeros_16(uint16_t value);
+
+/*
+ * Count leading zeros in a 32-bit value
+ *
+ * \param value value to inspect
+ *
+ * \return number of leading zeros in byte (0-32)
+ */
+NS_INLINE uint_fast8_t common_count_leading_zeros_32(uint32_t value);
+
+/*
+ * Compare 8-bit serial numbers
+ *
+ * Compare two 8-bit serial numbers, according to RFC 1982 Serial Number
+ * Arithmetic.
+ *
+ * \param s1 first serial number
+ * \param s2 second serial number
+ *
+ * \return true if s1 > s2
+ * \return false if s1 <= s2, or the comparison is undefined
+ */
+NS_INLINE bool common_serial_number_greater_8(uint8_t s1, uint8_t s2);
+
+/*
+ * Compare 16-bit serial numbers
+ *
+ * Compare two 16-bit serial numbers, according to RFC 1982 Serial Number
+ * Arithmetic.
+ *
+ * \param s1 first serial number
+ * \param s2 second serial number
+ *
+ * \return true if s1 > s2
+ * \return false if s1 <= s2, or the comparison is undefined
+ */
+NS_INLINE bool common_serial_number_greater_16(uint16_t s1, uint16_t s2);
+
+/*
+ * Compare 32-bit serial numbers
+ *
+ * Compare two 32-bit serial numbers, according to RFC 1982 Serial Number
+ * Arithmetic.
+ *
+ * \param s1 first serial number
+ * \param s2 second serial number
+ *
+ * \return true if s1 > s2
+ * \return false if s1 <= s2, or the comparison is undefined
+ */
+NS_INLINE bool common_serial_number_greater_32(uint32_t s1, uint32_t s2);
+
+/*
+ * Test a bit in an bit array.
+ *
+ * Check whether a particular bit is set in a bit string. The bit array
+ * is in big-endian (network) bit order.
+ *
+ * \param bitset pointer to bit array
+ * \param bit index of bit - 0 is the most significant bit of the first byte
+ *
+ * \return true if the bit is set
+ */
+NS_INLINE bool bit_test(const uint8_t *bitset, uint_fast8_t bit);
+
+/*
+ * Set a bit in an bit array.
+ *
+ * Set a bit in a bit array. The array is in big-endian (network) bit order.
+ *
+ * \param bitset pointer to bit array
+ * \param bit index of bit - 0 is the most significant bit of the first byte
+ */
+NS_INLINE void bit_set(uint8_t *bitset, uint_fast8_t bit);
+
+/*
+ * Clear a bit in an bit array.
+ *
+ * Clear a bit in a bit array. The bit array is in big-endian (network) bit order.
+ *
+ * \param bitset pointer to bit array
+ * \param bit index of bit - 0 is the most significant bit of the first byte
+ */
+NS_INLINE void bit_clear(uint8_t *bitset, uint_fast8_t bit);
+
+/*
+ * Compare two bitstrings.
+ *
+ * Compare two bitstrings of specified length. The bit strings are in
+ * big-endian (network) bit order.
+ *
+ * \param a pointer to first string
+ * \param b pointer to second string
+ * \param bits number of bits to compare
+ *
+ * \return true if the strings compare equal
+ */
+bool bitsequal(const uint8_t *a, const uint8_t *b, uint_fast8_t bits);
+
+/*
+ * Copy a bitstring
+ *
+ * Copy a bitstring of specified length. The bit string is in big-endian
+ * (network) bit order. Bits beyond the bitlength at the destination are not
+ * modified.
+ *
+ * For example, copying 4 bits sets the first 4 bits of dst[0] from src[0],
+ * the lower 4 bits of dst[0] are unmodified.
+ *
+ * \param dst destination pointer
+ * \param src source pointer
+ * \param bits number of bits to copy
+ *
+ * \return the value of dst
+ */
+uint8_t *bitcopy(uint8_t *restrict dst, const uint8_t *restrict src, uint_fast8_t bits);
+
+/*
+ * Copy a bitstring and pad last byte with zeros
+ *
+ * Copy a bitstring of specified length. The bit string is in big-endian
+ * (network) bit order. Bits beyond the bitlength in the last destination byte are
+ * zeroed.
+ *
+ * For example, copying 4 bits sets the first 4 bits of dst[0] from src[0], and
+ * the lower 4 bits of dst[0] are set to 0.
+ *
+ * \param dst destination pointer
+ * \param src source pointer
+ * \param bits number of bits to copy
+ *
+ * \return the value of dst
+ */
+uint8_t *bitcopy0(uint8_t *restrict dst, const uint8_t *restrict src, uint_fast8_t bits);
+
+/* Provide definitions, either for inlining, or for common_functions.c */
+#if defined NS_ALLOW_INLINING || defined COMMON_FUNCTIONS_FN
+#ifndef COMMON_FUNCTIONS_FN
+#define COMMON_FUNCTIONS_FN NS_INLINE
+#endif
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_64_bit(uint64_t value, uint8_t ptr[__static 8])
+{
+    *ptr++ = value >> 56;
+    *ptr++ = value >> 48;
+    *ptr++ = value >> 40;
+    *ptr++ = value >> 32;
+    *ptr++ = value >> 24;
+    *ptr++ = value >> 16;
+    *ptr++ = value >> 8;
+    *ptr++ = value;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint64_t common_read_64_bit(const uint8_t data_buf[__static 8])
+{
+    uint64_t temp_64;
+    temp_64 = (uint64_t)(*data_buf++) << 56;
+    temp_64 += (uint64_t)(*data_buf++) << 48;
+    temp_64 += (uint64_t)(*data_buf++) << 40;
+    temp_64 += (uint64_t)(*data_buf++) << 32;
+    temp_64 += (uint64_t)(*data_buf++) << 24;
+    temp_64 += (uint64_t)(*data_buf++) << 16;
+    temp_64 += (uint64_t)(*data_buf++) << 8;
+    temp_64 += *data_buf++;
+    return temp_64;
+}
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_32_bit(uint32_t value, uint8_t ptr[__static 4])
+{
+    *ptr++ = value >> 24;
+    *ptr++ = value >> 16;
+    *ptr++ = value >> 8;
+    *ptr++ = value;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint32_t common_read_32_bit(const uint8_t data_buf[__static 4])
+{
+    uint32_t temp_32;
+    temp_32 = (uint32_t)(*data_buf++) << 24;
+    temp_32 += (uint32_t)(*data_buf++) << 16;
+    temp_32 += (uint32_t)(*data_buf++) << 8;
+    temp_32 += *data_buf++;
+    return temp_32;
+}
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_32_bit_inverse(uint32_t value, uint8_t ptr[__static 4])
+{
+    *ptr++ = value;
+    *ptr++ = value >> 8;
+    *ptr++ = value >> 16;
+    *ptr++ = value >> 24;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint32_t common_read_32_bit_inverse(const uint8_t data_buf[__static 4])
+{
+    uint32_t temp_32;
+    temp_32 =  *data_buf++;
+    temp_32 += (uint32_t)(*data_buf++) << 8;
+    temp_32 += (uint32_t)(*data_buf++) << 16;
+    temp_32 += (uint32_t)(*data_buf++) << 24;
+    return temp_32;
+}
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_24_bit(uint_fast24_t value, uint8_t ptr[__static 3])
+{
+    *ptr++ = value >> 16;
+    *ptr++ = value >> 8;
+    *ptr++ = value;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint_fast24_t common_read_24_bit(const uint8_t data_buf[__static 3])
+{
+    uint_fast24_t temp_24;
+    temp_24 = (uint_fast24_t)(*data_buf++) << 16;
+    temp_24 += (uint_fast24_t)(*data_buf++) << 8;
+    temp_24 += *data_buf++;
+    return temp_24;
+}
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_16_bit(uint16_t value, uint8_t ptr[__static 2])
+{
+    *ptr++ = value >> 8;
+    *ptr++ = value;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint16_t common_read_16_bit(const uint8_t data_buf[__static 2])
+{
+    uint16_t temp_16;
+    temp_16 = (uint16_t)(*data_buf++) << 8;
+    temp_16 += *data_buf++;
+    return temp_16;
+}
+
+COMMON_FUNCTIONS_FN uint8_t *common_write_16_bit_inverse(uint16_t value, uint8_t ptr[__static 2])
+{
+    *ptr++ = value;
+    *ptr++ = value >> 8;
+    return ptr;
+}
+
+COMMON_FUNCTIONS_FN uint16_t common_read_16_bit_inverse(const uint8_t data_buf[__static 2])
+{
+    uint16_t temp_16;
+    temp_16 = *data_buf++;
+    temp_16 += (uint16_t)(*data_buf++) << 8;
+    return temp_16;
+}
+
+COMMON_FUNCTIONS_FN uint_fast8_t common_count_bits(uint8_t byte)
+{
+    /* First step sets each bit pair to be count of bits (00,01,10) */
+    /* [00-00 = 00, 01-00 = 01, 10-01 = 01, 11-01 = 10] */
+    uint_fast8_t count = byte - ((byte >> 1) & 0x55);
+    /* Add bit pairs to make each nibble contain count of bits (0-4) */
+    count = (count & 0x33) + ((count >> 2) & 0x33);
+    /* Final result is sum of nibbles (0-8) */
+    count = (count >> 4) + (count & 0x0F);
+    return count;
+}
+
+COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros(uint8_t byte)
+{
+    return common_count_leading_zeros_8(byte);
+}
+
+COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_8(uint8_t byte)
+{
+#ifdef  __CC_ARM
+    return byte ? __clz((unsigned int) byte << 24) : 8;
+#elif defined __GNUC__
+    return byte ? __builtin_clz((unsigned int) byte << 24) : 8;
+#else
+    uint_fast8_t cnt = 0;
+    if (byte == 0) {
+        return 8;
+    }
+    if ((byte & 0xF0) == 0) {
+        byte <<= 4;
+        cnt += 4;
+    }
+    if ((byte & 0xC0) == 0) {
+        byte <<= 2;
+        cnt += 2;
+    }
+    if ((byte & 0x80) == 0) {
+        cnt += 1;
+    }
+
+    return cnt;
+#endif
+}
+
+COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_16(uint16_t value)
+{
+#ifdef  __CC_ARM
+    return value ? __clz((unsigned int) value << 16) : 16;
+#elif defined __GNUC__
+    return value ? __builtin_clz((unsigned int) value << 16) : 16;
+#else
+    uint_fast8_t cnt = 0;
+    if (value == 0) {
+        return 16;
+    }
+    if ((value & 0xFF00) == 0) {
+        value <<= 8;
+        cnt += 8;
+    }
+    if ((value & 0xF000) == 0) {
+        value <<= 4;
+        cnt += 4;
+    }
+    if ((value & 0xC000) == 0) {
+        value <<= 2;
+        cnt += 2;
+    }
+    if ((value & 0x8000) == 0) {
+        cnt += 1;
+    }
+
+    return cnt;
+#endif
+}
+
+COMMON_FUNCTIONS_FN uint_fast8_t common_count_leading_zeros_32(uint32_t value)
+{
+#ifdef  __CC_ARM
+    return __clz(value);
+#elif defined __GNUC__
+    return value ? __builtin_clz(value) : 32;
+#else
+    uint_fast8_t cnt = 0;
+    if (value == 0) {
+        return 32;
+    }
+    if ((value & 0xFFFF0000) == 0) {
+        value <<= 16;
+        cnt += 16;
+    }
+    if ((value & 0xFF000000) == 0) {
+        value <<= 8;
+        cnt += 8;
+    }
+    if ((value & 0xF0000000) == 0) {
+        value <<= 4;
+        cnt += 4;
+    }
+    if ((value & 0xC0000000) == 0) {
+        value <<= 2;
+        cnt += 2;
+    }
+    if ((value & 0x80000000) == 0) {
+        cnt += 1;
+    }
+
+    return cnt;
+#endif
+}
+
+COMMON_FUNCTIONS_FN bool common_serial_number_greater_8(uint8_t s1, uint8_t s2)
+{
+    return (s1 > s2 && s1 - s2 < UINT8_C(0x80)) || (s1 < s2 && s2 - s1 > UINT8_C(0x80));
+}
+
+COMMON_FUNCTIONS_FN bool common_serial_number_greater_16(uint16_t s1, uint16_t s2)
+{
+    return (s1 > s2 && s1 - s2 < UINT16_C(0x8000)) || (s1 < s2 && s2 - s1 > UINT16_C(0x8000));
+}
+
+COMMON_FUNCTIONS_FN bool common_serial_number_greater_32(uint32_t s1, uint32_t s2)
+{
+    return (s1 > s2 && s1 - s2 < UINT32_C(0x80000000)) || (s1 < s2 && s2 - s1 > UINT32_C(0x80000000));
+}
+
+COMMON_FUNCTIONS_FN bool bit_test(const uint8_t *bitset, uint_fast8_t bit)
+{
+    return bitset[bit >> 3] & (0x80 >> (bit & 7));
+}
+
+COMMON_FUNCTIONS_FN void bit_set(uint8_t *bitset, uint_fast8_t bit)
+{
+    bitset[bit >> 3] |= (0x80 >> (bit & 7));
+}
+
+COMMON_FUNCTIONS_FN void bit_clear(uint8_t *bitset, uint_fast8_t bit)
+{
+    bitset[bit >> 3] &= ~(0x80 >> (bit & 7));
+}
+
+#endif /* defined NS_ALLOW_INLINING || defined COMMON_FUNCTIONS_FN */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__COMMON_FUNCTIONS_H_*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/ip6string.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef IP6STRING_H
+#define IP6STRING_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ns_types.h"
+
+#define MAX_IPV6_STRING_LEN_WITH_TRAILING_NULL 40
+
+/**
+ * Print binary IPv6 address to a string.
+ *
+ * String must contain enough room for full address, 40 bytes exact.
+ * IPv4 tunneling addresses are not covered.
+ *
+ * \param ip6addr IPv6 address.
+ * \param p buffer to write string to.
+ * \return length of generated string excluding the terminating null character
+ */
+uint_fast8_t ip6tos(const void *ip6addr, char *p);
+
+/**
+ * Print binary IPv6 prefix to a string.
+ *
+ * String buffer `p` must contain enough room for a full address and prefix length, 44 bytes exact.
+ * Bits in the `prefix` buffer beyond `prefix_len` bits are not shown and only the bytes containing the
+ * prefix bits are read. I.e. for a 20 bit prefix 3 bytes are read, and for a 0 bit prefix 0 bytes are
+ * read (thus if `prefix_len` is zero, `prefix` can be NULL).
+ * `prefix_len` must be 0 to 128.
+ *
+ * \param prefix IPv6 prefix.
+ * \param prefix_len length of `prefix` in bits.
+ * \param p buffer to write string to.
+ * \return length of generated string excluding the terminating null character, or 0 for an error, such as 'prefix_len' > 128
+ */
+uint_fast8_t ip6_prefix_tos(const void *prefix, uint_fast8_t prefix_len, char *p);
+
+/**
+ * Convert numeric IPv6 address string to a binary.
+ *
+ * IPv4 tunneling addresses are not covered.
+ *
+ * \param ip6addr IPv6 address in string format.
+ * \param len Lenght of ipv6 string, maximum of 41.
+ * \param dest buffer for address. MUST be 16 bytes.
+ */
+void stoip6(const char *ip6addr, size_t len, void *dest);
+/**
+ * Find out numeric IPv6 address prefix length.
+ *
+ * \param ip6addr  IPv6 address in string format
+ * \return prefix length or 0 if it not given
+ */
+unsigned char sipv6_prefixlength(const char *ip6addr);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/ip_fsc.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef _NS_FSC_H
+#define _NS_FSC_H
+
+#include "ns_types.h"
+
+#define NEXT_HEADER_TCP     0x06
+#define NEXT_HEADER_UDP     0x11
+#define NEXT_HEADER_ICMP6   0x3A
+
+extern uint16_t ip_fcf_v(uint_fast8_t count, const ns_iovec_t vec[static count]);
+extern uint16_t ipv6_fcf(const uint8_t src_address[static 16], const uint8_t dest_address[static 16],
+                         uint16_t data_length, const uint8_t data_ptr[static data_length],  uint8_t next_protocol);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/ns_list.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,738 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifndef NS_LIST_H_
+#define NS_LIST_H_
+
+#include "ns_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \file
+ * \brief Linked list support library
+ *
+ * The ns_list.h file provides a doubly-linked list/queue, providing O(1)
+ * performance for all insertion/removal operations, and access to either
+ * end of the list.
+ *
+ * Memory footprint is two pointers for the list head, and two pointers in each
+ * list entry. It is similar in concept to BSD's TAILQ.
+ *
+ * Although the API is symmetrical and O(1) in both directions, due to internal
+ * pointer design, it is *slightly* more efficient to insert at the end when
+ * used as a queue, and to iterate forwards rather than backwards.
+ *
+ * Example of an entry type that can be stored to this list.
+ * ~~~
+ *     typedef struct example_entry
+ *     {
+ *         uint8_t        *data;
+ *         uint32_t       data_count;
+ *         ns_list_link_t link;
+ *     }
+ *     example_entry_t;
+ *
+ *     static NS_LIST_HEAD(example_entry_t, link) my_list;
+ *     ns_list_init(&my_list);
+ * ~~~
+ * OR
+ * ~~~
+ *     NS_LIST_HEAD(example_entry_t, link) my_list = NS_LIST_INIT(my_list);
+ * ~~~
+ * OR
+ * ~~~
+ *     static NS_LIST_DEFINE(my_list, example_entry_t, link);
+ * ~~~
+ * OR
+ * ~~~
+ *     typedef NS_LIST_HEAD(example_entry_t, link) example_list_t;
+ *     example_list_t NS_LIST_NAME_INIT(my_list);
+ * ~~~
+ * NOTE: the link field SHALL NOT be accessed by the user.
+ *
+ * An entry can exist on multiple lists by having multiple link fields.
+ *
+ * All the list operations are implemented as macros, most of which are backed
+ * by optionally-inline functions. The macros do not evaluate any arguments more
+ * than once, unless documented.
+ *
+ * In macro documentation, `list_t` refers to a list type defined using
+ * NS_LIST_HEAD(), and `entry_t` to the entry type that was passed to it.
+ */
+
+/** \brief Underlying generic linked list head.
+ *
+ * Users should not use this type directly, but use the NS_LIST_HEAD() macro.
+ */
+typedef struct ns_list {
+    void *first_entry;      ///< Pointer to first entry, or NULL if list is empty
+    void **last_nextptr;    ///< Pointer to last entry's `next` pointer, or
+                            ///< to head's `first_entry` pointer if list is empty
+} ns_list_t;
+
+/** \brief Declare a list head type
+ *
+ * This union stores the real list head, and also encodes as compile-time type
+ * information the offset of the link pointer, and the type of the entry.
+ *
+ * Note that type information is compiler-dependent; this means
+ * ns_list_get_first() could return either `void *`, or a pointer to the actual
+ * entry type. So `ns_list_get_first()->data` is not a portable construct -
+ * always assign returned entry pointers to a properly typed pointer variable.
+ * This assignment will be then type-checked where the compiler supports it, and
+ * will dereference correctly on compilers that don't support this extension.
+ * ~~~
+ *     NS_LIST_HEAD(example_entry_t, link) my_list;
+ *
+ *     example_entry_t *entry = ns_list_get_first(&my_list);
+ *     do_something(entry->data);
+ * ~~~
+ * Each use of this macro generates a new anonymous union, so these two lists
+ * have different types:
+ * ~~~
+ *     NS_LIST_HEAD(example_entry_t, link) my_list1;
+ *     NS_LIST_HEAD(example_entry_t, link) my_list2;
+ * ~~~
+ * If you need to use a list type in multiple places, eg as a function
+ * parameter, use typedef:
+ * ~~~
+ *     typedef NS_LIST_HEAD(example_entry_t, link) example_list_t;
+ *
+ *     void example_function(example_list_t *);
+ * ~~~
+ */
+#define NS_LIST_HEAD(entry_type, field) \
+    NS_LIST_HEAD_BY_OFFSET_(entry_type, offsetof(entry_type, field))
+
+/** \brief Declare a list head type for an incomplete entry type.
+ *
+ * This declares a list head, similarly to NS_LIST_HEAD(), but unlike that
+ * this can be used in contexts where the entry type may be incomplete.
+ *
+ * To use this, the link pointer must be the first member in the
+ * actual complete structure. This is NOT checked - the definition of the
+ * element should probably test NS_STATIC_ASSERT(offsetof(type, link) == 0)
+ * if outside users are known to be using NS_LIST_HEAD_INCOMPLETE().
+ * ~~~
+ *     struct opaque;
+ *     NS_LIST_HEAD_INCOMPLETE(struct opaque) opaque_list;
+ * ~~~
+ */
+#define NS_LIST_HEAD_INCOMPLETE(entry_type) \
+    NS_LIST_HEAD_BY_OFFSET_(entry_type, 0)
+
+/// \privatesection
+/** \brief Internal macro defining a list head, given the offset to the link pointer
+ * The +1 allows for link_offset being 0 - we can't declare a 0-size array
+ */
+#define NS_LIST_HEAD_BY_OFFSET_(entry_type, link_offset) \
+union \
+{ \
+    ns_list_t slist; \
+    NS_FUNNY_COMPARE_OK \
+    NS_STATIC_ASSERT(link_offset <= UINT_FAST8_MAX, "link offset too large") \
+    NS_FUNNY_COMPARE_RESTORE \
+    char (*offset)[link_offset + 1]; \
+    entry_type *type; \
+}
+
+/** \brief Get offset of link field in entry.
+ * \return `(ns_list_offset_t)` The offset of the link field for entries on the specified list
+ */
+#define NS_LIST_OFFSET_(list) ((ns_list_offset_t) (sizeof *(list)->offset - 1))
+
+/** \brief Get the entry pointer type.
+ * \def NS_LIST_PTR_TYPE_
+ *
+ * \return An unqualified pointer type to an entry on the specified list.
+ *
+ * Only available if the compiler provides a "typeof" operator.
+ */
+#if defined __cplusplus && __cplusplus >= 201103L
+#define NS_LIST_PTR_TYPE_(list) decltype((list)->type)
+#elif defined __GNUC__
+#define NS_LIST_PTR_TYPE_(list) __typeof__((list)->type)
+#endif
+
+/** \brief Check for compatible pointer types
+ *
+ * This test will produce a diagnostic about a pointer mismatch on
+ * the == inside the sizeof operator. For example ARM/Norcroft C gives the error:
+ *
+ *     operand types are incompatible ("entry_t *" and "other_t *")
+ */
+#ifdef CPPCHECK
+#define NS_PTR_MATCH_(a, b, str) ((void) 0)
+#else
+#define NS_PTR_MATCH_(a, b, str) ((void) sizeof ((a) == (b)))
+#endif
+
+/** \brief Internal macro to cast returned entry pointers to correct type.
+ *
+ * Not portable in C, alas. With GCC or C++11, the "get entry" macros return
+ * correctly-typed pointers. Otherwise, the macros return `void *`.
+ *
+ * The attempt at a portable version would work if the C `?:` operator wasn't
+ * broken - `x ? (t *) : (void *)` should really have type `(t *)` in C, but
+ * it has type `(void *)`, which only makes sense for C++. The `?:` is left in,
+ * in case some day it works. Some compilers may still warn if this is
+ * assigned to a different type.
+ */
+#ifdef NS_LIST_PTR_TYPE_
+#define NS_LIST_TYPECAST_(list, val) ((NS_LIST_PTR_TYPE_(list)) (val))
+#else
+#define NS_LIST_TYPECAST_(list, val) (0 ? (list)->type : (val))
+#endif
+
+/** \brief Internal macro to check types of input entry pointer. */
+#define NS_LIST_TYPECHECK_(list, entry) \
+    (NS_PTR_MATCH_((list)->type, (entry), "incorrect entry type for list"), (entry))
+
+/** \brief Type used to pass link offset to underlying functions
+ *
+ * We could use size_t, but it would be unnecessarily large on 8-bit systems,
+ * where we can be (pretty) confident we won't have next pointers more than
+ * 256 bytes into a structure.
+ */
+typedef uint_fast8_t ns_list_offset_t;
+
+/// \publicsection
+/** \brief The type for the link member in the user's entry structure.
+ *
+ * Users should not access this member directly - just pass its name to the
+ * list head macros. The funny prev pointer simplifies common operations
+ * (eg insertion, removal), at the expense of complicating rare reverse iteration.
+ *
+ * NB - the list implementation relies on next being the first member.
+ */
+typedef struct ns_list_link {
+    void *next;     ///< Pointer to next entry, or NULL if none
+    void **prev;    ///< Pointer to previous entry's (or head's) next pointer
+} ns_list_link_t;
+
+/** \brief "Poison" value placed in unattached entries' link pointers.
+ * \internal What are good values for this? Platform dependent, maybe just NULL
+ */
+#define NS_LIST_POISON ((void *) 0xDEADBEEF)
+
+/** \brief Initialiser for an entry's link member
+ *
+ * This initialiser is not required by the library, but a user may want an
+ * initialiser to include in their own entry initialiser. See
+ * ns_list_link_init() for more discussion.
+ */
+#define NS_LIST_LINK_INIT(name) \
+    NS_FUNNY_INTPTR_OK \
+    { NS_LIST_POISON, NS_LIST_POISON } \
+    NS_FUNNY_INTPTR_RESTORE
+
+/** \hideinitializer \brief Initialise an entry's list link
+ *
+ * This "initialises" an unattached entry's link by filling the fields with
+ * poison. This is optional, as unattached entries field pointers are not
+ * meaningful, and it is not valid to call ns_list_get_next or similar on
+ * an unattached entry.
+ *
+ * \param entry Pointer to an entry
+ * \param field The name of the link member to initialise
+ */
+#define ns_list_link_init(entry, field) ns_list_link_init_(&(entry)->field)
+
+/** \hideinitializer \brief Initialise a list
+ *
+ * Initialise a list head before use. A list head must be initialised using this
+ * function or one of the NS_LIST_INIT()-type macros before use. A zero-initialised
+ * list head is *not* valid.
+ *
+ * If used on a list containing existing entries, those entries will
+ * become detached. (They are not modified, but their links are now effectively
+ * undefined).
+ *
+ * \param list Pointer to a NS_LIST_HEAD() structure.
+ */
+#define ns_list_init(list) ns_list_init_(&(list)->slist)
+
+/** \brief Initialiser for an empty list
+ *
+ * Usage in an enclosing initialiser:
+ * ~~~
+ *      static my_type_including_list_t x = {
+ *          "Something",
+ *          23,
+ *          NS_LIST_INIT(x),
+ *      };
+ * ~~~
+ * NS_LIST_DEFINE() or NS_LIST_NAME_INIT() may provide a shorter alternative
+ * in simpler cases.
+ */
+#define NS_LIST_INIT(name) { { NULL, &(name).slist.first_entry } }
+
+/** \brief Name and initialiser for an empty list
+ *
+ * Usage:
+ * ~~~
+ *      list_t NS_LIST_NAME_INIT(foo);
+ * ~~~
+ * acts as
+ * ~~~
+ *      list_t foo = { empty list };
+ * ~~~
+ * Also useful with designated initialisers:
+ * ~~~
+ *      .NS_LIST_NAME_INIT(foo),
+ * ~~~
+ * acts as
+ * ~~~
+ *      .foo = { empty list },
+ * ~~~
+ */
+#define NS_LIST_NAME_INIT(name) name = NS_LIST_INIT(name)
+
+/** \brief Define a list, and initialise to empty.
+ *
+ * Usage:
+ * ~~~
+ *     static NS_LIST_DEFINE(my_list, entry_t, link);
+ * ~~~
+ * acts as
+ * ~~~
+ *     static list_type my_list = { empty list };
+ * ~~~
+ */
+#define NS_LIST_DEFINE(name, type, field) \
+    NS_LIST_HEAD(type, field) NS_LIST_NAME_INIT(name)
+
+/** \hideinitializer \brief Add an entry to the start of the linked list.
+ *
+ * ns_list_add_to_end() is *slightly* more efficient than ns_list_add_to_start().
+ *
+ * \param list  `(list_t *)`           Pointer to list.
+ * \param entry `(entry_t * restrict)` Pointer to new entry to add.
+ */
+#define ns_list_add_to_start(list, entry) \
+    ns_list_add_to_start_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, entry))
+
+/** \hideinitializer \brief Add an entry to the end of the linked list.
+ *
+ * \param list  `(list_t *)`           Pointer to list.
+ * \param entry `(entry_t * restrict)` Pointer to new entry to add.
+ */
+#define ns_list_add_to_end(list, entry) \
+    ns_list_add_to_end_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, entry))
+
+/** \hideinitializer \brief Add an entry before a specified entry.
+ *
+ * \param list   `(list_t *)`           Pointer to list.
+ * \param before `(entry_t *)`          Existing entry before which to place the new entry.
+ * \param entry  `(entry_t * restrict)` Pointer to new entry to add.
+ */
+#define ns_list_add_before(list, before, entry) \
+    ns_list_add_before_(NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, before), NS_LIST_TYPECHECK_(list, entry))
+
+/** \hideinitializer \brief Add an entry after a specified entry.
+ *
+ * ns_list_add_before() is *slightly* more efficient than ns_list_add_after().
+ *
+ * \param list  `(list_t *)`           Pointer to list.
+ * \param after `(entry_t *)`          Existing entry after which to place the new entry.
+ * \param entry `(entry_t * restrict)` Pointer to new entry to add.
+ */
+#define ns_list_add_after(list, after, entry) \
+    ns_list_add_after_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, after), NS_LIST_TYPECHECK_(list, entry))
+
+/** \brief Check if a list is empty.
+ *
+ * \param list `(const list_t *)` Pointer to list.
+ *
+ * \return     `(bool)`           true if the list is empty.
+ */
+#define ns_list_is_empty(list) ((bool) ((list)->slist.first_entry == NULL))
+
+/** \brief Get the first entry.
+ *
+ * \param list `(const list_t *)` Pointer to list.
+ *
+ * \return     `(entry_t *)`      Pointer to first entry.
+ * \return                        NULL if list is empty.
+ */
+#define ns_list_get_first(list) NS_LIST_TYPECAST_(list, (list)->slist.first_entry)
+
+/** \hideinitializer \brief Get the previous entry.
+ *
+ * \param list    `(const list_t *)`  Pointer to list.
+ * \param current `(const entry_t *)` Pointer to current entry.
+ *
+ * \return        `(entry_t *)`       Pointer to previous entry.
+ * \return                            NULL if current entry is first.
+ */
+#define ns_list_get_previous(list, current) \
+    NS_LIST_TYPECAST_(list, ns_list_get_previous_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, current)))
+
+/** \hideinitializer \brief Get the next entry.
+ *
+ * \param list    `(const list_t *)`  Pointer to list.
+ * \param current `(const entry_t *)` Pointer to current entry.
+ *
+ * \return        `(entry_t *)`       Pointer to next entry.
+ * \return                            NULL if current entry is last.
+ */
+#define ns_list_get_next(list, current) \
+    NS_LIST_TYPECAST_(list, ns_list_get_next_(NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, current)))
+
+/** \hideinitializer \brief Get the last entry.
+ *
+ * \param list `(const list_t *)` Pointer to list.
+ *
+ * \return     `(entry_t *)`      Pointer to last entry.
+ * \return                        NULL if list is empty.
+ */
+#define ns_list_get_last(list) \
+    NS_LIST_TYPECAST_(list, ns_list_get_last_(&(list)->slist, NS_LIST_OFFSET_(list)))
+
+/** \hideinitializer \brief Remove an entry.
+ *
+ * \param list  `(list_t *)`  Pointer to list.
+ * \param entry `(entry_t *)` Entry on list to be removed.
+ */
+#define ns_list_remove(list, entry) \
+    ns_list_remove_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, entry))
+
+/** \hideinitializer \brief Replace an entry.
+ *
+ * \param list        `(list_t *)`           Pointer to list.
+ * \param current     `(entry_t *)`          Existing entry on list to be replaced.
+ * \param replacement `(entry_t * restrict)` New entry to be the replacement.
+ */
+#define ns_list_replace(list, current, replacement) \
+    ns_list_replace_(&(list)->slist, NS_LIST_OFFSET_(list), NS_LIST_TYPECHECK_(list, current), NS_LIST_TYPECHECK_(list, replacement))
+
+/** \hideinitializer \brief Concatenate two lists.
+ *
+ * Attach the entries on the source list to the end of the destination
+ * list, leaving the source list empty.
+ *
+ * \param dst `(list_t *)` Pointer to destination list.
+ * \param src `(list_t *)` Pointer to source list.
+ *
+ */
+#define ns_list_concatenate(dst, src) \
+        (NS_PTR_MATCH_(dst, src, "concatenating different list types"), \
+        ns_list_concatenate_(&(dst)->slist, &(src)->slist, NS_LIST_OFFSET_(src)))
+
+/** \brief Iterate forwards over a list.
+ *
+ * Example:
+ * ~~~
+ *     ns_list_foreach(const my_entry_t, cur, &my_list)
+ *     {
+ *         printf("%s\n", cur->name);
+ *     }
+ * ~~~
+ * Deletion of the current entry is not permitted as its next is checked after
+ * running user code.
+ *
+ * The iteration pointer is declared inside the loop, using C99/C++, so it
+ * is not accessible after the loop.  This encourages good code style, and
+ * matches the semantics of C++11's "ranged for", which only provides the
+ * declaration form:
+ * ~~~
+ *     for (const my_entry_t cur : my_list)
+ * ~~~
+ * If you need to see the value of the iteration pointer after a `break`,
+ * you will need to assign it to a variable declared outside the loop before
+ * breaking:
+ * ~~~
+ *      my_entry_t *match = NULL;
+ *      ns_list_foreach(my_entry_t, cur, &my_list)
+ *      {
+ *          if (cur->id == id)
+ *          {
+ *              match = cur;
+ *              break;
+ *          }
+ *      }
+ * ~~~
+ *
+ * The user has to specify the entry type for the pointer definition, as type
+ * extraction from the list argument isn't portable. On the other hand, this
+ * also permits const qualifiers, as in the example above, and serves as
+ * documentation. The entry type will be checked against the list type where the
+ * compiler supports it.
+ *
+ * \param type                    Entry type `([const] entry_t)`.
+ * \param e                       Name for iteration pointer to be defined
+ *                                inside the loop.
+ * \param list `(const list_t *)` Pointer to list - evaluated multiple times.
+ */
+#define ns_list_foreach(type, e, list) \
+    for (type *e = ns_list_get_first(list); e; e = ns_list_get_next(list, e))
+
+/** \brief Iterate forwards over a list, where user may delete.
+ *
+ * As ns_list_foreach(), but deletion of current entry is permitted as its
+ * next pointer is recorded before running user code.
+ *
+ * Example:
+ * ~~~
+ *     ns_list_foreach_safe(my_entry_t, cur, &my_list)
+ *     {
+ *         ns_list_remove(cur);
+ *     }
+ * ~~~
+ * \param type               Entry type `(entry_t)`.
+ * \param e                  Name for iteration pointer to be defined
+ *                           inside the loop.
+ * \param list `(list_t *)`  Pointer to list - evaluated multiple times.
+ */
+#define ns_list_foreach_safe(type, e, list) \
+    for (type *e = ns_list_get_first(list), *_next##e; \
+        e && (_next##e = ns_list_get_next(list, e), true); e = _next##e)
+
+/** \brief Iterate backwards over a list.
+ *
+ * As ns_list_foreach(), but going backwards - see its documentation.
+ * Iterating forwards is *slightly* more efficient.
+ */
+#define ns_list_foreach_reverse(type, e, list) \
+    for (type *e = ns_list_get_last(list); e; e = ns_list_get_previous(list, e))
+
+/** \brief Iterate backwards over a list, where user may delete.
+ *
+ * As ns_list_foreach_safe(), but going backwards - see its documentation.
+ * Iterating forwards is *slightly* more efficient.
+ */
+#define ns_list_foreach_reverse_safe(type, e, list) \
+    for (type *e = ns_list_get_last(list), *_next##e; \
+        e && (_next##e = ns_list_get_previous(list, e), true); e = _next##e)
+
+/** \hideinitializer \brief Count entries on a list
+ *
+ * Unlike other operations, this is O(n). Note: if list might contain over
+ * 65535 entries, this function **must not** be used to get the entry count.
+ *
+ * \param list `(const list_t *)` Pointer to list.
+
+ * \return     `(uint_fast16_t)`  Number of entries that are stored in list.
+ */
+#define ns_list_count(list) ns_list_count_(&(list)->slist, NS_LIST_OFFSET_(list))
+
+/** \privatesection
+ *  Internal functions - designed to be accessed using corresponding macros above
+ */
+NS_INLINE void ns_list_init_(ns_list_t *list);
+NS_INLINE void ns_list_link_init_(ns_list_link_t *link);
+NS_INLINE void ns_list_add_to_start_(ns_list_t *list, ns_list_offset_t link_offset, void *restrict entry);
+NS_INLINE void ns_list_add_to_end_(ns_list_t *list, ns_list_offset_t link_offset, void *restrict entry);
+NS_INLINE void ns_list_add_before_(ns_list_offset_t link_offset, void *before, void *restrict entry);
+NS_INLINE void ns_list_add_after_(ns_list_t *list, ns_list_offset_t link_offset, void *after, void *restrict entry);
+NS_INLINE void *ns_list_get_next_(ns_list_offset_t link_offset, const void *current);
+NS_INLINE void *ns_list_get_previous_(const ns_list_t *list, ns_list_offset_t link_offset, const void *current);
+NS_INLINE void *ns_list_get_last_(const ns_list_t *list,  ns_list_offset_t offset);
+NS_INLINE void ns_list_remove_(ns_list_t *list, ns_list_offset_t link_offset, void *entry);
+NS_INLINE void ns_list_replace_(ns_list_t *list, ns_list_offset_t link_offset, void *current, void *restrict replacement);
+NS_INLINE void ns_list_concatenate_(ns_list_t *dst, ns_list_t *src, ns_list_offset_t offset);
+NS_INLINE uint_fast16_t ns_list_count_(const ns_list_t *list, ns_list_offset_t link_offset);
+
+/* Provide definitions, either for inlining, or for ns_list.c */
+#if defined NS_ALLOW_INLINING || defined NS_LIST_FN
+#ifndef NS_LIST_FN
+#define NS_LIST_FN NS_INLINE
+#endif
+
+/* Pointer to the link member in entry e */
+#define NS_LIST_LINK_(e, offset) ((ns_list_link_t *)((char *)(e) + offset))
+
+/* Lvalue of the next link pointer in entry e */
+#define NS_LIST_NEXT_(e, offset) (NS_LIST_LINK_(e, offset)->next)
+
+/* Lvalue of the prev link pointer in entry e */
+#define NS_LIST_PREV_(e, offset) (NS_LIST_LINK_(e, offset)->prev)
+
+/* Convert a pointer to a link member back to the entry;
+ * works for linkptr either being a ns_list_link_t pointer, or its next pointer,
+ * as the next pointer is first in the ns_list_link_t */
+#define NS_LIST_ENTRY_(linkptr, offset) ((void *)((char *)(linkptr) - offset))
+
+NS_LIST_FN void ns_list_init_(ns_list_t *list)
+{
+    list->first_entry = NULL;
+    list->last_nextptr = &list->first_entry;
+}
+
+NS_LIST_FN void ns_list_link_init_(ns_list_link_t *link)
+{
+    NS_FUNNY_INTPTR_OK
+    link->next = NS_LIST_POISON;
+    link->prev = NS_LIST_POISON;
+    NS_FUNNY_INTPTR_RESTORE
+}
+
+NS_LIST_FN void ns_list_add_to_start_(ns_list_t *list, ns_list_offset_t offset, void *restrict entry)
+{
+    void *next;
+
+    NS_LIST_PREV_(entry, offset) = &list->first_entry;
+    NS_LIST_NEXT_(entry, offset) = next = list->first_entry;
+
+    if (next) {
+        NS_LIST_PREV_(next, offset) = &NS_LIST_NEXT_(entry, offset);
+    } else {
+        list->last_nextptr = &NS_LIST_NEXT_(entry, offset);
+    }
+
+    list->first_entry = entry;
+}
+
+NS_LIST_FN void ns_list_add_after_(ns_list_t *list, ns_list_offset_t offset, void *current, void *restrict entry)
+{
+    void *next;
+
+    NS_LIST_PREV_(entry, offset) = &NS_LIST_NEXT_(current, offset);
+    NS_LIST_NEXT_(entry, offset) = next = NS_LIST_NEXT_(current, offset);
+
+    if (next) {
+        NS_LIST_PREV_(next, offset) = &NS_LIST_NEXT_(entry, offset);
+    } else {
+        list->last_nextptr = &NS_LIST_NEXT_(entry, offset);
+    }
+
+    NS_LIST_NEXT_(current, offset) = entry;
+}
+
+NS_LIST_FN void ns_list_add_before_(ns_list_offset_t offset, void *current, void *restrict entry)
+{
+    void **prev_nextptr;
+
+    NS_LIST_NEXT_(entry, offset) = current;
+    NS_LIST_PREV_(entry, offset) = prev_nextptr = NS_LIST_PREV_(current, offset);
+    *prev_nextptr = entry;
+    NS_LIST_PREV_(current, offset) = &NS_LIST_NEXT_(entry, offset);
+}
+
+NS_LIST_FN void ns_list_add_to_end_(ns_list_t *list, ns_list_offset_t offset, void *restrict entry)
+{
+    void **prev_nextptr;
+
+    NS_LIST_NEXT_(entry, offset) = NULL;
+    NS_LIST_PREV_(entry, offset) = prev_nextptr = list->last_nextptr;
+    *prev_nextptr = entry;
+    list->last_nextptr = &NS_LIST_NEXT_(entry, offset);
+}
+
+NS_LIST_FN void *ns_list_get_next_(ns_list_offset_t offset, const void *current)
+{
+    return NS_LIST_NEXT_(current, offset);
+}
+
+NS_LIST_FN void *ns_list_get_previous_(const ns_list_t *list, ns_list_offset_t offset, const void *current)
+{
+    if (current == list->first_entry) {
+        return NULL;
+    }
+
+    // Tricky. We don't have a direct previous pointer, but a pointer to the
+    // pointer that points to us - ie &head->first_entry OR &{prev}->next.
+    // This makes life easier on insertion and removal, but this is where we
+    // pay the price.
+
+    // We have to check manually for being the first entry above, so we know it's
+    // a real link's next pointer. Then next is the first field of
+    // ns_list_link_t, so we can use the normal offset value.
+
+    return NS_LIST_ENTRY_(NS_LIST_PREV_(current, offset), offset);
+}
+
+NS_LIST_FN void *ns_list_get_last_(const ns_list_t *list, ns_list_offset_t offset)
+{
+    if (!list->first_entry) {
+        return NULL;
+    }
+
+    // See comments in ns_list_get_previous_()
+    return NS_LIST_ENTRY_(list->last_nextptr, offset);
+}
+
+NS_LIST_FN void ns_list_remove_(ns_list_t *list, ns_list_offset_t offset, void *removed)
+{
+    void *next;
+    void **prev_nextptr;
+
+    next = NS_LIST_NEXT_(removed, offset);
+    prev_nextptr = NS_LIST_PREV_(removed, offset);
+    if (next) {
+        NS_LIST_PREV_(next, offset) = prev_nextptr;
+    } else {
+        list->last_nextptr = prev_nextptr;
+    }
+    *prev_nextptr = next;
+
+    ns_list_link_init_(NS_LIST_LINK_(removed, offset));
+}
+
+NS_LIST_FN void ns_list_replace_(ns_list_t *list, ns_list_offset_t offset, void *current, void *restrict replacement)
+{
+    void *next;
+    void **prev_nextptr;
+
+    NS_LIST_PREV_(replacement, offset) = prev_nextptr = NS_LIST_PREV_(current, offset);
+    NS_LIST_NEXT_(replacement, offset) = next = NS_LIST_NEXT_(current, offset);
+
+    if (next) {
+        NS_LIST_PREV_(next, offset) = &NS_LIST_NEXT_(replacement, offset);
+    } else {
+        list->last_nextptr = &NS_LIST_NEXT_(replacement, offset);
+    }
+    *prev_nextptr = replacement;
+
+    ns_list_link_init_(NS_LIST_LINK_(current, offset));
+}
+
+NS_LIST_FN void ns_list_concatenate_(ns_list_t *dst, ns_list_t *src, ns_list_offset_t offset)
+{
+    ns_list_link_t *src_first;
+
+    src_first = src->first_entry;
+    if (!src_first) {
+        return;
+    }
+
+    *dst->last_nextptr = src_first;
+    NS_LIST_PREV_(src_first, offset) = dst->last_nextptr;
+    dst->last_nextptr = src->last_nextptr;
+
+    ns_list_init_(src);
+}
+
+NS_LIST_FN uint_fast16_t ns_list_count_(const ns_list_t *list, ns_list_offset_t offset)
+{
+    uint_fast16_t count = 0;
+
+    for (void *p = list->first_entry; p; p = NS_LIST_NEXT_(p, offset)) {
+        count++;
+    }
+
+    return count;
+}
+#endif /* defined NS_ALLOW_INLINING || defined NS_LIST_FN */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NS_LIST_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/ns_nvm_helper.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,100 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+/**
+ * NanoStack NVM helper functions to read, write and delete key-value pairs to platform NVM.
+ *
+ * Client can use following methods:
+ * -ns_nvm_data_write to write data to a key in platform NVM
+ * -ns_nvm_data_read to read data from key in platform NVM
+ * -ns_nvm_key_delete to delete a key from platform NVM
+ *
+ * If a API call returns NS_NVM_OK then a provided callback function will be called
+ * and status argument indicates success or failure of the operation. If API call
+ * returns error then callback will not be called.
+ *
+ * When client writes data this module will:
+ * -initialize the NVM if not already initialized
+ * -(re)create the key with a given size
+ * -write data to the key
+ * -flush data to the NVM
+ *
+ * When client reads data this module will:
+ * -initialize the NVM if not initialized
+ * -read data from the key
+ *
+ * When client deletes a key this module will:
+ * -initialize the NVM if not initialized
+ * -delete the key from NVM
+ */
+
+/*
+ * API function and callback function return statuses
+ */
+#define NS_NVM_OK               0
+#define NS_NVM_DATA_NOT_FOUND   -1
+#define NS_NVM_ERROR            -2
+#define NS_NVM_MEMORY           -3
+
+/**
+ *  callback type for NanoStack NVM
+ */
+typedef void (ns_nvm_callback)(int status, void *context);
+
+/**
+ * \brief Delete key from NVM
+ *
+ * \param callback function to be called when key deletion is ready
+ * \param key_name Name of the key to be deleted from NVM
+ * \param context argument will be provided as an argument when callback is called
+ *
+ * \return NS_NVM_OK if key deletion is in progress and callback will be called
+ * \return NS_NVM_ERROR in error case, callback will not be called
+ * \return provided callback function will be called with status indicating success or failure.
+ */
+int ns_nvm_key_delete(ns_nvm_callback *callback, const char *key_name, void *context);
+
+/**
+ * \brief Read data from NVM
+ *
+ * \param callback function to be called when data is read
+ * \param key_name Name of the key whose data will be read
+ * \param buf buffer where data will be stored
+ * \param buf_len address of variable containing provided buffer length
+ * \param context argument will be provided as an argument when callback is called
+ *
+ * \return NS_NVM_OK if read is in progress and callback will be called
+ * \return NS_NVM_ERROR in error case, callback will not be called
+ * \return provided callback function will be called with status indicating success or failure.
+ */
+int ns_nvm_data_read(ns_nvm_callback *callback, const char *key_name, uint8_t *buf, uint16_t *buf_len, void *context);
+
+/**
+ * \brief Write data to NVM
+ *
+ * \param callback function to be called when data writing is completed
+ * \param key_name Name of the key whose data will be read
+ * \param buf buffer where data will be stored
+ * \param buf_len address of variable containing provided buffer length
+ * \param context argument will be provided as an argument when callback is called
+ *
+ * \return NS_NVM_OK if read is in progress and callback will be called
+ * \return NS_NVM_ERROR in error case, callback will not be called
+ * \return provided callback function will be called with status indicating success or failure.
+ */
+int ns_nvm_data_write(ns_nvm_callback *callback, const char *key_name, uint8_t *buf, uint16_t *buf_len, void *context);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/ns_trace.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2015-2017 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/**
+ * \file ns_trace.h
+ * Trace interface abstraction for NanoStack library as well as application.
+ *
+ * Actual used trace library is mbed-trace. For usage details check mbed_trace.h.
+ *
+ */
+#ifndef NS_TRACE_H_
+#define NS_TRACE_H_
+
+#if defined(HAVE_DEBUG) && !defined(FEA_TRACE_SUPPORT)
+#define FEA_TRACE_SUPPORT
+#endif
+
+#include "mbed-trace/mbed_trace.h"
+
+#endif /* NS_TRACE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/ns_types.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+/*
+ * ns_types.h - Basic compiler and type setup for Nanostack libraries.
+ */
+#ifndef NS_TYPES_H_
+#define NS_TYPES_H_
+
+/** \file
+ * \brief Basic compiler and type setup
+ *
+ * We currently assume C99 or later.
+ *
+ * C99 features being relied on:
+ *
+ *   - <inttypes.h> and <stdbool.h>
+ *   - inline (with C99 semantics, not C++ as per default GCC);
+ *   - designated initialisers;
+ *   - compound literals;
+ *   - restrict;
+ *   - [static N] in array parameters;
+ *   - declarations in for statements;
+ *   - mixing declarations and statements
+ *
+ * Compilers should be set to C99 or later mode when building Nanomesh source.
+ * For GCC this means "-std=gnu99" (C99 with usual GNU extensions).
+ *
+ * Also, a little extra care is required for public header files that could be
+ * included from C++, especially as C++ lacks some C99 features.
+ *
+ * (TODO: as this is exposed to API users, do we need a predefine to distinguish
+ * internal and external use, for finer control? Not yet, but maybe...)
+ */
+
+/* Make sure <stdint.h> defines its macros if C++ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+#ifndef __STDC_CONSTANT_MACROS
+#define __STDC_CONSTANT_MACROS
+#endif
+
+#include <stddef.h>
+#include <inttypes.h> // includes <stdint.h>; debugf() users need PRIu32 etc
+#include <stdbool.h>
+
+/*
+ * Create the optional <stdint.h> 24-bit types if they don't exist (worth trying
+ * to use them, as they could exist and be more efficient than 32-bit on 8-bit
+ * systems...)
+ */
+#ifndef UINT_LEAST24_MAX
+typedef uint_least32_t uint_least24_t;
+#define UINT_LEAST24_MAX UINT_LEAST32_MAX
+#define UINT24_C(x) UINT32_C(x)
+#define PRIoLEAST24 PRIoLEAST32
+#define PRIuLEAST24 PRIuLEAST32
+#define PRIxLEAST24 PRIxLEAST32
+#define PRIXLEAST24 PRIXLEAST32
+#endif
+
+#ifndef INT_LEAST24_MAX
+typedef int_least32_t int_least24_t;
+#define INT_LEAST24_MIN INT_LEAST32_MIN
+#define INT_LEAST24_MAX INT_LEAST32_MAX
+#define INT24_C(x) INT32_C(x)
+#define PRIdLEAST24 PRIdLEAST32
+#define PRIiLEAST24 PRIiLEAST32
+#endif
+
+#ifndef UINT_FAST24_MAX
+typedef uint_fast32_t uint_fast24_t;
+#define UINT_FAST24_MAX UINT_FAST32_MAX
+#define PRIoFAST24 PRIoFAST32
+#define PRIuFAST24 PRIuFAST32
+#define PRIxFAST24 PRIxFAST32
+#define PRIXFAST24 PRIXFAST32
+#endif
+
+#ifndef INT_FAST24_MAX
+typedef int_fast32_t int_fast24_t;
+#define INT_FAST24_MIN INT_FAST32_MIN
+#define INT_FAST24_MAX INT_FAST32_MAX
+#define PRIdFAST24 PRIdFAST32
+#define PRIiFAST24 PRIiFAST32
+#endif
+
+/* Function attribute - C11 "noreturn" or C++11 "[[noreturn]]" */
+#ifndef NS_NORETURN
+#if defined  __cplusplus && __cplusplus >= 201103L
+#define NS_NORETURN [[noreturn]]
+#elif !defined  __cplusplus && __STDC_VERSION__ >= 201112L
+#define NS_NORETURN _Noreturn
+#elif defined __GNUC__
+#define NS_NORETURN __attribute__((__noreturn__))
+#elif defined __CC_ARM
+#define NS_NORETURN __declspec(noreturn)
+#elif defined __IAR_SYSTEMS_ICC__
+#define NS_NORETURN __noreturn
+#else
+#define NS_NORETURN
+#endif
+#endif
+
+/* C11's "alignas" macro, emulated for integer expressions if necessary */
+#ifndef __alignas_is_defined
+#if defined __CC_ARM || defined __TASKING__
+#define alignas(n) __align(n)
+#define __alignas_is_defined 1
+#elif (__STDC_VERSION__ >= 201112L) || (defined __cplusplus && __cplusplus >= 201103L)
+#include <stdalign.h>
+#elif defined __GNUC__
+#define alignas(n) __attribute__((__aligned__(n)))
+#define __alignas_is_defined 1
+#elif defined __IAR_SYSTEMS_ICC__
+/* Does this really just apply to the next variable? */
+#define alignas(n) __Alignas(data_alignment=n)
+#define __Alignas(x) _Pragma(#x)
+#define __alignas_is_defined 1
+#endif
+#endif
+
+/**
+ * Marker for functions or objects that may be unused, suppressing warnings.
+ * Place after the identifier:
+ * ~~~
+ *    static int X MAYBE_UNUSED = 3;
+ *    static int foo(void) MAYBE_UNUSED;
+ * ~~~
+ */
+#if defined __CC_ARM || defined __GNUC__
+#define MAYBE_UNUSED __attribute__((unused))
+#else
+#define MAYBE_UNUSED
+#endif
+
+/*
+ * C++ (even C++11) doesn't provide restrict: define away or provide
+ * alternative.
+ */
+#ifdef __cplusplus
+#ifdef __GNUC__
+#define restrict __restrict
+#else
+#define restrict
+#endif
+#endif /* __cplusplus */
+
+
+/**
+ * C++ doesn't allow "static" in function parameter types: ie
+ * ~~~
+ *    entry_t *find_entry(const uint8_t address[static 16])
+ * ~~~
+ * If a header file may be included from C++, use this __static define instead.
+ *
+ * (Syntax introduced in C99 - `uint8_t address[16]` in a prototype was always
+ * equivalent to `uint8_t *address`, but the C99 addition of static tells the
+ * compiler that address is never NULL, and always points to at least 16
+ * elements. This adds no new type-checking, but the information could aid
+ * compiler optimisation, and it can serve as documentation).
+ */
+#ifdef __cplusplus
+#define __static
+#else
+#define __static static
+#endif
+
+#ifdef __GNUC__
+#define NS_GCC_VERSION (__GNUC__ * 10000 \
+                   + __GNUC_MINOR__ * 100 \
+                   + __GNUC_PATCHLEVEL__)
+#endif
+
+/** \brief Compile-time assertion
+ *
+ * C11 provides _Static_assert, as does GCC even in C99 mode (and
+ * as a freestanding implementation, we can't rely on <assert.h> to get
+ * the static_assert macro).
+ * C++11 provides static_assert as a keyword, as does G++ in C++0x mode.
+ *
+ * The assertion acts as a declaration that can be placed at file scope, in a
+ * code block (except after a label), or as a member of a struct/union. It
+ * produces a compiler error if "test" evaluates to 0.
+ *
+ * Note that this *includes* the required semicolon when defined, else it
+ * is totally empty, permitting use in structs. (If the user provided the `;`,
+ * it would leave an illegal stray `;` if unavailable).
+ */
+#ifdef __cplusplus
+# if __cplusplus >= 201103L || __cpp_static_assert >= 200410
+# define NS_STATIC_ASSERT(test, str) static_assert(test, str);
+# elif defined __GXX_EXPERIMENTAL_CXX0X__  && NS_GCC_VERSION >= 40300
+# define NS_STATIC_ASSERT(test, str) __extension__ static_assert(test, str);
+# else
+# define NS_STATIC_ASSERT(test, str)
+# endif
+#else /* C */
+# if __STDC_VERSION__ >= 201112L
+# define NS_STATIC_ASSERT(test, str) _Static_assert(test, str);
+# elif defined __GNUC__ && NS_GCC_VERSION >= 40600 && !defined __CC_ARM
+# ifdef _Static_assert
+    /*
+     * Some versions of glibc cdefs.h (which comes in via <stdint.h> above)
+     * attempt to define their own _Static_assert (if GCC < 4.6 or
+     * __STRICT_ANSI__) using an extern declaration, which doesn't work in a
+     * struct/union.
+     *
+     * For GCC >= 4.6 and __STRICT_ANSI__, we can do better - just use
+     * the built-in _Static_assert with __extension__. We have to do this, as
+     * ns_list.h needs to use it in a union. No way to get at it though, without
+     * overriding their define.
+     */
+#   undef _Static_assert
+#   define _Static_assert(x, y) __extension__ _Static_assert(x, y)
+# endif
+# define NS_STATIC_ASSERT(test, str) __extension__ _Static_assert(test, str);
+# else
+# define NS_STATIC_ASSERT(test, str)
+#endif
+#endif
+
+/** \brief Pragma to suppress warnings about unusual pointer values.
+ *
+ * Useful if using "poison" values.
+ */
+#ifdef __IAR_SYSTEMS_ICC__
+#define NS_FUNNY_INTPTR_OK      _Pragma("diag_suppress=Pe1053")
+#define NS_FUNNY_INTPTR_RESTORE _Pragma("diag_default=Pe1053")
+#else
+#define NS_FUNNY_INTPTR_OK
+#define NS_FUNNY_INTPTR_RESTORE
+#endif
+
+/** \brief Pragma to suppress warnings about always true/false comparisons
+ */
+#if defined __GNUC__ && NS_GCC_VERSION >= 40600 && !defined __CC_ARM
+#define NS_FUNNY_COMPARE_OK         _Pragma("GCC diagnostic push") \
+                                    _Pragma("GCC diagnostic ignored \"-Wtype-limits\"")
+#define NS_FUNNY_COMPARE_RESTORE    _Pragma("GCC diagnostic pop")
+#else
+#define NS_FUNNY_COMPARE_OK
+#define NS_FUNNY_COMPARE_RESTORE
+#endif
+
+/** \brief Pragma to suppress warnings arising from dummy definitions.
+ *
+ * Useful when you have function-like macros that returning constants
+ * in cut-down builds. Can be fairly cavalier about disabling as we
+ * do not expect every build to use this macro. Generic builds of
+ * components should ensure this is not included by only using it in
+ * a ifdef blocks providing dummy definitions.
+ */
+#ifdef __CC_ARM
+// statement is unreachable(111),  controlling expression is constant(236), expression has no effect(174),
+// function was declared but never referenced(177), variable was set but never used(550)
+#define NS_DUMMY_DEFINITIONS_OK _Pragma("diag_suppress=111,236,174,177,550")
+#elif defined __IAR_SYSTEMS_ICC__
+// controlling expression is constant
+#define NS_DUMMY_DEFINITIONS_OK _Pragma("diag_suppress=Pe236")
+#else
+#define NS_DUMMY_DEFINITIONS_OK
+#endif
+
+/** \brief Convert pointer to member to pointer to containing structure */
+#define NS_CONTAINER_OF(ptr, type, member) \
+    ((type *) ((char *) (ptr) - offsetof(type, member)))
+
+/*
+ * Inlining could cause problems when mixing with C++; provide a mechanism to
+ * disable it. This could also be turned off for other reasons (although
+ * this can usually be done through a compiler flag, eg -O0 on gcc).
+ */
+#ifndef __cplusplus
+#define NS_ALLOW_INLINING
+#endif
+
+/* There is inlining problem in GCC version 4.1.x and we know it works in 4.6.3 */
+#if defined __GNUC__ && NS_GCC_VERSION < 40600
+#undef NS_ALLOW_INLINING
+#endif
+
+/** \brief Mark a potentially-inlineable function.
+ *
+ * We follow C99 semantics, which requires precisely one external definition.
+ * To also allow inlining to be totally bypassed under control of
+ * NS_ALLOW_INLINING, code can be structured as per the example of ns_list:
+ *
+ * foo.h
+ * -----
+ * ~~~
+ *    NS_INLINE int my_func(int);
+ *
+ *    #if defined NS_ALLOW_INLINING || defined FOO_FN
+ *    #ifndef FOO_FN
+ *    #define FOO_FN NS_INLINE
+ *    #endif
+ *    FOO_FN int my_func(int a)
+ *    {
+ *        definition;
+ *    }
+ *    #endif
+ * ~~~
+ * foo.c
+ * -----
+ * ~~~
+ *    #define FOO_FN extern
+ *    #include "foo.h"
+ * ~~~
+ * Which generates:
+ * ~~~
+ *                 NS_ALLOW_INLINING set          NS_ALLOW_INLINING unset
+ *                 =====================          =======================
+ *                 Include foo.h                  Include foo.h
+ *                 -------------                  -------------
+ *                 inline int my_func(int);       int my_func(int);
+ *
+ *                 // inline definition
+ *                 inline int my_func(int a)
+ *                 {
+ *                     definition;
+ *                 }
+ *
+ *                 Compile foo.c                  Compile foo.c
+ *                 -------------                  -------------
+ *    (from .h)    inline int my_func(int);       int my_func(int);
+ *
+ *                 // external definition
+ *                 // because of no "inline"      // normal external definition
+ *                 extern int my_func(int a)      extern int my_func(int a)
+ *                 {                              {
+ *                     definition;                    definition;
+ *                 }                              }
+ * ~~~
+ *
+ * Note that even with inline keywords, whether the compiler inlines or not is
+ * up to it. For example, gcc at "-O0" will not inline at all, and will always
+ * call the real functions in foo.o, just as if NS_ALLOW_INLINING was unset.
+ * At "-O2", gcc could potentially inline everything, meaning that foo.o is not
+ * referenced at all.
+ *
+ * Alternatively, you could use "static inline", which gives every caller its
+ * own internal definition. This is compatible with C++ inlining (which expects
+ * the linker to eliminate duplicates), but in C it's less efficient if the code
+ * ends up non-inlined, and it's harder to breakpoint. I don't recommend it
+ * except for the most trivial functions (which could then probably be macros).
+ */
+#ifdef NS_ALLOW_INLINING
+#define NS_INLINE inline
+#else
+#define NS_INLINE
+#endif
+
+#if defined __SDCC_mcs51 || defined __ICC8051__ || defined __C51__
+
+/* The 8051 environments: SDCC (historic), IAR (current), Keil (future?) */
+
+#define NS_LARGE            __xdata
+#define NS_LARGE_PTR        __xdata
+#ifdef __ICC8051__
+#define NS_REENTRANT
+#define NS_REENTRANT_PREFIX __idata_reentrant
+#else
+#define NS_REENTRANT        __reentrant
+#define NS_REENTRANT_PREFIX
+#endif
+#define NS_NEAR_FUNC        __near_func
+
+#else
+
+/* "Normal" systems. Define it all away. */
+#define NS_LARGE
+#define NS_LARGE_PTR
+#define NS_REENTRANT
+#define NS_REENTRANT_PREFIX
+#define NS_NEAR_FUNC
+
+#endif
+
+/** \brief Scatter-gather descriptor
+ *
+ * Slightly optimised for small platforms - we assume we won't need any
+ * element bigger than 64K.
+ */
+typedef struct ns_iovec {
+    void *iov_base;
+    uint_fast16_t iov_len;
+} ns_iovec_t;
+
+#endif /* NS_TYPES_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/nsdynmemLIB.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2014-2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+
+/**
+ * \file nsdynmemLIB.h
+ * \brief Dynamical Memory API for library model
+ * nsdynmemlib provides access to one default heap, along with the ability to use extra user heaps.
+ * ns_dyn_mem_alloc/free always access the default heap initialised by ns_dyn_mem_init.
+ * ns_mem_alloc/free access a user heap initialised by ns_mem_init. User heaps are identified by a book-keeping pointer.
+ */
+
+#ifndef NSDYNMEMLIB_H_
+#define NSDYNMEMLIB_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ns_types.h"
+
+// Added to maintain backward compatibility with older implementation of ns_dyn_mem APIs
+#define NSDYNMEMLIB_API_VERSION 2
+
+typedef uint16_t ns_mem_block_size_t; //external interface unsigned heap block size type
+typedef uint16_t ns_mem_heap_size_t; //total heap size type.
+
+/*!
+ * \enum heap_fail_t
+ * \brief Dynamically heap system failure call back event types.
+ */
+typedef enum {
+    NS_DYN_MEM_NULL_FREE,               /**< ns_dyn_mem_free(), NULL pointer free [obsolete - no longer faulted]  */
+    NS_DYN_MEM_DOUBLE_FREE,                     /**< ns_dyn_mem_free(), Possible double pointer free */
+    NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID, /**< Allocate size is 0 or smaller or size is bigger than max heap size  */
+    NS_DYN_MEM_POINTER_NOT_VALID,       /**< ns_dyn_mem_free(), try to free pointer which not at heap sector */
+    NS_DYN_MEM_HEAP_SECTOR_CORRUPTED,   /**< Heap system detect sector corruption */
+    NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED /**< ns_dyn_mem_free(), ns_dyn_mem_temporary_alloc() or ns_dyn_mem_alloc() called before ns_dyn_mem_init() */
+} heap_fail_t;
+
+/**
+ * /struct mem_stat_t
+ * /brief Struct for Memory stats Buffer structure
+ */
+typedef struct mem_stat_t {
+    /*Heap stats*/
+    ns_mem_heap_size_t heap_sector_size;                   /**< Heap total Sector len. */
+    ns_mem_heap_size_t heap_sector_alloc_cnt;              /**< Reserved Heap sector cnt. */
+    ns_mem_heap_size_t heap_sector_allocated_bytes;        /**< Reserved Heap data in bytes. */
+    ns_mem_heap_size_t heap_sector_allocated_bytes_max;    /**< Reserved Heap data in bytes max value. */
+    uint32_t heap_alloc_total_bytes;            /**< Total Heap allocated bytes. */
+    uint32_t heap_alloc_fail_cnt;               /**< Counter for Heap allocation fail. */
+} mem_stat_t;
+
+
+typedef struct ns_mem_book ns_mem_book_t;
+
+/**
+  * \brief Init and set Dynamical heap pointer and length.
+  *
+  * \param heap_ptr Pointer to dynamically heap buffer
+  * \param heap_size size of the heap buffer
+  * \return None
+  */
+extern void ns_dyn_mem_init(void *heap, ns_mem_heap_size_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr);
+
+
+/**
+  * \brief Free allocated memory.
+  *
+  * \param heap_ptr Pointer to allocated memory
+  *
+  * \return 0, Free OK
+  * \return <0, Free Fail
+  */
+extern void ns_dyn_mem_free(void *heap_ptr);
+/**
+  * \brief Allocate temporary data.
+  *
+  * Space allocate started from beginning of the heap sector
+  *
+  * \param alloc_size Allocated data size
+  *
+  * \return 0, Allocate Fail
+  * \return >0, Pointer to allocated data sector.
+  */
+extern void *ns_dyn_mem_temporary_alloc(ns_mem_block_size_t alloc_size);
+/**
+  * \brief Allocate long period data.
+  *
+  * Space allocate started from end of the heap sector
+  *
+  * \param alloc_size Allocated data size
+  *
+  * \return 0, Allocate Fail
+  * \return >0, Pointer to allocated data sector.
+  */
+extern void *ns_dyn_mem_alloc(ns_mem_block_size_t alloc_size);
+
+/**
+  * \brief Get pointer to the current mem_stat_t set via ns_dyn_mem_init.
+  *
+  * Get pointer to the statistics information, if one is set during the
+  * initialization. This may be useful for statistics collection purposes.
+  *
+  * Note: the caller may not modify the returned structure.
+  *
+  * \return NULL, no mem_stat_t was given on initialization
+  * \return !=0, Pointer to mem_stat_t.
+  */
+extern const mem_stat_t *ns_dyn_mem_get_mem_stat(void);
+
+/**
+  * \brief Init and set Dynamical heap pointer and length.
+  *
+  * \param heap_ptr Pointer to dynamically heap buffer
+  * \param heap_size size of the heap buffer
+  * \return !=0, Pointer to ns_mem_book_t.
+  */
+extern ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr);
+
+/**
+  * \brief Free allocated memory.
+  *
+  * \param book Address of book keeping structure
+  * \param heap_ptr Pointer to allocated memory
+  *
+  * \return 0, Free OK
+  * \return <0, Free Fail
+  */
+extern void ns_mem_free(ns_mem_book_t *book, void *heap_ptr);
+/**
+  * \brief Allocate temporary data.
+  *
+  * Space allocate started from beginning of the heap sector
+  *
+  * \param book Address of book keeping structure
+  * \param alloc_size Allocated data size
+  *
+  * \return 0, Allocate Fail
+  * \return >0, Pointer to allocated data sector.
+  */
+extern void *ns_mem_temporary_alloc(ns_mem_book_t *book, ns_mem_block_size_t alloc_size);
+/**
+  * \brief Allocate long period data.
+  *
+  * Space allocate started from end of the heap sector
+  *
+  * \param book Address of book keeping structure
+  * \param alloc_size Allocated data size
+  *
+  * \return 0, Allocate Fail
+  * \return >0, Pointer to allocated data sector.
+  */
+extern void *ns_mem_alloc(ns_mem_book_t *book, ns_mem_block_size_t alloc_size);
+
+/**
+  * \brief Get pointer to the current mem_stat_t set via ns_mem_init.
+  *
+  * Get pointer to the statistics information, if one is set during the
+  * initialization. This may be useful for statistics collection purposes.
+  *
+  * Note: the caller may not modify the returned structure.
+  *
+  * \param book Address of book keeping structure
+  *
+  * \return NULL, no mem_stat_t was given on initialization
+  * \return !=0, Pointer to mem_stat_t.
+  */
+extern const mem_stat_t *ns_mem_get_mem_stat(ns_mem_book_t *book);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* NSDYNMEMLIB_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/platform/arm_hal_interrupt.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#ifndef ARM_HAL_API_H_
+#define ARM_HAL_API_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <stdint.h>
+
+/**
+ * \brief This function disable global interrupts.
+ */
+extern void platform_enter_critical(void);
+/**
+ * \brief This function enable global interrupts.
+ */
+extern void platform_exit_critical(void);
+
+/**
+ * \brief This function increments the disable IRQ counter.
+ * The function must be called inside interrupt routines
+ * before any routine that uses platform_enter_critical()
+ * is called.
+ *
+ * This routine may not be need to do anything on some platforms,
+ * but requiring the call to be made before using
+ * platform_enter_critical() in an interrupt can simplify some
+ * implementations of platform_enter/exit_critical().
+ */
+extern void platform_interrupts_disabled(void);
+
+/**
+ * \brief This function decrements the disable IRQ counter.
+ */
+extern void platform_interrupts_enabling(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ARM_HAL_API_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/mbed-client-libservice/platform/arm_hal_nvm.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/*
+ * Nanostack NVM API.
+ *
+ * After NVM initialization (platform_nvm_init(...)) a user can:
+ * -create key to the NVM by using method platform_nvm_key_create(...)
+ * -write data to the NVM by using method platform_nvm_write(...)
+ * -read data from the NVM by using method platform_nvm_read(...)
+ * -delete the created key by using platform_nvm_key_delete(...)
+ * -store changed data to the underlying backing store by using method platform_nvm_flush(...).
+ *
+ * This NVM API is asynchronous. If API function returns PLATFORM_NVM_OK then provided callback function will be
+ * called once operation is completed. Callback function carries status parameter that indicates status of the
+ * operation. If platform API function returns error code then callback will not be called. A new operation can not
+ * be started until the previous operation has completed.
+ *
+ */
+
+#ifndef _PLATFORM_NVM_H_
+#define _PLATFORM_NVM_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Enumeration for nvm API function return values */
+typedef enum {
+    PLATFORM_NVM_OK,
+    PLATFORM_NVM_KEY_NOT_FOUND,
+    PLATFORM_NVM_ERROR
+} platform_nvm_status;
+
+/** \brief Client registered API callback type.
+ *
+ * \param status operation completion status
+ * \param context client provided context that was used when requesting operation
+ */
+typedef void (nvm_callback)(platform_nvm_status status, void *context);
+
+/** \brief Initialize NVM. Allocates module static resources and initializes underlying NMV.
+ *
+ * \param callback callback function that will be called once initialization is completed.
+ * \param context A client registered context that will be supplied as an argument to the callback when called.
+ *
+ * \return NVM_OK if initialization is in progress and callback will be called.
+ * \return NVM_ERROR if initialization failed and callback will not be called.
+  */
+platform_nvm_status platform_nvm_init(nvm_callback *callback, void *context);
+
+/** \brief Free resources reserved by NVM init.
+ *
+ * \param callback callback function that will be called once deinitialization is completed.
+ * \param context A client registered context that will be supplied as an argument to the callback when called.
+ *
+ * \return NVM_OK if initialization is in progress and callback will be called.
+ * \return NVM_ERROR if initialization failed and callback will not be called.
+  */
+platform_nvm_status platform_nvm_finalize(nvm_callback *callback, void *context);
+
+/** \brief Create key to the NMV. If the key exists then the key will be recreated with new length.
+ *
+ * \param callback callback function that will be called once key creation is finished
+ * \param key_name name of the key to be created
+ * \param value_len length of data reserved for the key
+ * \param flags reserved for future use
+ * \param context A client registered context that will be supplied as an argument to the callback when called
+ *
+ * \return NVM_OK if key creation is in progress and callback will be called.
+ * \return NVM_ERROR if key creation failed and callback will not be called.
+ * \return Provided callback function will be called once operation is completed.
+ */
+platform_nvm_status platform_nvm_key_create(nvm_callback *callback, const char *key_name, uint16_t value_len, uint32_t flags, void *context);
+
+/** \brief Delete key from NMV.
+ *
+ * \param callback callback function that will be called once key creation is finished
+ * \param key_name name of the key to be deleted
+ * \param context A client registered context that will be supplied as an argument to the callback when called
+ *
+ * \return NVM_OK if key creation is in progress and callback will be called.
+ * \return NVM_ERROR if key creation failed and callback will not be called.
+ * \return Provided callback function will be called once operation is completed.
+ */
+platform_nvm_status platform_nvm_key_delete(nvm_callback *callback, const char *key_name, void *context);
+
+/** \brief Write data to the NVM. Data will be truncated if the key does not have enough space for the data.
+ *
+ * \param callback callback function that will be called once writing is complete
+ * \param key_name name of the key where data will be written
+ * \param data buffer to data to be write. Data must be valid until callback is called.
+ * \param data_len [IN] length of data in bytes. [OUT] number of bytes written. Argument must be valid until a callback is called.
+ * \param context A client registered context that will be supplied as an argument to the callback when called.
+ *
+ * \return NVM_OK if data writing is in progress and callback will be called.
+ * \return NVM_ERROR if data writing failed and callback will not be called.
+ * \return Provided callback function will be called once operation is completed.
+ */
+platform_nvm_status platform_nvm_write(nvm_callback *callback, const char *key_name, const void *data, uint16_t *data_len, void *context);
+
+/** \brief Read key value from the NVM.
+ *
+ * \param callback callback function that will be called once reading is complete
+ * \param key_name name of the key whose data will be read
+ * \param buf buffer where data will be copied. Argument must be valid until a callback is called.
+ * \param buf_len [IN] provided buffer length in bytes. [OUT] bytes read. Argument must be valid until callback is called.
+ * \param context A client registered context that will be supplied as an argument to the callback when called.
+ *
+ * \return NVM_OK if data reading is in progress and callback will be called.
+ * \return NVM_ERROR if data reading failed and callback will not be called.
+ * \return Provided callback function will be called once operation is completed.
+ */
+platform_nvm_status platform_nvm_read(nvm_callback *callback, const char *key_name, void *buf, uint16_t *buf_len, void *context);
+
+/** \brief Store changed data to the backing store. This operation will write changed data to SRAM/Flash.
+ *
+ * \param callback callback function that will be called once flushing is complete
+ * \param context A client registered context that will be supplied as an argument to the callback when called.
+ *
+ * \return NVM_OK if data flushing is in progress and callback will be called.
+ * \return NVM_ERROR if data flushing failed and callback will not be called.
+ * \return Provided callback function will be called once operation is completed.
+ */
+platform_nvm_status platform_nvm_flush(nvm_callback *callback, void *context);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _PLATFORM_NVM_H_ */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/IPv6_fcf_lib/ip_fsc.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "stdint.h"
+#include "ip_fsc.h"
+
+/** \brief Compute IP checksum for arbitary data
+ *
+ * Compute an IP checksum, given a arbitrary gather list.
+ *
+ * See ipv6_fcf for discussion of use.
+ *
+ * This will work for any arbitrary gather list - it can handle odd
+ * alignments. The one limitation is that the 32-bit accumulator limits
+ * it to basically 64K of total data.
+ */
+uint16_t ip_fcf_v(uint_fast8_t count, const ns_iovec_t vec[static count])
+{
+    uint_fast32_t acc32 = 0;
+    bool odd = false;
+    while (count) {
+        const uint8_t *data_ptr = vec->iov_base;
+        uint_fast16_t data_length = vec->iov_len;
+        if (odd && data_length > 0) {
+            acc32 += *data_ptr++;
+            data_length--;
+            odd = false;
+        }
+        while (data_length >= 2) {
+            acc32 += (uint_fast16_t) data_ptr[0] << 8 | data_ptr[1];
+            data_ptr += 2;
+            data_length -= 2;
+        }
+        if (data_length) {
+            acc32 += (uint_fast16_t) data_ptr[0] << 8;
+            odd = true;
+        }
+        vec++;
+        count--;
+    }
+
+    // Fold down up to 0xffff carries in the 32-bit accumulator
+    acc32 = (acc32 >> 16) + (acc32 & 0xffff);
+
+    // Could be one more carry from the previous addition (result <= 0x1fffe)
+    uint16_t sum16 = (uint16_t)((acc32 >> 16) + (acc32 & 0xffff));
+    return ~sum16;
+}
+
+/** \brief Compute IPv6 checksum
+ *
+ * Compute an IPv6 checksum, given fields of an IPv6 pseudoheader and payload.
+ *
+ * This returns the 1's-complement of the checksum, as required when
+ * generating the checksum for transmission. The result can be 0x0000;
+ * for UDP (only) this must be transformed to 0xFFFF to distinguish from
+ * a packet with no checksum.
+ *
+ * To check a packet, this function will return 0 when run on a
+ * packet with a valid checksum. Checksums should be checked like this rather
+ * than setting the checksum field to zero and comparing generated checksum with
+ * the original value - this would fail in the case the received packet had
+ * checksum 0xFFFF.
+ */
+uint16_t ipv6_fcf(const uint8_t src_address[static 16], const uint8_t dest_address[static 16],
+                  uint16_t data_length, const uint8_t data_ptr[static data_length],  uint8_t next_protocol)
+{
+    // Use gather vector to lay out IPv6 pseudo-header (RFC 2460) and data
+    uint8_t hdr_data[] = { data_length >> 8, data_length, 0, next_protocol };
+    ns_iovec_t vec[4] = {
+        { (void *) src_address, 16 },
+        { (void *) dest_address, 16 },
+        { hdr_data, 4 },
+        { (void *) data_ptr, data_length }
+    };
+
+    return ip_fcf_v(4, vec);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/libBits/common_functions.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/*
+ * Most functions can be inlined, and definitions are in common_functions.h.
+ * Define COMMON_FUNCTIONS_FN before including it to generate external definitions.
+ */
+#define COMMON_FUNCTIONS_FN extern
+
+#include "common_functions.h"
+
+#include <string.h>
+
+/* Returns mask for <split_value> (0-8) most-significant bits of a byte */
+static inline uint8_t context_split_mask(uint_fast8_t split_value)
+{
+    return (uint8_t) - (0x100u >> split_value);
+}
+
+bool bitsequal(const uint8_t *a, const uint8_t *b, uint_fast8_t bits)
+{
+    uint_fast8_t bytes = bits / 8;
+    bits %= 8;
+
+    if (memcmp(a, b, bytes)) {
+        return false;
+    }
+
+    if (bits) {
+        uint_fast8_t split_bit = context_split_mask(bits);
+        if ((a[bytes] & split_bit) != (b[bytes] & split_bit)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+uint8_t *bitcopy(uint8_t *restrict dst, const uint8_t *restrict src, uint_fast8_t bits)
+{
+    uint_fast8_t bytes = bits / 8;
+    bits %= 8;
+
+    if (bytes) {
+        dst = (uint8_t *) memcpy(dst, src, bytes) + bytes;
+        src += bytes;
+    }
+
+    if (bits) {
+        uint_fast8_t split_bit = context_split_mask(bits);
+        *dst = (*src & split_bit) | (*dst & ~ split_bit);
+    }
+
+    return dst;
+}
+
+uint8_t *bitcopy0(uint8_t *restrict dst, const uint8_t *restrict src, uint_fast8_t bits)
+{
+    uint_fast8_t bytes = bits / 8;
+    bits %= 8;
+
+    if (bytes) {
+        dst = (uint8_t *) memcpy(dst, src, bytes) + bytes;
+        src += bytes;
+    }
+
+    if (bits) {
+        uint_fast8_t split_bit = context_split_mask(bits);
+        *dst = (*src & split_bit);
+    }
+
+    return dst;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/libList/ns_list.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+/*
+ * All functions can be inlined, and definitions are in ns_list.h.
+ * Define NS_LIST_FN before including it to generate external definitions.
+ */
+#define NS_LIST_FN extern
+
+#include "ns_list.h"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/libip6string/ip6tos.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include <stdio.h>
+#include <string.h>
+#include "common_functions.h"
+#include "ip6string.h"
+
+/**
+ * Print binary IPv6 address to a string.
+ * String must contain enough room for full address, 40 bytes exact.
+ * IPv4 tunneling addresses are not covered.
+ * \param addr IPv6 address.
+ * \p buffer to write string to.
+ */
+uint_fast8_t ip6tos(const void *ip6addr, char *p)
+{
+    char *p_orig = p;
+    uint_fast8_t zero_start = 255, zero_len = 1;
+    const uint8_t *addr = ip6addr;
+    uint_fast16_t part;
+
+    /* Follow RFC 5952 - pre-scan for longest run of zeros */
+    for (uint_fast8_t n = 0; n < 8; n++) {
+        part = *addr++;
+        part = (part << 8) | *addr++;
+        if (part != 0) {
+            continue;
+        }
+
+        /* We're at the start of a run of zeros - scan to non-zero (or end) */
+        uint_fast8_t n0 = n;
+        for (n = n0 + 1; n < 8; n++) {
+            part = *addr++;
+            part = (part << 8) | *addr++;
+            if (part != 0) {
+                break;
+            }
+        }
+
+        /* Now n0->initial zero of run, n->after final zero in run. Is this the
+         * longest run yet? If equal, we stick with the previous one - RFC 5952
+         * S4.2.3. Note that zero_len being initialised to 1 stops us
+         * shortening a 1-part run (S4.2.2.)
+         */
+        if (n - n0 > zero_len) {
+            zero_start = n0;
+            zero_len = n - n0;
+        }
+
+        /* Continue scan for initial zeros from part n+1 - we've already
+         * consumed part n, and know it's non-zero. */
+    }
+
+    /* Now go back and print, jumping over any zero run */
+    addr = ip6addr;
+    for (uint_fast8_t n = 0; n < 8;) {
+        if (n == zero_start) {
+            if (n == 0) {
+                *p++ = ':';
+            }
+            *p++ = ':';
+            addr += 2 * zero_len;
+            n += zero_len;
+            continue;
+        }
+
+        part = *addr++;
+        part = (part << 8) | *addr++;
+        n++;
+
+        p += sprintf(p, "%"PRIxFAST16, part);
+
+        /* One iteration writes "part:" rather than ":part", and has the
+         * explicit check for n == 8 below, to allow easy extension for
+         * IPv4-in-IPv6-type addresses ("xxxx::xxxx:a.b.c.d"): we'd just
+         * run the same loop for 6 parts, and output would then finish with the
+         * required : or ::, ready for "a.b.c.d" to be tacked on.
+         */
+        if (n != 8) {
+            *p++ = ':';
+        }
+    }
+    *p = '\0';
+
+    // Return length of generated string, excluding the terminating null character
+    return p - p_orig;
+}
+
+uint_fast8_t ip6_prefix_tos(const void *prefix, uint_fast8_t prefix_len, char *p)
+{
+    char *wptr = p;
+    uint8_t addr[16] = {0};
+
+    if (prefix_len > 128) {
+        return 0;
+    }
+
+    // Generate prefix part of the string
+    bitcopy(addr, prefix, prefix_len);
+    wptr += ip6tos(addr, wptr);
+    // Add the prefix length part of the string
+    wptr += sprintf(wptr, "/%"PRIuFAST8, prefix_len);
+
+    // Return total length of generated string
+    return wptr - p;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/libip6string/stoip6.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "common_functions.h"
+#include "ip6string.h"
+
+static uint16_t hex(const char *p);
+
+/**
+ * Convert numeric IPv6 address string to a binary.
+ * IPv4 tunnelling addresses are not covered.
+ * \param ip6addr IPv6 address in string format.
+ * \param len Length of ipv6 string.
+ * \param dest buffer for address. MUST be 16 bytes.
+ */
+void stoip6(const char *ip6addr, size_t len, void *dest)
+{
+    uint8_t *addr;
+    const char *p, *q;
+    int_fast8_t field_no, coloncolon = -1;
+
+    addr = dest;
+
+    if (len > 39) { // Too long, not possible. We do not support IPv4-mapped IPv6 addresses
+        return;
+    }
+
+    // First go forward the string, until end, noting :: position if any
+    for (field_no = 0, p = ip6addr; (len > (size_t)(p - ip6addr)) && *p && field_no < 8; p = q + 1) {
+        q = p;
+        // Seek for ':' or end
+        while (*q && (*q != ':')) {
+            q++;
+        }
+        //Convert and write this part, (high-endian AKA network byte order)
+        addr = common_write_16_bit(hex(p), addr);
+        field_no++;
+        //Check if we reached "::"
+        if ((len > (size_t)(q - ip6addr)) && *q && (q[0] == ':') && (q[1] == ':')) {
+            coloncolon = field_no;
+            q++;
+        }
+    }
+
+    if (coloncolon != -1) {
+        /* Insert zeros in the appropriate place */
+        uint_fast8_t head_size = 2 * coloncolon;
+        uint_fast8_t inserted_size = 2 * (8 - field_no);
+        uint_fast8_t tail_size = 16 - head_size - inserted_size;
+        addr = dest;
+        memmove(addr + head_size + inserted_size, addr + head_size, tail_size);
+        memset(addr + head_size, 0, inserted_size);
+    } else if (field_no != 8) {
+        /* Should really report an error if we didn't get 8 fields */
+        memset(addr, 0, 16 - field_no * 2);
+    }
+}
+unsigned char  sipv6_prefixlength(const char *ip6addr)
+{
+    char *ptr = strchr(ip6addr, '/');
+    if (ptr) {
+        return (unsigned char)strtoul(ptr + 1, 0, 10);
+    }
+    return 0;
+}
+static uint16_t hex(const char *p)
+{
+    uint16_t val = 0;
+
+    for (;;) {
+        char c = *p++;
+        if ((c >= '0') && (c <= '9')) {
+            val = (val << 4) | (c - '0');
+        } else if ((c >= 'A') && (c <= 'F')) {
+            val = (val << 4) | (10 + (c - 'A'));
+        } else if ((c >= 'a') && (c <= 'f')) {
+            val = (val << 4) | (10 + (c - 'a'));
+        } else {
+            break; // Non hex character
+        }
+    }
+    return val;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/nsdynmemLIB/nsdynmemLIB.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include <stdint.h>
+#include <string.h>
+#include "nsdynmemLIB.h"
+#include "platform/arm_hal_interrupt.h"
+#include <stdlib.h>
+#include "ns_list.h"
+
+#ifndef STANDARD_MALLOC
+typedef enum mem_stat_update_t {
+    DEV_HEAP_ALLOC_OK,
+    DEV_HEAP_ALLOC_FAIL,
+    DEV_HEAP_FREE,
+} mem_stat_update_t;
+
+typedef struct {
+    ns_list_link_t link;
+} hole_t;
+
+typedef int ns_mem_word_size_t; // internal signed heap block size type
+
+/* struct for book keeping variables */
+struct ns_mem_book {
+    ns_mem_word_size_t     *heap_main;
+    ns_mem_word_size_t     *heap_main_end;
+    mem_stat_t *mem_stat_info_ptr;
+    void (*heap_failure_callback)(heap_fail_t);
+    NS_LIST_HEAD(hole_t, link) holes_list;
+    ns_mem_heap_size_t heap_size;
+};
+
+static ns_mem_book_t *default_book; // heap pointer for original "ns_" API use
+
+// size of a hole_t in our word units
+#define HOLE_T_SIZE ((ns_mem_word_size_t) ((sizeof(hole_t) + sizeof(ns_mem_word_size_t) - 1) / sizeof(ns_mem_word_size_t)))
+
+static NS_INLINE hole_t *hole_from_block_start(ns_mem_word_size_t *start)
+{
+    return (hole_t *)(start + 1);
+}
+
+static NS_INLINE ns_mem_word_size_t *block_start_from_hole(hole_t *start)
+{
+    return ((ns_mem_word_size_t *)start) - 1;
+}
+
+static void heap_failure(ns_mem_book_t *book, heap_fail_t reason)
+{
+    if (book->heap_failure_callback) {
+        book->heap_failure_callback(reason);
+    }
+}
+
+#endif
+
+void ns_dyn_mem_init(void *heap, ns_mem_heap_size_t h_size,
+                     void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr)
+{
+    default_book = ns_mem_init(heap, h_size, passed_fptr, info_ptr);
+}
+
+const mem_stat_t *ns_dyn_mem_get_mem_stat(void)
+{
+#ifndef STANDARD_MALLOC
+    return ns_mem_get_mem_stat(default_book);
+#else
+    return NULL;
+#endif
+}
+
+
+ns_mem_book_t *ns_mem_init(void *heap, ns_mem_heap_size_t h_size,
+                         void (*passed_fptr)(heap_fail_t),
+                                      mem_stat_t *info_ptr)
+{
+#ifndef STANDARD_MALLOC
+    ns_mem_book_t *book;
+
+    ns_mem_word_size_t *ptr;
+    ns_mem_word_size_t temp_int;
+    /* Do memory alignment */
+    temp_int = ((uintptr_t)heap % sizeof(ns_mem_word_size_t));
+    if (temp_int) {
+        heap = (uint8_t *) heap + (sizeof(ns_mem_word_size_t) - temp_int);
+        h_size -= (sizeof(ns_mem_word_size_t) - temp_int);
+    }
+
+    /* Make correction for total length also */
+    temp_int = (h_size % sizeof(ns_mem_word_size_t));
+    if (temp_int) {
+        h_size -= (sizeof(ns_mem_word_size_t) - temp_int);
+    }
+    book = heap;
+    book->heap_main = (ns_mem_word_size_t *)&(book[1]); // SET Heap Pointer
+    book->heap_size = h_size - sizeof(ns_mem_book_t); //Set Heap Size
+    temp_int = (book->heap_size / sizeof(ns_mem_word_size_t));
+    temp_int -= 2;
+    ptr = book->heap_main;
+    *ptr = -(temp_int);
+    ptr += (temp_int + 1);
+    *ptr = -(temp_int);
+    book->heap_main_end = ptr;
+
+    ns_list_init(&book->holes_list);
+    ns_list_add_to_start(&book->holes_list, hole_from_block_start(book->heap_main));
+
+    book->mem_stat_info_ptr = info_ptr;
+    //RESET Memory by Hea Len
+    if (info_ptr) {
+        memset(book->mem_stat_info_ptr, 0, sizeof(mem_stat_t));
+        book->mem_stat_info_ptr->heap_sector_size = book->heap_size;
+    }
+#endif
+    //There really is no support to standard malloc in this library anymore
+    book->heap_failure_callback = passed_fptr;
+
+    return book;
+}
+
+const mem_stat_t *ns_mem_get_mem_stat(ns_mem_book_t *heap)
+{
+#ifndef STANDARD_MALLOC
+    return heap->mem_stat_info_ptr;
+#else
+    return NULL;
+#endif
+}
+
+#ifndef STANDARD_MALLOC
+static void dev_stat_update(mem_stat_t *mem_stat_info_ptr, mem_stat_update_t type, ns_mem_block_size_t size)
+{
+    if (mem_stat_info_ptr) {
+        switch (type) {
+            case DEV_HEAP_ALLOC_OK:
+                mem_stat_info_ptr->heap_sector_alloc_cnt++;
+                mem_stat_info_ptr->heap_sector_allocated_bytes += size;
+                if (mem_stat_info_ptr->heap_sector_allocated_bytes_max < mem_stat_info_ptr->heap_sector_allocated_bytes) {
+                    mem_stat_info_ptr->heap_sector_allocated_bytes_max = mem_stat_info_ptr->heap_sector_allocated_bytes;
+                }
+                mem_stat_info_ptr->heap_alloc_total_bytes += size;
+                break;
+            case DEV_HEAP_ALLOC_FAIL:
+                mem_stat_info_ptr->heap_alloc_fail_cnt++;
+                break;
+            case DEV_HEAP_FREE:
+                mem_stat_info_ptr->heap_sector_alloc_cnt--;
+                mem_stat_info_ptr->heap_sector_allocated_bytes -= size;
+                break;
+        }
+    }
+}
+
+static ns_mem_word_size_t convert_allocation_size(ns_mem_book_t *book, ns_mem_block_size_t requested_bytes)
+{
+    if (book->heap_main == 0) {
+        heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED);
+    } else if (requested_bytes < 1) {
+        heap_failure(book, NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID);
+    } else if (requested_bytes > (book->heap_size - 2 * sizeof(ns_mem_word_size_t)) ) {
+        heap_failure(book, NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID);
+    }
+    return (requested_bytes + sizeof(ns_mem_word_size_t) - 1) / sizeof(ns_mem_word_size_t);
+}
+
+// Checks that block length indicators are valid
+// Block has format: Size of data area [1 word] | data area [abs(size) words]| Size of data area [1 word]
+// If Size is negative it means area is unallocated
+// For direction, use 1 for direction up and -1 for down
+static int8_t ns_mem_block_validate(ns_mem_word_size_t *block_start, int direction)
+{
+    int8_t ret_val = -1;
+    ns_mem_word_size_t *end = block_start;
+    ns_mem_word_size_t size_start = *end;
+    end += (1 + abs(size_start));
+    if (size_start != 0 && size_start == *end) {
+        ret_val = 0;
+    }
+    return ret_val;
+}
+#endif
+
+// For direction, use 1 for direction up and -1 for down
+static void *ns_mem_internal_alloc(ns_mem_book_t *book, const ns_mem_block_size_t alloc_size, int direction)
+{
+#ifndef STANDARD_MALLOC
+    if (!book) {
+        /* We can not do anything except return NULL because we can't find book
+           keeping block */
+        return NULL;
+    }
+
+    ns_mem_word_size_t *block_ptr = NULL;
+
+    platform_enter_critical();
+
+    ns_mem_word_size_t data_size = convert_allocation_size(book, alloc_size);
+    if (!data_size) {
+        goto done;
+    }
+
+    // ns_list_foreach, either forwards or backwards, result to ptr
+    for (hole_t *cur_hole = direction > 0 ? ns_list_get_first(&book->holes_list)
+                                          : ns_list_get_last(&book->holes_list);
+         cur_hole;
+         cur_hole = direction > 0 ? ns_list_get_next(&book->holes_list, cur_hole)
+                                  : ns_list_get_previous(&book->holes_list, cur_hole)
+        ) {
+        ns_mem_word_size_t *p = block_start_from_hole(cur_hole);
+        if (ns_mem_block_validate(p, direction) != 0 || *p >= 0) {
+            //Validation failed, or this supposed hole has positive (allocated) size
+            heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
+            break;
+        }
+        if (-*p >= data_size) {
+            // Found a big enough block
+            block_ptr = p;
+            break;
+        }
+    }
+
+    if (!block_ptr) {
+        goto done;
+    }
+
+    ns_mem_word_size_t block_data_size = -*block_ptr;
+    if (block_data_size >= (data_size + 2 + HOLE_T_SIZE)) {
+        ns_mem_word_size_t hole_size = block_data_size - data_size - 2;
+        ns_mem_word_size_t *hole_ptr;
+        //There is enough room for a new hole so create it first
+        if ( direction > 0 ) {
+            hole_ptr = block_ptr + 1 + data_size + 1;
+            // Hole will be left at end of area.
+            // Would like to just replace this block_ptr with new descriptor, but
+            // they could overlap, so ns_list_replace might fail
+            //ns_list_replace(&holes_list, block_ptr, hole_from_block_start(hole_ptr));
+            hole_t *before = ns_list_get_previous(&book->holes_list, hole_from_block_start(block_ptr));
+            ns_list_remove(&book->holes_list, hole_from_block_start(block_ptr));
+            if (before) {
+                ns_list_add_after(&book->holes_list, before, hole_from_block_start(hole_ptr));
+            } else {
+                ns_list_add_to_start(&book->holes_list, hole_from_block_start(hole_ptr));
+            }
+        } else {
+            hole_ptr = block_ptr;
+            // Hole remains at start of area - keep existing descriptor in place.
+            block_ptr += 1 + hole_size + 1;
+        }
+
+        hole_ptr[0] = -hole_size;
+        hole_ptr[1 + hole_size] = -hole_size;
+    } else {
+        // Not enough room for a left-over hole, so use the whole block
+        data_size = block_data_size;
+        ns_list_remove(&book->holes_list, hole_from_block_start(block_ptr));
+    }
+    block_ptr[0] = data_size;
+    block_ptr[1 + data_size] = data_size;
+
+ done:
+    if (book->mem_stat_info_ptr) {
+        if (block_ptr) {
+            //Update Allocate OK
+            dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_OK, (data_size + 2) * sizeof(ns_mem_word_size_t));
+
+        } else {
+            //Update Allocate Fail, second parameter is not used for stats
+            dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_ALLOC_FAIL, 0);
+        }
+    }
+    platform_exit_critical();
+
+    return block_ptr ? block_ptr + 1 : NULL;
+#else
+    void *retval = NULL;
+    if (alloc_size) {
+        platform_enter_critical();
+        retval = malloc(alloc_size);
+        platform_exit_critical();
+    }
+    return retval;
+#endif
+}
+
+void *ns_mem_alloc(ns_mem_book_t *heap, ns_mem_block_size_t alloc_size)
+{
+    return ns_mem_internal_alloc(heap, alloc_size, -1);
+}
+
+void *ns_mem_temporary_alloc(ns_mem_book_t *heap, ns_mem_block_size_t alloc_size)
+{
+    return ns_mem_internal_alloc(heap, alloc_size, 1);
+}
+
+void *ns_dyn_mem_alloc(ns_mem_block_size_t alloc_size)
+{
+    return ns_mem_alloc(default_book, alloc_size);
+}
+
+void *ns_dyn_mem_temporary_alloc(ns_mem_block_size_t alloc_size)
+{
+    return ns_mem_temporary_alloc(default_book, alloc_size);
+}
+
+#ifndef STANDARD_MALLOC
+static void ns_mem_free_and_merge_with_adjacent_blocks(ns_mem_book_t *book, ns_mem_word_size_t *cur_block, ns_mem_word_size_t data_size)
+{
+    // Theory of operation: Block is always in form | Len | Data | Len |
+    // So we need to check length of previous (if current not heap start)
+    // and next (if current not heap end) blocks. Negative length means
+    // free memory so we can merge freed block with those.
+
+    hole_t *existing_start = NULL;
+    hole_t *existing_end = NULL;
+    ns_mem_word_size_t *start = cur_block;
+    ns_mem_word_size_t *end = cur_block + data_size + 1;
+    //invalidate current block
+    *start = -data_size;
+    *end = -data_size;
+    ns_mem_word_size_t merged_data_size = data_size;
+
+    if (start != book->heap_main) {
+        if (*(start - 1) < 0) {
+            ns_mem_word_size_t *block_end = start - 1;
+            ns_mem_word_size_t block_size = 1 + (-*block_end) + 1;
+            merged_data_size += block_size;
+            start -= block_size;
+            if (*start != *block_end) {
+                heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
+            }
+            if (block_size >= 1 + HOLE_T_SIZE + 1) {
+                existing_start = hole_from_block_start(start);
+            }
+        }
+    }
+
+    if (end != book->heap_main_end) {
+        if (*(end + 1) < 0) {
+            ns_mem_word_size_t *block_start = end + 1;
+            ns_mem_word_size_t block_size = 1 + (-*block_start) + 1;
+            merged_data_size += block_size;
+            end += block_size;
+            if (*end != *block_start) {
+                heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
+            }
+            if (block_size >= 1 + HOLE_T_SIZE + 1) {
+                existing_end = hole_from_block_start(block_start);
+            }
+        }
+    }
+
+    hole_t *to_add = hole_from_block_start(start);
+    hole_t *before = NULL;
+    if (existing_end) {
+        // Extending hole described by "existing_end" downwards.
+        // Will replace with descriptor at bottom of merged block.
+        // (Can't use ns_list_replace, because of danger of overlap)
+        // Optimisation - note our position for insertion below.
+        before = ns_list_get_next(&book->holes_list, existing_end);
+        ns_list_remove(&book->holes_list, existing_end);
+    }
+    if (existing_start) {
+        // Extending hole described by "existing_start" upwards.
+        // No need to modify that descriptor - it remains at the bottom
+        // of the merged block to describe it.
+    } else {
+        // Didn't find adjacent descriptors, but may still
+        // be merging with small blocks without descriptors.
+        if ( merged_data_size >= HOLE_T_SIZE ) {
+            // Locate hole position in list, if we don't already know
+            // from merging with the block above.
+            if (!existing_end) {
+                ns_list_foreach(hole_t, ptr, &book->holes_list) {
+                    if (ptr > to_add) {
+                        before = ptr;
+                        break;
+                    }
+                }
+            }
+            if (before) {
+                ns_list_add_before(&book->holes_list, before, to_add);
+            } else {
+                ns_list_add_to_end(&book->holes_list, to_add);
+            }
+
+        }
+    }
+    *start = -merged_data_size;
+    *end = -merged_data_size;
+}
+#endif
+
+void ns_mem_free(ns_mem_book_t *book, void *block)
+{
+#ifndef STANDARD_MALLOC
+
+    if (!block) {
+        return;
+    }
+
+    ns_mem_word_size_t *ptr = block;
+    ns_mem_word_size_t size;
+
+    platform_enter_critical();
+    ptr --;
+    //Read Current Size
+    size = *ptr;
+    if (ptr < book->heap_main || ptr >= book->heap_main_end) {
+        heap_failure(book, NS_DYN_MEM_POINTER_NOT_VALID);
+    } else if ((ptr + size) >= book->heap_main_end) {
+        heap_failure(book, NS_DYN_MEM_POINTER_NOT_VALID);
+    } else if (size < 0) {
+        heap_failure(book, NS_DYN_MEM_DOUBLE_FREE);
+    } else {
+        if (ns_mem_block_validate(ptr, 1) != 0) {
+            heap_failure(book, NS_DYN_MEM_HEAP_SECTOR_CORRUPTED);
+        } else {
+            ns_mem_free_and_merge_with_adjacent_blocks(book, ptr, size);
+            if (book->mem_stat_info_ptr) {
+                //Update Free Counter
+                dev_stat_update(book->mem_stat_info_ptr, DEV_HEAP_FREE, (size + 2) * sizeof(ns_mem_word_size_t));
+            }
+        }
+    }
+    platform_exit_critical();
+#else
+    platform_enter_critical();
+    free(block);
+    platform_exit_critical();
+#endif
+}
+
+void ns_dyn_mem_free(void *block)
+{
+    ns_mem_free(default_book, block);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/nanostack-libservice/source/nvmHelper/ns_nvm_helper.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,229 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include <string.h>
+#include <ns_types.h>
+#include <nsdynmemLIB.h>
+#include "ns_list.h"
+#include "platform/arm_hal_nvm.h"
+#include "ns_nvm_helper.h"
+
+#define TRACE_GROUP "nnvm"
+
+/* NVM operations */
+#define NS_NVM_NONE         0x00
+#define NS_NVM_INIT         0x01
+#define NS_NVM_KEY_CREATE   0x02
+#define NS_NVM_KEY_READ     0x03
+#define NS_NVM_KEY_WRITE    0x04
+#define NS_NVM_FLUSH        0x05
+#define NS_NVM_KEY_DELETE   0x06
+
+typedef struct {
+    ns_nvm_callback *callback;
+    const char *client_key_name;
+    void *client_context;
+    int operation;
+    uint8_t *buffer;
+    uint16_t *buffer_len;
+    void *original_request;
+    ns_list_link_t link;
+} ns_nvm_request_t;
+
+static bool ns_nvm_initialized = false;
+static bool ns_nvm_operation_in_progress = false;
+
+static ns_nvm_request_t *ns_nvm_create_request(ns_nvm_callback *callback, void *context, const char *key_name, uint8_t *buf, uint16_t *buf_len, uint8_t operation);
+static int ns_nvm_operation_start(ns_nvm_request_t *request);
+static int ns_nvm_operation_continue(ns_nvm_request_t *request, bool free_request);
+static void ns_nvm_operation_end(ns_nvm_request_t *ns_nvm_request_ptr, int client_retval);
+
+static NS_LIST_DEFINE(ns_nvm_request_list, ns_nvm_request_t, link);
+
+/*
+ * Callback from platform NVM adaptation
+ */
+void ns_nvm_callback_func(platform_nvm_status status, void *args)
+{
+    ns_nvm_request_t *ns_nvm_request_ptr = (ns_nvm_request_t*)args;
+    int client_retval = NS_NVM_OK;
+
+    if (status == PLATFORM_NVM_ERROR) {
+        client_retval = NS_NVM_ERROR;
+    } else if (status == PLATFORM_NVM_KEY_NOT_FOUND) {
+        client_retval = NS_NVM_DATA_NOT_FOUND;
+    }
+
+    switch(ns_nvm_request_ptr->operation) {
+        case NS_NVM_INIT:
+            ns_nvm_operation_continue(ns_nvm_request_ptr->original_request, true);
+            ns_dyn_mem_free(ns_nvm_request_ptr);
+            break;
+        case NS_NVM_FLUSH:
+        case NS_NVM_KEY_READ:
+            ns_nvm_operation_end(ns_nvm_request_ptr, client_retval);
+            break;
+        case NS_NVM_KEY_CREATE:
+            if (status == PLATFORM_NVM_OK) {
+                ns_nvm_request_ptr->operation = NS_NVM_KEY_WRITE;
+                platform_nvm_write(ns_nvm_callback_func, ns_nvm_request_ptr->client_key_name, ns_nvm_request_ptr->buffer, ns_nvm_request_ptr->buffer_len, ns_nvm_request_ptr);
+            } else {
+                ns_nvm_operation_end(ns_nvm_request_ptr, client_retval);
+            }
+            break;
+        case NS_NVM_KEY_DELETE:
+        case NS_NVM_KEY_WRITE:
+            if (status == PLATFORM_NVM_OK) {
+                // write ok, flush the changes
+                ns_nvm_request_ptr->operation = NS_NVM_FLUSH;
+                platform_nvm_flush(ns_nvm_callback_func, ns_nvm_request_ptr);
+            } else {
+                // write failed, inform client
+                ns_nvm_operation_end(ns_nvm_request_ptr, client_retval);
+            }
+            break;
+    }
+}
+
+int ns_nvm_key_delete(ns_nvm_callback *callback, const char *key_name, void *context)
+{
+    if (!callback || !key_name) {
+        return NS_NVM_ERROR;
+    }
+    ns_nvm_request_t *ns_nvm_request_ptr = ns_nvm_create_request(callback, context, key_name, NULL, NULL, NS_NVM_KEY_DELETE);
+    return ns_nvm_operation_start(ns_nvm_request_ptr);
+}
+
+int ns_nvm_data_read(ns_nvm_callback *callback, const char *key_name, uint8_t *buf, uint16_t *buf_len, void *context)
+{
+    if (!callback || !key_name || !buf || !buf_len) {
+        return NS_NVM_ERROR;
+    }
+    ns_nvm_request_t *ns_nvm_request_ptr = ns_nvm_create_request(callback, context, key_name, buf, buf_len, NS_NVM_KEY_READ);
+    return ns_nvm_operation_start(ns_nvm_request_ptr);
+}
+
+int ns_nvm_data_write(ns_nvm_callback *callback, const char *key_name, uint8_t *buf, uint16_t *buf_len, void *context)
+{
+    if (!callback || !key_name || !buf || !buf_len) {
+        return NS_NVM_ERROR;
+    }
+    ns_nvm_request_t *ns_nvm_request_ptr = ns_nvm_create_request(callback, context, key_name, buf, buf_len, NS_NVM_KEY_WRITE);
+    return ns_nvm_operation_start(ns_nvm_request_ptr);
+}
+
+static int ns_nvm_operation_start(ns_nvm_request_t *nvm_request)
+{
+    int ret = NS_NVM_OK;
+    platform_nvm_status pnvm_status;
+
+    if (!nvm_request) {
+        return NS_NVM_MEMORY;
+    }
+    if (ns_nvm_initialized == true) {
+        // NVM already initialized, continue directly
+        if (!ns_nvm_operation_in_progress) {
+            ret = ns_nvm_operation_continue(nvm_request, true);
+        } else {
+            // add request to list and handle when existing calls has been handled.
+            ns_list_add_to_end(&ns_nvm_request_list, nvm_request);
+        }
+    } else {
+        ns_nvm_request_t *ns_nvm_request_ptr = ns_nvm_create_request(NULL, NULL, NULL, NULL, NULL, NS_NVM_INIT);
+        if (!ns_nvm_request_ptr) {
+            ns_dyn_mem_free(nvm_request);
+            ns_dyn_mem_free(ns_nvm_request_ptr);
+            return NS_NVM_MEMORY;
+        }
+        ns_nvm_request_ptr->original_request = nvm_request;
+        pnvm_status = platform_nvm_init(ns_nvm_callback_func, ns_nvm_request_ptr);
+        if (pnvm_status != PLATFORM_NVM_OK) {
+            ns_dyn_mem_free(nvm_request);
+            ns_dyn_mem_free(ns_nvm_request_ptr);
+            return NS_NVM_ERROR;
+        }
+        ns_list_init(&ns_nvm_request_list);
+        ns_nvm_initialized = true;
+        ns_nvm_operation_in_progress = true;
+    }
+    return ret;
+}
+
+static ns_nvm_request_t *ns_nvm_create_request(ns_nvm_callback *callback, void *context, const char *key_name, uint8_t *buf, uint16_t *buf_len, uint8_t operation)
+{
+    ns_nvm_request_t *ns_nvm_request_ptr = ns_dyn_mem_temporary_alloc(sizeof(ns_nvm_request_t));
+    if (!ns_nvm_request_ptr) {
+        return NULL;
+    }
+    ns_nvm_request_ptr->client_context = context;
+    ns_nvm_request_ptr->callback = callback;
+    ns_nvm_request_ptr->client_key_name = key_name;
+    ns_nvm_request_ptr->operation = operation;
+    ns_nvm_request_ptr->buffer = buf;
+    ns_nvm_request_ptr->buffer_len = buf_len;
+
+    return ns_nvm_request_ptr;
+}
+
+static int ns_nvm_operation_continue(ns_nvm_request_t *request, bool free_request)
+{
+    platform_nvm_status ret = PLATFORM_NVM_OK;
+
+    ns_nvm_operation_in_progress = true;
+    switch(request->operation) {
+        case NS_NVM_KEY_WRITE:
+            request->operation = NS_NVM_KEY_CREATE;
+            ret = platform_nvm_key_create(ns_nvm_callback_func, request->client_key_name, *request->buffer_len, 0, request);
+            break;
+        case NS_NVM_KEY_READ:
+            ret = platform_nvm_read(ns_nvm_callback_func, request->client_key_name, request->buffer, request->buffer_len, request);
+            break;
+        case NS_NVM_KEY_DELETE:
+            ret = platform_nvm_key_delete(ns_nvm_callback_func, request->client_key_name, request);
+            break;
+    }
+
+    if (ret != PLATFORM_NVM_OK) {
+        if (free_request == true) {
+            // free request if requested
+            ns_dyn_mem_free(request);
+        }
+        ns_nvm_operation_in_progress = false;
+        return NS_NVM_ERROR;
+    }
+
+    return NS_NVM_OK;
+}
+
+static void ns_nvm_operation_end(ns_nvm_request_t *ns_nvm_request_ptr, int client_retval)
+{
+    ns_nvm_request_ptr->callback(client_retval, ns_nvm_request_ptr->client_context);
+    ns_dyn_mem_free(ns_nvm_request_ptr);
+    ns_nvm_operation_in_progress = false;
+
+    ns_list_foreach_safe(ns_nvm_request_t, pending_req, &ns_nvm_request_list) {
+        // there are pending requests to be processed
+        ns_list_remove(&ns_nvm_request_list, pending_req);
+        int ret = ns_nvm_operation_continue(pending_req, false);
+        if (ret != NS_NVM_OK) {
+            ns_nvm_operation_end(pending_req, ret);
+        } else {
+            break;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/arm_hal_interrupt.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,52 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "platform/arm_hal_interrupt.h"
+
+#include "arm_hal_interrupt_private.h"
+#include "pal.h"
+
+#include <assert.h>
+
+
+static uint8_t sys_irq_disable_counter;
+
+static palMutexID_t critical_mutex_id;
+
+void platform_critical_init(void)
+{
+    palStatus_t status;
+    status = pal_osMutexCreate(&critical_mutex_id);
+    assert(PAL_SUCCESS == status);
+}
+
+void platform_enter_critical(void)
+{
+    palStatus_t status;
+    status = pal_osMutexWait(critical_mutex_id, UINT32_MAX);
+    assert(PAL_SUCCESS == status);
+    sys_irq_disable_counter++;
+}
+
+void platform_exit_critical(void)
+{
+    palStatus_t status;
+    --sys_irq_disable_counter;
+    status = pal_osMutexRelease(critical_mutex_id);
+    assert(PAL_SUCCESS == status);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/arm_hal_interrupt_private.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,32 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_HAL_INTERRUPT_PRIVATE_H_
+#define ARM_HAL_INTERRUPT_PRIVATE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void platform_critical_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/arm_hal_random.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,36 @@
+// ----------------------------------------------------------------------------
+// Copyright 2015-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include <assert.h>
+#include "ns_types.h"
+#include "platform/arm_hal_random.h"
+#include "pal.h"
+
+void arm_random_module_init(void)
+{
+    palStatus_t status = pal_init();
+    assert(status == PAL_SUCCESS);
+}
+
+uint32_t arm_random_seed_get(void)
+{
+    uint32_t result = 0;
+    palStatus_t status = pal_osRandom32bit(&result);
+    assert(status == PAL_SUCCESS);
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/arm_hal_timer.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,92 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+// Include before mbed.h to properly get UINT*_C()
+#include "ns_types.h"
+
+#include "pal.h"
+#include "pal_rtos.h"
+
+#include "platform/arm_hal_timer.h"
+#include "platform/arm_hal_interrupt.h"
+
+#include <assert.h>
+
+// Low precision platform tick timer variables
+static void (*tick_timer_callback)(void);
+static palTimerID_t tick_timer_id;
+#define TICK_TIMER_ID   1
+
+void timer_callback(void const *funcArgument)
+{
+    (void)funcArgument;
+    if (tick_timer_callback != NULL) {
+        tick_timer_callback();
+    }
+}
+
+#ifdef MBED_CONF_NANOSTACK_EVENTLOOP_EXCLUDE_HIGHRES_TIMER
+extern "C" int8_t ns_timer_sleep(void);
+#endif
+
+// static method for creating the timer, called implicitly by platform_tick_timer_register if
+// timer was not enabled already
+static void tick_timer_create(void)
+{
+    palStatus_t status;
+    status = pal_init();
+    assert(PAL_SUCCESS == status);
+    status = pal_osTimerCreate(timer_callback, NULL, palOsTimerPeriodic, &tick_timer_id);
+    assert(PAL_SUCCESS == status);
+    
+}
+
+// Low precision platform tick timer
+int8_t platform_tick_timer_register(void (*tick_timer_cb_handler)(void))
+{
+    if (tick_timer_id == 0) {
+        tick_timer_create();
+    }
+    tick_timer_callback = tick_timer_cb_handler;
+    return TICK_TIMER_ID;
+}
+
+int8_t platform_tick_timer_start(uint32_t period_ms)
+{
+    int8_t retval = -1;
+    if ((tick_timer_id != 0) && (PAL_SUCCESS == pal_osTimerStart(tick_timer_id, period_ms))) {
+        retval = 0;
+    }
+    return retval;
+}
+
+int8_t platform_tick_timer_stop(void)
+{
+    int8_t retval = -1;
+    if ((tick_timer_id != 0) && (PAL_SUCCESS == pal_osTimerStop(tick_timer_id))) {
+        retval = 0;
+    }
+
+    // release PAL side resources
+    pal_osTimerDelete(&tick_timer_id);
+    pal_destroy();
+
+    return retval;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/mbed_lib.json	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,13 @@
+{
+    "name": "ns-hal-pal",
+    "config": {
+        "nvm_cfstore": {
+            "help": "Use cfstore as a NVM storage. Else RAM simulation will be used",
+            "value": false
+        },
+        "event_loop_thread_stack_size": {
+            "help": "Define event-loop thread stack size.",
+            "value": 6144
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/ns_event_loop.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,155 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "ns_event_loop.h"
+
+#include "pal.h"
+#include "ns_trace.h"
+
+#include "eventOS_scheduler.h"
+
+#include <assert.h>
+
+
+#define TRACE_GROUP "evlp"
+
+static void event_loop_thread(const void *arg);
+
+static palThreadID_t event_thread_id = 0;
+static palMutexID_t event_mutex_id = 0;
+static palSemaphoreID_t event_start_sema_id = 0;
+static palSemaphoreID_t event_signal_sema_id = 0;
+static palSemaphoreID_t event_stop_sema_id = 0;
+static volatile bool event_stop_loop;
+
+void eventOS_scheduler_mutex_wait(void)
+{
+    palStatus_t status;
+    status = pal_osMutexWait(event_mutex_id, UINT32_MAX);
+    assert(PAL_SUCCESS == status);
+}
+
+void eventOS_scheduler_mutex_release(void)
+{
+    palStatus_t status;
+    status = pal_osMutexRelease(event_mutex_id);
+    assert(PAL_SUCCESS == status);
+}
+
+void eventOS_scheduler_signal(void)
+{
+    palStatus_t status;
+    status = pal_osSemaphoreRelease(event_signal_sema_id);
+    assert(PAL_SUCCESS == status);
+}
+
+void eventOS_scheduler_idle(void)
+{
+    int32_t counters = 0;
+    palStatus_t status;
+
+    eventOS_scheduler_mutex_release();
+
+    status = pal_osSemaphoreWait(event_signal_sema_id, UINT32_MAX, &counters);
+    assert(PAL_SUCCESS == status);
+
+    eventOS_scheduler_mutex_wait();
+}
+
+static void event_loop_thread(const void *arg)
+{
+    int32_t counters = 0;
+    palStatus_t status;
+
+    tr_debug("event_loop_thread create");
+
+    event_stop_loop = false;
+
+    status = pal_osSemaphoreWait(event_start_sema_id, UINT32_MAX, &counters);
+    assert(PAL_SUCCESS == status);
+
+    // TODO: Delete start semaphore?
+    eventOS_scheduler_mutex_wait();
+    tr_debug("event_loop_thread loop start");
+
+    // A stoppable version of eventOS_scheduler_run(void)
+    while (event_stop_loop == false) {
+        if (!eventOS_scheduler_dispatch_event()) {
+            eventOS_scheduler_idle();
+        }
+    }
+    tr_debug("event_loop_thread loop end");
+
+    // cleanup the scheduler timer resources which are not needed anymore
+    eventOS_scheduler_timer_stop();
+
+    // signal the ns_event_loop_thread_stop() that it can continue 
+    status = pal_osSemaphoreRelease(event_stop_sema_id);
+    assert(PAL_SUCCESS == status);
+}
+
+void ns_event_loop_thread_create(void)
+{
+    int32_t counters = 0;
+    palStatus_t status;
+
+    status = pal_osSemaphoreCreate(1, &event_start_sema_id);
+    assert(PAL_SUCCESS == status);
+
+    status = pal_osSemaphoreWait(event_start_sema_id, UINT32_MAX, &counters);
+    assert(PAL_SUCCESS == status);
+
+    status = pal_osSemaphoreCreate(0, &event_stop_sema_id);
+    assert(PAL_SUCCESS == status);
+
+    status = pal_osSemaphoreCreate(1, &event_signal_sema_id);
+    assert(PAL_SUCCESS == status);
+
+    status = pal_osMutexCreate(&event_mutex_id);
+    assert(PAL_SUCCESS == status);
+
+    status = pal_osThreadCreateWithAlloc(event_loop_thread, NULL, PAL_osPriorityNormal, MBED_CONF_NS_HAL_PAL_EVENT_LOOP_THREAD_STACK_SIZE, NULL, &event_thread_id);
+    assert(PAL_SUCCESS == status);
+}
+
+void ns_event_loop_thread_start(void)
+{
+    palStatus_t status;
+    status = pal_osSemaphoreRelease(event_start_sema_id);
+    assert(PAL_SUCCESS == status);
+}
+
+void ns_event_loop_thread_stop(void)
+{
+    palStatus_t status;
+
+    // request loop to stop
+    event_stop_loop = true;
+
+    // Ping the even loop at least once more so it will notice the flag and
+    // hopefully end the loop soon.
+    eventOS_scheduler_signal();
+
+    // wait until the event loop has been stopped and the thread is shutting down.
+    // Note: the PAL API does not have any better means to join with a thread termination. 
+    status = pal_osSemaphoreWait(event_stop_sema_id, UINT32_MAX, NULL);
+    assert(PAL_SUCCESS == status);
+
+    pal_osSemaphoreDelete(&event_start_sema_id);
+    pal_osSemaphoreDelete(&event_stop_sema_id);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/ns_event_loop.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,36 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef NS_EVENT_LOOP_H_
+#define NS_EVENT_LOOP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void ns_event_loop_thread_create(void);
+void ns_event_loop_thread_start(void);
+
+// A extension to original event loop API, which is useful on Linux only
+void ns_event_loop_thread_stop(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NS_EVENT_LOOP_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/ns_hal_init.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,54 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "ns_hal_init.h"
+
+#include "ns_types.h"
+#include <stdlib.h>
+#include <assert.h>
+
+#include "arm_hal_interrupt_private.h"
+#include "ns_event_loop.h"
+#include "eventOS_scheduler.h"
+#include "platform/arm_hal_timer.h"
+#include "ns_trace.h"
+
+
+void ns_hal_init(void *heap, size_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr)
+{
+    static bool initted;
+    if (initted) {
+        return;
+    }
+    if (!heap) {
+        heap = malloc(h_size);
+        assert(heap);
+        if (!heap) {
+            return;
+        }
+    }
+    platform_critical_init();
+    ns_dyn_mem_init(heap, h_size, passed_fptr, info_ptr);
+    eventOS_scheduler_init();
+    // We do not initialise randlib, as it should be done after
+    // RF driver has started, to get MAC address and RF noise as seed.
+    // We do not initialise trace - left to application.
+    ns_event_loop_thread_create();
+    ns_event_loop_thread_start();
+    initted = true;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/ns-hal-pal/ns_hal_init.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,49 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef NS_HAL_INIT_H_
+#define NS_HAL_INIT_H_
+
+#include <stddef.h>
+#include "nsdynmemLIB.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Initialise core Nanostack HAL components.
+ *
+ * Calls after the first do nothing. So "major" users should make sure
+ * they call this first with a "large" heap size, before anyone
+ * requests a smaller one.
+ *
+ * Parameters are as for ns_dyn_mem_init (but note that nsdynmemlib
+ * currently limits heap size to 16-bit, so be wary of passing large
+ * sizes.
+ *
+ * If heap is NULL, h_size will be allocated from the malloc() heap,
+ * else the passed-in pointer will be used.
+ */
+void ns_hal_init(void *heap, size_t h_size, void (*passed_fptr)(heap_fail_t), mem_stat_t *info_ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NS_HAL_INIT_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+Unless specifically indicated otherwise in a file, files are licensed
+under the Apache 2.0 license, as can be found in: apache-2.0.txt
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/apache-2.0.txt	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,56 @@
+
+
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+    You must give any other recipients of the Work or Derivative Works a copy of this License; and
+    You must cause any modified files to carry prominent notices stating that You changed the files; and
+    You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+    If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+    You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/mbed_lib.json	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,13 @@
+{
+    "name": "nanostack-eventloop",
+    "config": {
+        "use_platform_tick_timer": {
+            "help": "Use platform provided low resolution tick timer for eventloop",
+            "value": null
+        },
+        "exclude_highres_timer": {
+            "help": "Exclude high resolution timer from build",
+            "value": null
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_callback_timer.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef EVENTOS_CALLBACK_TIMER_H_
+#define EVENTOS_CALLBACK_TIMER_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "ns_types.h"
+
+extern int8_t eventOS_callback_timer_register(void (*timer_interrupt_handler)(int8_t, uint16_t));
+extern int8_t eventOS_callback_timer_unregister(int8_t ns_timer_id);
+
+extern int8_t eventOS_callback_timer_stop(int8_t ns_timer_id);
+extern int8_t eventOS_callback_timer_start(int8_t ns_timer_id, uint16_t slots);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EVENTOS_CALLBACK_TIMER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_event.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef EVENTOS_EVENT_H_
+#define EVENTOS_EVENT_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "ns_types.h"
+#include "ns_list.h"
+
+/**
+ * \enum arm_library_event_priority_e
+ * \brief Event Priority level.
+ */
+typedef enum arm_library_event_priority_e {
+    ARM_LIB_HIGH_PRIORITY_EVENT = 0, /**< High Priority Event (Function CB) */
+    ARM_LIB_MED_PRIORITY_EVENT = 1, /**< Medium Priority (Timer) */
+    ARM_LIB_LOW_PRIORITY_EVENT = 2, /*!*< Normal Event and ECC / Security */
+} arm_library_event_priority_e;
+
+/**
+ * \struct arm_event_s
+ * \brief Event structure.
+ */
+typedef struct arm_event_s {
+    int8_t receiver; /**< Event handler Tasklet ID */
+    int8_t sender; /**< Event sender Tasklet ID */
+    uint8_t event_type; /**< This will be typecast arm_library_event_type_e, arm_internal_event_type_e or application specific define */
+    uint8_t event_id; /**< Timer ID, NWK interface ID or application specific ID */
+    void *data_ptr; /**< Application could share data pointer tasklet to tasklet */
+    arm_library_event_priority_e priority;
+    uint32_t event_data;
+} arm_event_t;
+
+/* Backwards compatibility */
+typedef arm_event_t arm_event_s;
+
+/**
+ * \struct arm_event_storage
+ * \brief Event structure storage, including list link.
+
+@startuml
+
+partition "Event loop" {
+(*) -->[event created] "UNQUEUED"
+"UNQUEUED" -->[event_core_write()] "QUEUED"
+"QUEUED" -->[event_core_read()] "RUNNING"
+"RUNNING" ->[event_core_free_push()] "UNQUEUED"
+}
+
+partition "system_timer.c" {
+    "UNQUEUED:timer" -->[eventOS_event_send_timer_allocated()] "QUEUED"
+}
+@enduml
+
+ */
+typedef struct arm_event_storage {
+    arm_event_s data;
+    enum {
+        ARM_LIB_EVENT_STARTUP_POOL,
+        ARM_LIB_EVENT_DYNAMIC,
+        ARM_LIB_EVENT_USER,
+        ARM_LIB_EVENT_TIMER,
+    } allocator;
+    enum {
+        ARM_LIB_EVENT_UNQUEUED,
+        ARM_LIB_EVENT_QUEUED,
+        ARM_LIB_EVENT_RUNNING,
+    } state;
+    ns_list_link_t link;
+} arm_event_storage_t;
+
+/**
+ * \brief Send event to event scheduler.
+ *
+ * \param event pointer to pushed event.
+ *
+ * Event data is copied by the call, and this copy persists until the
+ * recipient's callback function returns. The callback function is passed
+ * a pointer to a copy of the data, not the original pointer.
+ *
+ * \return 0 Event push OK
+ * \return -1 Memory allocation Fail
+ */
+extern int8_t eventOS_event_send(const arm_event_t *event);
+
+/* Alternate names for timer function from eventOS_event_timer.h;
+ * implementations may one day merge */
+#define eventOS_event_send_at(event, at)       eventOS_event_timer_request_at(event, at)
+#define eventOS_event_send_in(event, in)       eventOS_event_timer_request_in(event, in)
+#define eventOS_event_send_after(event, after) eventOS_event_timer_request_after(event, after)
+#define eventOS_event_send_every(event, every) eventOS_event_timer_request_every(event, every)
+
+/**
+ * \brief Send user-allocated event to event scheduler.
+ *
+ * \param event pointer to pushed event storage.
+ *
+ * The event structure is not copied by the call, the event system takes
+ * ownership and it is threaded directly into the event queue. This avoids the
+ * possibility of event sending failing due to memory exhaustion.
+ *
+ * event->data must be filled in on entry - the rest of the structure (link and
+ * allocator) need not be.
+ *
+ * The structure must remain valid until the recipient is called - the
+ * event system passes ownership to the receiving event handler, who may then
+ * invalidate it, or send it again.
+ *
+ * The recipient receives a pointer to the arm_event_t data member of the
+ * event - it can use NS_CONTAINER_OF() to get a pointer to the original
+ * event passed to this call, or to its outer container.
+ *
+ * It is a program error to send a user-allocated event to a non-existent task.
+ */
+extern void eventOS_event_send_user_allocated(arm_event_storage_t *event);
+
+/**
+ * \brief Event handler callback register
+ *
+ * Function will register and allocate unique event id handler
+ *
+ * \param handler_func_ptr function pointer for event handler
+ * \param init_event_type generated event type for init purpose
+ *
+ * \return >= 0 Unique event ID for this handler
+ * \return < 0 Register fail
+ *
+ * */
+extern int8_t eventOS_event_handler_create(void (*handler_func_ptr)(arm_event_t *), uint8_t init_event_type);
+
+/**
+ * Cancel an event.
+ *
+ * Queued events are removed from the event-loop queue and/or the timer queue.
+ *
+ * Passing a NULL pointer is allowed, and does nothing.
+ *
+ * Event pointers are valid from the time they are queued until the event
+ * has finished running or is cancelled.
+ *
+ * Cancelling a currently-running event is only useful to stop scheduling
+ * it if it is on a periodic timer; it has no other effect.
+ *
+ * Cancelling an already-cancelled or already-run single-shot event
+ * is undefined behaviour.
+ *
+ * \param event Pointer to event handle or NULL.
+ */
+extern void eventOS_cancel(arm_event_storage_t *event);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* EVENTOS_EVENT_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_event_timer.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef EVENTOS_EVENT_TIMER_H_
+#define EVENTOS_EVENT_TIMER_H_
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "ns_types.h"
+#include "eventOS_event.h"
+
+struct arm_event_s;
+typedef struct sys_timer_struct_s sys_timer_struct_t;
+
+/* 100 Hz ticker, so 10 milliseconds per tick */
+#define EVENTOS_EVENT_TIMER_HZ 100
+
+static inline uint32_t eventOS_event_timer_ticks_to_ms(uint32_t ticks)
+{
+    NS_STATIC_ASSERT(1000 % EVENTOS_EVENT_TIMER_HZ == 0, "Assuming whole number of ms per tick")
+    return ticks * (1000 / EVENTOS_EVENT_TIMER_HZ);
+}
+
+/* Convert ms to ticks, rounding up (so 9ms = 1 tick, 10ms = 1 tick, 11ms = 2 ticks) */
+static inline uint32_t eventOS_event_timer_ms_to_ticks(uint32_t ms)
+{
+    NS_STATIC_ASSERT(1000 % EVENTOS_EVENT_TIMER_HZ == 0, "Assuming whole number of ms per tick")
+    return (ms + (1000 / EVENTOS_EVENT_TIMER_HZ) - 1) / (1000 / EVENTOS_EVENT_TIMER_HZ);
+}
+
+/**
+ * Read current timer tick count.
+ *
+ * Can be used as a monotonic time source, and to schedule events with
+ * eventOS_event_timer_send.
+ *
+ * Note that the value will wrap, so take care on comparisons.
+ *
+ * \return tick count.
+ */
+extern uint32_t eventOS_event_timer_ticks(void);
+
+/* Comparison macros handling wrap efficiently (assuming a conventional compiler
+ * which converts 0x80000000 to 0xFFFFFFFF to negative when casting to int32_t).
+ */
+#define TICKS_AFTER(a, b) ((int32_t) ((a)-(b)) > 0)
+#define TICKS_BEFORE(a, b) ((int32_t) ((a)-(b)) < 0)
+#define TICKS_AFTER_OR_AT(a, b) ((int32_t) ((a)-(b)) >= 0)
+#define TICKS_BEFORE_OR_AT(a, b) ((int32_t) ((a)-(b)) <= 0)
+
+/**
+ * Send an event after time expired (in milliseconds)
+ *
+ * Note that the current implementation has the "feature" that rounding
+ * varies depending on the precise timing requested:
+ *     0-20 ms => 2 x 10ms tick
+ *    21-29 ms => 3 x 10ms tick
+ *    30-39 ms => 4 x 10ms tick
+ *    40-49 ms => 5 x 10ms tick
+ *    ... etc
+ *
+ * For improved flexibility on the event, and for more control of time,
+ * you should use eventOS_event_timer_request_at().
+ *
+ * \param event_id event_id for event
+ * \param event_type event_type for event
+ * \param tasklet_id receiver for event
+ * \param time time to sleep in milliseconds
+ *
+ * \return 0 on success
+ * \return -1 on error (invalid tasklet_id or allocation failure)
+ *
+ * */
+extern int8_t eventOS_event_timer_request(uint8_t event_id, uint8_t event_type, int8_t tasklet_id, uint32_t time);
+
+/**
+ * Send an event at specified time
+ *
+ * The event will be sent when eventOS_event_timer_ticks() reaches the
+ * specified value.
+ *
+ * If the specified time is in the past (ie "at" is before or at the current
+ * tick value), the event will be sent immediately.
+ *
+ * Can also be invoked using the eventOS_event_send_at() macro in eventOS_event.h
+ *
+ * \param event event to send
+ * \param at absolute tick time to run event at
+ *
+ * \return pointer to timer structure on success
+ * \return NULL on error (invalid tasklet_id or allocation failure)
+ *
+ */
+extern arm_event_storage_t *eventOS_event_timer_request_at(const struct arm_event_s *event, uint32_t at);
+
+/**
+ * Send an event in a specified time
+ *
+ * The event will be sent in the specified number of ticks - to
+ * be precise, it is equivalent to requesting an event at
+ *
+ *    eventOS_event_timer_ticks() + ticks
+ *
+ * Because of timer granularity, the elapsed time between issuing the request
+ * and it running may be up to 1 tick less than the specified time.
+ *
+ * eg requesting 2 ticks will cause the event to be sent on the second tick from
+ * now. If requested just after a tick, the delay will be nearly 2 ticks, but if
+ * requested just before a tick, the delay will be just over 1 tick.
+ *
+ * If `in` is <= 0, the event will be sent immediately.
+ *
+ * Can also be invoked using the eventOS_event_send_in() macro in eventOS_event.h
+ *
+ * \param event event to send
+ * \param in tick delay for event
+ *
+ * \return pointer to timer structure on success
+ * \return NULL on error (invalid tasklet_id or allocation failure)
+ *
+ */
+extern arm_event_storage_t *eventOS_event_timer_request_in(const struct arm_event_s *event, int32_t in);
+
+/**
+ * Send an event after a specified time
+ *
+ * The event will be sent after the specified number of ticks - to
+ * be precise, it is equivalent to requesting an event at
+ *
+ *    eventOS_event_timer_ticks() +  ticks + 1
+ *
+ * Because of timer granularity, the elapsed time between issuing the request
+ * and it running may be up to 1 tick more than the specified time.
+ *
+ * eg requesting 2 ticks will cause the event to be sent on the third tick from
+ * now. If requested just after a tick, the delay will be nearly 3 ticks, but if
+ * requested just before a tick, the delay will be just over 2 ticks.
+ *
+ * If `after` is < 0, the event will be sent immediately. If it is 0, the event
+ * is sent on the next tick.
+ *
+ * Can also be invoked using the eventOS_event_send_after() macro in eventOS_event.h
+ *
+ * \param event event to send
+ * \param after tick delay for event
+ *
+ * \return pointer to timer structure on success
+ * \return NULL on error (invalid tasklet_id or allocation failure)
+ *
+ */
+#define eventOS_event_timer_request_after(event, after) \
+    eventOS_event_timer_request_in(event, (after) + 1)
+
+/**
+ * Send an event periodically
+ *
+ * The event will be sent repeatedly using the specified ticks period.
+ *
+ * The first call is sent at
+ *
+ *          eventOS_event_timer_ticks() +  ticks
+ *
+ * Subsequent events will be sent at N*ticks from the initial time.
+ *
+ * Period will be maintained while the device is awake, regardless of delays to
+ * event scheduling. If an event has not been delivered and completed by the
+ * next scheduled time, the next event will be sent immediately when it
+ * finishes. This could cause a continuous stream of events if unable to keep
+ * up with the period.
+ *
+ * Can also be invoked using the eventOS_event_send_every() macro in eventOS_event.h
+ *
+ * \param event event to send
+ * \param period period for event
+ *
+ * \return pointer to timer structure on success
+ * \return NULL on error (invalid tasklet_id or allocation failure)
+ *
+ */
+extern arm_event_storage_t *eventOS_event_timer_request_every(const struct arm_event_s *event, int32_t period);
+
+/**
+ * Cancel an event timer
+ *
+ * This cancels a pending timed event, matched by event_id and tasklet_id.
+ *
+ * \param event_id event_id for event
+ * \param tasklet_id receiver for event
+ *
+ * \return 0 on success
+ * \return -1 on error (event not found)
+ *
+ * */
+extern int8_t eventOS_event_timer_cancel(uint8_t event_id, int8_t tasklet_id);
+
+/**
+ * System Timer shortest time in milli seconds
+ *
+ * \param ticks Time in 10 ms resolution
+ *
+ * \return none
+ *
+ * */
+extern uint32_t eventOS_event_timer_shortest_active_timer(void);
+
+
+/** Timeout structure. Not to be modified by user */
+typedef struct timeout_entry_t timeout_t;
+
+/** Request timeout callback.
+ *
+ * Create timeout request for specific callback.
+ *
+ * \param ms timeout in milliseconds. Maximum range is same as for eventOS_event_timer_request().
+ * \param callback function to call after timeout
+ * \param arg arquement to pass to callback
+ * \return pointer to timeout structure or NULL on errors
+ */
+timeout_t *eventOS_timeout_ms(void (*callback)(void *), uint32_t ms, void *arg);
+
+/** Request periodic callback.
+ *
+ * Create timeout request for specific callback. Called periodically until eventOS_timeout_cancel() is called.
+ *
+ * \param every period in milliseconds. Maximum range is same as for eventOS_event_timer_request().
+ * \param callback function to call after timeout
+ * \param arg arquement to pass to callback
+ * \return pointer to timeout structure or NULL on errors
+ */
+timeout_t *eventOS_timeout_every_ms(void (*callback)(void *), uint32_t every, void *arg);
+
+/** Cancell timeout request.
+ *
+ * \param t timeout request id.
+ */
+void eventOS_timeout_cancel(timeout_t *t);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EVENTOS_EVENT_TIMER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/nanostack-event-loop/eventOS_scheduler.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef EVENTOS_SCHEDULER_H_
+#define EVENTOS_SCHEDULER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "ns_types.h"
+
+/* Compatibility with older ns_types.h */
+#ifndef NS_NORETURN
+#define NS_NORETURN
+#endif
+
+/**
+ * \brief Initialise event scheduler.
+ *
+ */
+extern void eventOS_scheduler_init(void);
+
+/**
+ * Process one event from event queue.
+ * Do not call this directly from application. Requires to be public so that simulator can call this.
+ * Use eventOS_scheduler_run() or eventOS_scheduler_run_until_idle().
+ * \return true If there was event processed, false if the event queue was empty.
+ */
+bool eventOS_scheduler_dispatch_event(void);
+
+/**
+ * \brief Process events until no more events to process.
+ */
+extern void eventOS_scheduler_run_until_idle(void);
+
+/**
+ * \brief Start Event scheduler.
+ * Loops forever processing events from the queue.
+ * Calls eventOS_scheduler_idle() whenever event queue is empty.
+ */
+NS_NORETURN extern void eventOS_scheduler_run(void);
+/**
+ * \brief Disable Event scheduler Timers
+ *
+ * \return 0 Timer Stop OK
+ * \return -1 Timer Stop Fail
+ *
+ * */
+int eventOS_scheduler_timer_stop(void);
+
+/**
+ * \brief Synch Event scheduler timer after sleep
+ *
+ * \param sleep_ticks time in milli seconds
+ *
+ * \return 0 Timer Synch OK
+ * \return -1 Timer Synch & Start Fail
+ *
+ * */
+int eventOS_scheduler_timer_synch_after_sleep(uint32_t sleep_ticks);
+
+/**
+ * \brief Read current active Tasklet ID
+ *
+ * This function not return valid information called inside interrupt
+ *
+ * \return curret active tasklet id
+ *
+ * */
+extern int8_t eventOS_scheduler_get_active_tasklet(void);
+
+/**
+ * \brief Set manually Active Tasklet ID
+ *
+ * \param tasklet requested tasklet ID
+ *
+ * */
+extern  void eventOS_scheduler_set_active_tasklet(int8_t tasklet);
+
+/**
+ * \brief Event scheduler loop idle Callback.
+
+ * Note! This method is called only by eventOS_scheduler_run, needs to be
+ * ported for the platform only if you are using eventOS_scheduler_run().
+ */
+extern void eventOS_scheduler_idle(void);
+
+/**
+ * \brief This function will be called when stack enter idle state and start
+ *  waiting signal.
+ *
+ * Note! This method is called only by reference implementation of idle. Needs
+ * to be ported for the platform only if you are using reference implementation.
+ */
+extern void eventOS_scheduler_wait(void);
+
+/**
+ * \brief This function will be called when stack receives an event.
+ */
+extern void eventOS_scheduler_signal(void);
+
+/**
+ * \brief This function will be called when stack can enter deep sleep state in detected time.
+ *
+ * Note! This method is called only by reference implementation of idle. Needs to be
+ * ported for the platform only if you are using reference implementation.
+ *
+ * \param sleep_time_ms Time in milliseconds to sleep
+ * \return time slept in milliseconds
+ */
+extern uint32_t eventOS_scheduler_sleep(uint32_t sleep_time_ms);
+
+/**
+ * \brief Lock a thread against the event loop thread
+ *
+ * This method can be provided by multi-threaded platforms to allow
+ * mutual exclusion with the event loop thread, for cases where
+ * code wants to work with both the event loop and other threads.
+ *
+ * A typical platform implementation would claim the same mutex
+ * before calling eventOS_scheduler_run() or
+ * eventOS_scheduler_dispatch(), and release it during
+ * eventOS_scheduler_idle().
+ *
+ * The mutex must count - nested calls from one thread return
+ * immediately. Thus calling this from inside an event callback
+ * is harmless.
+ */
+extern void eventOS_scheduler_mutex_wait(void);
+
+/**
+ * \brief Release the event loop mutex
+ *
+ * Release the mutex claimed with eventOS_scheduler_mutex_wait(),
+ * allowing the event loop to continue processing.
+ */
+extern void eventOS_scheduler_mutex_release(void);
+
+/**
+ * \brief Check if the current thread owns the event mutex
+ *
+ * Check if the calling thread owns the scheduler mutex.
+ * This allows the ownership to be asserted if a function
+ * requires the mutex to be locked externally.
+ *
+ * The function is only intended as a debugging aid for
+ * users of eventOS_scheduler_mutex_wait() - it is not
+ * used by the event loop core itself.
+ *
+ * If the underlying mutex system does not support it,
+ * this may be implemented to always return true.
+ *
+ * \return true if the current thread owns the mutex
+ */
+extern bool eventOS_scheduler_mutex_am_owner(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EVENTOS_SCHEDULER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/nanostack-event-loop/platform/arm_hal_timer.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef ARM_HAL_TIMER_H_
+#define ARM_HAL_TIMER_H_
+
+#include "eventloop_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef NS_EXCLUDE_HIGHRES_TIMER
+/**
+ * \brief This function perform timer init.
+ */
+extern void platform_timer_enable(void);
+
+/**
+ * \brief This function is API for set Timer interrupt handler for stack
+ *
+ * \param new_fp Function pointer for stack giving timer handler
+ *
+ */
+typedef void (*platform_timer_cb)(void);
+extern void platform_timer_set_cb(platform_timer_cb new_fp);
+
+/**
+ * \brief This function is API for stack timer start
+ *
+ * \param slots define how many 50us slot time period will be started
+ *
+ */
+extern void platform_timer_start(uint16_t slots);
+
+/**
+ * \brief This function is API for stack timer stop
+ *
+ */
+extern void platform_timer_disable(void);
+
+/**
+ * \brief This function is API for stack timer to read active timer remaining slot count
+ *
+ * \return 50us time slot remaining
+ */
+extern uint16_t platform_timer_get_remaining_slots(void);
+
+#endif // NS_EXCLUDE_HIGHRES_TIMER
+
+#ifdef NS_EVENTLOOP_USE_TICK_TIMER
+/**
+ * \brief This function is API for registering low resolution tick timer callback. Also does
+ *        any necessary initialization of the tick timer.
+ *
+ * \return -1 for failure, success otherwise
+ */
+extern int8_t platform_tick_timer_register(void (*tick_timer_cb_handler)(void));
+
+/**
+ * \brief This function is API for starting the low resolution tick timer. The callback
+ *        set with platform_tick_timer_register gets called periodically until stopped
+ *        by calling platform_tick_timer_stop.
+ *
+ * \param period_ms define how many milliseconds time period will be started
+ * \return -1 for failure, success otherwise
+ */
+extern int8_t platform_tick_timer_start(uint32_t period_ms);
+
+/**
+ * \brief This function is API for stopping the low resolution tick timer
+ *
+ * \return -1 for failure, success otherwise
+ */
+extern int8_t platform_tick_timer_stop(void);
+
+#endif // NS_EVENTLOOP_USE_TICK_TIMER
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ARM_HAL_TIMER_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/nanostack-event-loop/platform/eventloop_config.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef EVENTLOOP_CONFIG_H_
+#define EVENTLOOP_CONFIG_H_
+
+/*
+ * Options can be picked up from mbed-cli JSON configuration, or from
+ * Yotta JSON configuration, or from a user configuration file - see below.
+ *
+ * Undefine all internal flags before evaluating the configuration.
+ */
+
+/* Use platform-provided low-resolution tick timer for eventloop (requires "platform_tick_timer" API) */
+#undef NS_EVENTLOOP_USE_TICK_TIMER
+/* Exclude high resolution timer from build (removes need for "platform_timer" API) */
+#undef NS_EXCLUDE_HIGHRES_TIMER
+
+/*
+ * mbedOS 5 specific configuration flag mapping to internal flags
+ */
+#ifdef MBED_CONF_NANOSTACK_EVENTLOOP_USE_PLATFORM_TICK_TIMER
+#define NS_EVENTLOOP_USE_TICK_TIMER     1
+#endif
+
+#ifdef MBED_CONF_NANOSTACK_EVENTLOOP_EXCLUDE_HIGHRES_TIMER
+#define NS_EXCLUDE_HIGHRES_TIMER        1
+#endif
+
+/*
+ * For mbedOS 3 and minar use platform tick timer by default, highres timers should come from eventloop adaptor
+ */
+#ifdef YOTTA_CFG_MINAR
+#define NS_EVENTLOOP_USE_TICK_TIMER     1
+#endif
+
+/*
+ * Include the user config file if defined
+ */
+#ifdef NS_EVENTLOOP_USER_CONFIG_FILE
+#include NS_EVENTLOOP_USER_CONFIG_FILE
+#endif
+
+#endif /* EVENTLOOP_CONFIG_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/event.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,401 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include <string.h>
+#include "ns_types.h"
+#include "ns_list.h"
+#include "eventOS_event.h"
+#include "eventOS_scheduler.h"
+#include "timer_sys.h"
+#include "nsdynmemLIB.h"
+#include "ns_timer.h"
+#include "event.h"
+#include "platform/arm_hal_interrupt.h"
+
+
+typedef struct arm_core_tasklet {
+    int8_t id; /**< Event handler Tasklet ID */
+    void (*func_ptr)(arm_event_s *);
+    ns_list_link_t link;
+} arm_core_tasklet_t;
+
+static NS_LIST_DEFINE(arm_core_tasklet_list, arm_core_tasklet_t, link);
+static NS_LIST_DEFINE(event_queue_active, arm_event_storage_t, link);
+static NS_LIST_DEFINE(free_event_entry, arm_event_storage_t, link);
+
+// Statically allocate initial pool of events.
+#define STARTUP_EVENT_POOL_SIZE 10
+static arm_event_storage_t startup_event_pool[STARTUP_EVENT_POOL_SIZE];
+
+/** Curr_tasklet tell to core and platform which task_let is active, Core Update this automatic when switch Tasklet. */
+int8_t curr_tasklet = 0;
+
+
+static arm_core_tasklet_t *tasklet_dynamically_allocate(void);
+static arm_event_storage_t *event_dynamically_allocate(void);
+static arm_event_storage_t *event_core_get(void);
+static void event_core_write(arm_event_storage_t *event);
+
+static arm_core_tasklet_t *event_tasklet_handler_get(uint8_t tasklet_id)
+{
+    ns_list_foreach(arm_core_tasklet_t, cur, &arm_core_tasklet_list) {
+        if (cur->id == tasklet_id) {
+            return cur;
+        }
+    }
+    return NULL;
+}
+
+bool event_tasklet_handler_id_valid(uint8_t tasklet_id)
+{
+    return event_tasklet_handler_get(tasklet_id);
+}
+
+// XXX this can return 0, but 0 seems to mean "none" elsewhere? Or at least
+// curr_tasklet is reset to 0 in various places.
+static int8_t tasklet_get_free_id(void)
+{
+    /*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/
+    for (uint8_t i = 0; i <= INT8_MAX; i++) {
+        if (!event_tasklet_handler_get(i)) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+
+int8_t eventOS_event_handler_create(void (*handler_func_ptr)(arm_event_s *), uint8_t init_event_type)
+{
+    arm_event_storage_t *event_tmp;
+
+    // XXX Do we really want to prevent multiple tasklets with same function?
+    ns_list_foreach(arm_core_tasklet_t, cur, &arm_core_tasklet_list) {
+        if (cur->func_ptr == handler_func_ptr) {
+            return -1;
+        }
+    }
+
+    //Allocate new
+    arm_core_tasklet_t *new = tasklet_dynamically_allocate();
+    if (!new) {
+        return -2;
+    }
+
+    event_tmp = event_core_get();
+    if (!event_tmp) {
+        ns_dyn_mem_free(new);
+        return -2;
+    }
+
+    //Fill in tasklet; add to list
+    new->id = tasklet_get_free_id();
+    new->func_ptr = handler_func_ptr;
+    ns_list_add_to_end(&arm_core_tasklet_list, new);
+
+    //Queue "init" event for the new task
+    event_tmp->data.receiver = new->id;
+    event_tmp->data.sender = 0;
+    event_tmp->data.event_type = init_event_type;
+    event_tmp->data.event_data = 0;
+    event_core_write(event_tmp);
+
+    return new->id;
+}
+
+int8_t eventOS_event_send(const arm_event_t *event)
+{
+    if (event_tasklet_handler_get(event->receiver)) {
+        arm_event_storage_t *event_tmp = event_core_get();
+        if (event_tmp) {
+            event_tmp->data = *event;
+            event_core_write(event_tmp);
+            return 0;
+        }
+    }
+    return -1;
+}
+
+void eventOS_event_send_user_allocated(arm_event_storage_t *event)
+{
+    event->allocator = ARM_LIB_EVENT_USER;
+    event_core_write(event);
+}
+
+void eventOS_event_send_timer_allocated(arm_event_storage_t *event)
+{
+    event->allocator = ARM_LIB_EVENT_TIMER;
+    event_core_write(event);
+}
+
+void eventOS_event_cancel_critical(arm_event_storage_t *event)
+{
+    ns_list_remove(&event_queue_active, event);
+}
+
+static arm_event_storage_t *event_dynamically_allocate(void)
+{
+    arm_event_storage_t *event = ns_dyn_mem_temporary_alloc(sizeof(arm_event_storage_t));
+    if (event) {
+        event->allocator = ARM_LIB_EVENT_DYNAMIC;
+    }
+    return event;
+}
+
+static arm_core_tasklet_t *tasklet_dynamically_allocate(void)
+{
+    return ns_dyn_mem_alloc(sizeof(arm_core_tasklet_t));
+}
+
+arm_event_storage_t *event_core_get(void)
+{
+    arm_event_storage_t *event;
+    platform_enter_critical();
+    event = ns_list_get_first(&free_event_entry);
+    if (event) {
+        ns_list_remove(&free_event_entry, event);
+    } else {
+        event = event_dynamically_allocate();
+    }
+    if (event) {
+        event->data.data_ptr = NULL;
+        event->data.priority = ARM_LIB_LOW_PRIORITY_EVENT;
+    }
+    platform_exit_critical();
+    return event;
+}
+
+void event_core_free_push(arm_event_storage_t *free)
+{
+    free->state = ARM_LIB_EVENT_UNQUEUED;
+
+    switch (free->allocator) {
+        case ARM_LIB_EVENT_STARTUP_POOL:
+            platform_enter_critical();
+            ns_list_add_to_start(&free_event_entry, free);
+            platform_exit_critical();
+            break;
+        case ARM_LIB_EVENT_DYNAMIC:
+            // Free all dynamically allocated events.
+            ns_dyn_mem_free(free);
+            break;
+        case ARM_LIB_EVENT_TIMER:
+            // Hand it back to the timer system
+            timer_sys_event_free(free);
+            break;
+        case ARM_LIB_EVENT_USER:
+        default:
+            break;
+    }
+}
+
+
+static arm_event_storage_t *event_core_read(void)
+{
+    platform_enter_critical();
+    arm_event_storage_t *event = ns_list_get_first(&event_queue_active);
+    if (event) {
+        event->state = ARM_LIB_EVENT_RUNNING;
+        ns_list_remove(&event_queue_active, event);
+    }
+    platform_exit_critical();
+    return event;
+}
+
+void event_core_write(arm_event_storage_t *event)
+{
+    platform_enter_critical();
+    bool added = false;
+    ns_list_foreach(arm_event_storage_t, event_tmp, &event_queue_active) {
+        // note enum ordering means we're checking if event_tmp is LOWER priority than event
+        if (event_tmp->data.priority > event->data.priority) {
+            ns_list_add_before(&event_queue_active, event_tmp, event);
+            added = true;
+            break;
+        }
+    }
+    if (!added) {
+        ns_list_add_to_end(&event_queue_active, event);
+    }
+    event->state = ARM_LIB_EVENT_QUEUED;
+
+    /* Wake From Idle */
+    platform_exit_critical();
+    eventOS_scheduler_signal();
+}
+
+// Requires lock to be held
+arm_event_storage_t *eventOS_event_find_by_id_critical(uint8_t tasklet_id, uint8_t event_id)
+{
+    ns_list_foreach(arm_event_storage_t, cur, &event_queue_active) {
+        if (cur->data.receiver == tasklet_id && cur->data.event_id == event_id) {
+            return cur;
+        }
+    }
+
+    return NULL;
+}
+
+/**
+ *
+ * \brief Initialize Nanostack Core.
+ *
+ * Function Initialize Nanostack Core, Socket Interface,Buffer memory and Send Init event to all Tasklett which are Defined.
+ *
+ */
+void eventOS_scheduler_init(void)
+{
+    /* Reset Event List variables */
+    ns_list_init(&free_event_entry);
+    ns_list_init(&event_queue_active);
+    ns_list_init(&arm_core_tasklet_list);
+
+    //Add first 10 entries to "free" list
+    for (unsigned i = 0; i < (sizeof(startup_event_pool) / sizeof(startup_event_pool[0])); i++) {
+        startup_event_pool[i].allocator = ARM_LIB_EVENT_STARTUP_POOL;
+        ns_list_add_to_start(&free_event_entry, &startup_event_pool[i]);
+    }
+
+    /* Init Generic timer module */
+    timer_sys_init();               //initialize timer
+    /* Set Tasklett switcher to Idle */
+    curr_tasklet = 0;
+
+}
+
+int8_t eventOS_scheduler_get_active_tasklet(void)
+{
+    return curr_tasklet;
+}
+
+void eventOS_scheduler_set_active_tasklet(int8_t tasklet)
+{
+    curr_tasklet = tasklet;
+}
+
+int eventOS_scheduler_timer_stop(void)
+{
+    timer_sys_disable();
+    if (ns_timer_sleep() != 0) {
+        return 1;
+    }
+    return 0;
+}
+
+int eventOS_scheduler_timer_synch_after_sleep(uint32_t sleep_ticks)
+{
+    //Update MS to 10ms ticks
+    sleep_ticks /= 10;
+    sleep_ticks++;
+    system_timer_tick_update(sleep_ticks);
+    if (timer_sys_wakeup() == 0) {
+        return 0;
+    }
+    return -1;
+}
+
+/**
+ *
+ * \brief Infinite Event Read Loop.
+ *
+ * Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep
+ *
+ */
+bool eventOS_scheduler_dispatch_event(void)
+{
+    curr_tasklet = 0;
+
+    arm_event_storage_t *cur_event = event_core_read();
+    if (!cur_event) {
+        return false;
+    }
+
+    curr_tasklet = cur_event->data.receiver;
+
+    arm_core_tasklet_t *tasklet = event_tasklet_handler_get(curr_tasklet);
+    /* Do not bother with check for NULL - tasklets cannot be deleted,
+     * and user-facing API eventOS_event_send() has already checked the tasklet
+     * exists, so there is no possible issue there.
+     *
+     * For eventOS_event_send_user_allocated(), it would be a non-recoverable
+     * error to not deliver the message - we have to have a receiver to pass
+     * ownership to. If the lookup fails, let it crash. We want the send call
+     * itself to return void to simplify logic.
+     */
+
+    /* Tasklet Scheduler Call */
+    tasklet->func_ptr(&cur_event->data);
+    event_core_free_push(cur_event);
+
+    /* Set Current Tasklet to Idle state */
+    curr_tasklet = 0;
+
+    return true;
+}
+
+void eventOS_scheduler_run_until_idle(void)
+{
+    while (eventOS_scheduler_dispatch_event());
+}
+
+/**
+ *
+ * \brief Infinite Event Read Loop.
+ *
+ * Function Read and handle Cores Event and switch/enable tasklet which are event receiver. WhenEvent queue is empty it goes to sleep
+ *
+ */
+NS_NORETURN void eventOS_scheduler_run(void)
+{
+    while (1) {
+        if (!eventOS_scheduler_dispatch_event()) {
+            eventOS_scheduler_idle();
+        }
+    }
+}
+
+void eventOS_cancel(arm_event_storage_t *event)
+{
+    if (!event) {
+        return;
+    }
+
+    platform_enter_critical();
+
+    /*
+     * Notify timer of cancellation.
+     */
+    if (event->allocator == ARM_LIB_EVENT_TIMER) {
+        timer_sys_event_cancel_critical(event);
+    }
+
+    /*
+     * Remove event from the list,
+     * Only queued can be removed, unqued are either timers or stale pointers
+     * RUNNING cannot be removed, we are currenly "in" that event.
+     */
+    if (event->state == ARM_LIB_EVENT_QUEUED) {
+        eventOS_event_cancel_critical(event);
+    }
+
+    /*
+     * Push back to "free" state
+     */
+    if (event->state != ARM_LIB_EVENT_RUNNING) {
+        event_core_free_push(event);
+    }
+
+    platform_exit_critical();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/event.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef NS_EVENT_H_
+#define NS_EVENT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+bool event_tasklet_handler_id_valid(uint8_t tasklet_id);
+void eventOS_event_send_timer_allocated(arm_event_storage_t *event);
+
+// This requires lock to be held
+arm_event_storage_t *eventOS_event_find_by_id_critical(uint8_t tasklet_id, uint8_t event_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*NS_EVENT_H_*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/minar_hal_timer.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016 ARM Limited, All Rights Reserved
+ */
+
+// Include before mbed.h to properly get UINT*_C()
+
+#include "ns_types.h"
+
+#include "platform/arm_hal_timer.h"
+#include "platform/arm_hal_interrupt.h"
+
+#if defined(NS_EVENTLOOP_USE_TICK_TIMER) && defined(YOTTA_CFG_MINAR)
+
+#include "minar/minar.h"
+#include "mbed-drivers/mbed.h"
+#include "core-util/FunctionPointer.h"
+#include "core-util/Event.h"
+
+#define TICK_TIMER_ID   1
+
+using minar::Scheduler;
+using minar::milliseconds;
+using minar::callback_handle_t;
+using namespace mbed::util;
+
+static callback_handle_t sys_timer_handle;
+static void (*tick_timer_callback)(void);
+
+void timer_callback(void const *funcArgument)
+{
+    (void)funcArgument;
+    if (NULL != tick_timer_callback) {
+        tick_timer_callback();
+    }
+}
+
+// Low precision platform tick timer
+int8_t platform_tick_timer_register(void (*tick_timer_cb_handler)(void))
+{
+    tick_timer_callback = tick_timer_cb_handler;
+    return TICK_TIMER_ID;
+}
+
+int8_t platform_tick_timer_start(uint32_t period_ms)
+{
+    int8_t retval = -1;
+    if (sys_timer_handle != NULL) {
+        return 0; // Timer already started already so return success
+    }
+    Event e = FunctionPointer1<void, void const *>(timer_callback).bind(NULL);
+    if (e != NULL) {
+        sys_timer_handle = Scheduler::postCallback(e).period(milliseconds(period_ms)).getHandle();
+        if (sys_timer_handle != NULL) {
+            retval = 0;
+        }
+    }
+    return retval;
+}
+
+int8_t platform_tick_timer_stop(void)
+{
+    int8_t retval = -1;
+    if (sys_timer_handle != NULL) {
+        Scheduler::cancelCallback(sys_timer_handle);
+        sys_timer_handle = NULL;
+        retval = 0;
+    }
+    return retval;
+}
+
+#endif // defined(NS_EVENTLOOP_USE_TICK_TIMER) && defined(YOTTA_CFG)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/ns_timeout.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "eventOS_event.h"
+#include "eventOS_event_timer.h"
+#include "nsdynmemLIB.h"
+#include "ns_list.h"
+#include "timer_sys.h"
+
+#define STARTUP_EVENT 0
+#define TIMER_EVENT 1
+
+// Timeout structure, already typedefed to timeout_t
+struct timeout_entry_t {
+    void (*callback)(void *);
+    void *arg;
+    arm_event_storage_t *event;
+};
+
+static int8_t timeout_tasklet_id = -1;
+
+static void timeout_tasklet(arm_event_s *event)
+{
+    if (TIMER_EVENT != event->event_type) {
+        return;
+    }
+
+    timeout_t *t = event->data_ptr;
+    arm_event_storage_t *storage = t->event;
+    sys_timer_struct_s *timer = NS_CONTAINER_OF(storage, sys_timer_struct_s, event);
+
+    t->callback(t->arg);
+
+
+    // Check if this was periodic timer
+    if (timer->period == 0) {
+        ns_dyn_mem_free(event->data_ptr);
+    }
+}
+
+static timeout_t *eventOS_timeout_at_(void (*callback)(void *), void *arg, uint32_t at, uint32_t period)
+{
+    arm_event_storage_t *storage;
+
+    timeout_t *timeout = ns_dyn_mem_alloc(sizeof(timeout_t));
+    if (!timeout) {
+        return NULL;
+    }
+    timeout->callback = callback;
+    timeout->arg = arg;
+
+    // Start timeout taskled if it is not running
+    if (-1 == timeout_tasklet_id) {
+        timeout_tasklet_id = eventOS_event_handler_create(timeout_tasklet, STARTUP_EVENT);
+        if (timeout_tasklet_id < 0) {
+            timeout_tasklet_id = -1;
+            goto FAIL;
+        }
+    }
+
+    arm_event_t event = {
+        .receiver   = timeout_tasklet_id,
+        .sender     = timeout_tasklet_id,
+        .event_type = TIMER_EVENT,
+        .event_id   = TIMER_EVENT,
+        .data_ptr   = timeout
+    };
+
+    if (period)
+        storage = eventOS_event_timer_request_every(&event, period);
+    else
+        storage = eventOS_event_timer_request_at(&event, at);
+
+    timeout->event = storage;
+    if (storage)
+        return timeout;
+FAIL:
+    ns_dyn_mem_free(timeout);
+    return NULL;
+}
+
+timeout_t *eventOS_timeout_ms(void (*callback)(void *), uint32_t ms, void *arg)
+{
+    return eventOS_timeout_at_(callback, arg, eventOS_event_timer_ms_to_ticks(ms)+eventOS_event_timer_ticks(), 0);
+}
+
+timeout_t *eventOS_timeout_every_ms(void (*callback)(void *), uint32_t every, void *arg)
+{
+    return eventOS_timeout_at_(callback, arg, 0, eventOS_event_timer_ms_to_ticks(every));
+}
+
+void eventOS_timeout_cancel(timeout_t *t)
+{
+    if (!t)
+        return;
+
+    eventOS_cancel(t->event);
+
+    // Defer the freeing until returning from the callback
+    if (t->event->state != ARM_LIB_EVENT_RUNNING) {
+        ns_dyn_mem_free(t);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/ns_timer.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#include "ns_types.h"
+#include "ns_list.h"
+#include "ns_timer.h"
+#include "eventOS_callback_timer.h"
+#include "platform/arm_hal_interrupt.h"
+#include "platform/arm_hal_timer.h"
+#include "nsdynmemLIB.h"
+
+#ifndef NS_EXCLUDE_HIGHRES_TIMER
+typedef enum ns_timer_state_e {
+    NS_TIMER_ACTIVE = 0,        // Will run on the next HAL interrupt
+    NS_TIMER_HOLD,              // Will run on a later HAL interrupt
+    NS_TIMER_RUN_INTERRUPT,     // Running on the interrupt we're currently handling
+    NS_TIMER_STOP               // Timer not scheduled ("start" not called since last callback)
+} ns_timer_state_e;
+
+typedef struct ns_timer_struct {
+    int8_t ns_timer_id;
+    ns_timer_state_e timer_state;
+    uint16_t slots;
+    uint16_t remaining_slots;
+    void (*interrupt_handler)(int8_t, uint16_t);
+    ns_list_link_t link;
+} ns_timer_struct;
+
+static NS_LIST_DEFINE(ns_timer_list, ns_timer_struct, link);
+
+#define NS_TIMER_RUNNING    1
+static uint8_t ns_timer_state = 0;
+
+#ifdef ATMEGA256RFR2
+#define COMPENSATION 3
+#define COMPENSATION_TUNE 1
+#else
+#define COMPENSATION 0
+#define COMPENSATION_TUNE 0
+#endif
+
+static void ns_timer_interrupt_handler(void);
+static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id);
+static bool ns_timer_initialized = 0;
+
+int8_t eventOS_callback_timer_register(void (*timer_interrupt_handler)(int8_t, uint16_t))
+{
+    int8_t retval = -1;
+
+    if (!ns_timer_initialized) {
+        /*Set interrupt handler in HAL driver*/
+        platform_timer_set_cb(ns_timer_interrupt_handler);
+        ns_timer_initialized = 1;
+    }
+
+    /*Find first free timer ID in timer list*/
+    /*(Note use of uint8_t to avoid overflow if we reach 0x7F)*/
+    for (uint8_t i = 0; i <= INT8_MAX; i++) {
+        if (!ns_timer_get_pointer_to_timer_struct(i)) {
+            retval = i;
+            break;
+        }
+    }
+
+    if (retval == -1) {
+        return -1;
+    }
+
+    ns_timer_struct *new_timer = ns_dyn_mem_alloc(sizeof(ns_timer_struct));
+    if (!new_timer) {
+        return -1;
+    }
+
+    /*Initialise new timer*/
+    new_timer->ns_timer_id = retval;
+    new_timer->timer_state = NS_TIMER_STOP;
+    new_timer->remaining_slots = 0;
+    new_timer->interrupt_handler = timer_interrupt_handler;
+
+    // Critical section sufficient as long as list can't be reordered from
+    // interrupt, otherwise will need to cover whole routine
+    platform_enter_critical();
+    ns_list_add_to_end(&ns_timer_list, new_timer);
+    platform_exit_critical();
+
+    /*Return timer ID*/
+    return retval;
+}
+
+int8_t eventOS_callback_timer_unregister(int8_t ns_timer_id)
+{
+    ns_timer_struct *current_timer;
+
+    current_timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id);
+    if (!current_timer) {
+        return -1;
+    }
+
+    // Critical section sufficient as long as list can't be reordered from
+    // interrupt, otherwise will need to cover whole routine
+    platform_enter_critical();
+    ns_list_remove(&ns_timer_list, current_timer);
+    platform_exit_critical();
+
+    ns_dyn_mem_free(current_timer);
+    return 0;
+}
+
+
+static int8_t ns_timer_start_pl_timer(uint16_t pl_timer_start_slots)
+{
+    /*Don't start timer with 0 slots*/
+    if (!pl_timer_start_slots) {
+        pl_timer_start_slots = 1;
+    }
+
+    /*Start HAL timer*/
+    platform_timer_start(pl_timer_start_slots);
+    /*Set HAL timer state to running*/
+    ns_timer_state |= NS_TIMER_RUNNING;
+    return 0;
+}
+
+int8_t ns_timer_sleep(void)
+{
+    int8_t ret_val = -1;
+    if (ns_timer_state & NS_TIMER_RUNNING) {
+        /*Start HAL timer*/
+        platform_timer_disable();
+        /*Set HAL timer state to running*/
+        ns_timer_state &= ~NS_TIMER_RUNNING;
+        ret_val = 0;
+    }
+    return ret_val;
+}
+
+static int8_t ns_timer_get_next_running_to(void)
+{
+    uint8_t hold_count = 0;
+    ns_timer_struct *first_timer = NULL;
+
+    /*Find hold-labelled timer with the least remaining slots*/
+    ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
+        if (current_timer->timer_state == NS_TIMER_HOLD) {
+            if (!first_timer || current_timer->remaining_slots < first_timer->remaining_slots) {
+                first_timer = current_timer;
+            }
+            /*For optimisation, count the found timers*/
+            hold_count++;
+        }
+    }
+
+    if (!first_timer) {
+        return 0;
+    }
+
+    /*If hold-labelled timer found, set it active and start the HAL driver*/
+    hold_count--;
+    first_timer->timer_state = NS_TIMER_ACTIVE;
+    /*Compensate time spent in timer function*/
+    if (first_timer->remaining_slots > COMPENSATION) {
+        first_timer->remaining_slots -= COMPENSATION;
+    }
+    /*Start HAL timer*/
+    ns_timer_start_pl_timer(first_timer->remaining_slots);
+
+    /*Update other hold-labelled timers*/
+    ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
+        if (hold_count == 0) { // early termination optimisation
+            break;
+        }
+        if (current_timer->timer_state == NS_TIMER_HOLD) {
+            if (current_timer->remaining_slots == first_timer->remaining_slots) {
+                current_timer->timer_state = NS_TIMER_ACTIVE;
+            } else {
+                current_timer->remaining_slots -= first_timer->remaining_slots;
+                /*Compensate time spent in timer function*/
+                if (current_timer->remaining_slots > COMPENSATION) {
+                    current_timer->remaining_slots -= COMPENSATION;
+                }
+            }
+            hold_count--;
+        }
+    }
+
+    return 0;
+}
+
+
+static ns_timer_struct *ns_timer_get_pointer_to_timer_struct(int8_t timer_id)
+{
+    /*Find timer with the given ID*/
+    ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
+        if (current_timer->ns_timer_id == timer_id) {
+            return current_timer;
+        }
+    }
+    return NULL;
+}
+
+int8_t eventOS_callback_timer_start(int8_t ns_timer_id, uint16_t slots)
+{
+    int8_t ret_val = 0;
+    uint16_t pl_timer_remaining_slots;
+    ns_timer_struct *timer;
+    platform_enter_critical();
+
+    /*Find timer to be activated*/
+    timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id);
+    if (!timer) {
+        ret_val = -1;
+        goto exit;
+    }
+
+    // XXX this assumes the timer currently isn't running?
+    // Is event.c relying on this restarting HAL timer after ns_timer_sleep()?
+
+    /*If any timers are active*/
+    if (ns_timer_state & NS_TIMER_RUNNING) {
+        /*Get remaining slots of the currently activated timeout*/
+        pl_timer_remaining_slots = platform_timer_get_remaining_slots();
+
+        /*New timeout is shorter than currently enabled timeout*/
+        if (pl_timer_remaining_slots > slots) {
+            /*Start HAL timer*/
+            ns_timer_start_pl_timer(slots - 0);
+
+            ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
+                /*Switch active timers to hold*/
+                if (current_timer->timer_state == NS_TIMER_ACTIVE) {
+                    current_timer->timer_state = NS_TIMER_HOLD;
+                    current_timer->remaining_slots = 0;
+                }
+                /*Update hold-labelled timers*/
+                if (current_timer->timer_state == NS_TIMER_HOLD) {
+                    current_timer->remaining_slots += (pl_timer_remaining_slots - slots);
+                    /*Compensate time spent in timer function*/
+                    if (current_timer->remaining_slots > (COMPENSATION - COMPENSATION_TUNE)) {
+                        current_timer->remaining_slots -= (COMPENSATION - COMPENSATION_TUNE);
+                    }
+                }
+            }
+            /*Mark active and start the timer*/
+            timer->timer_state = NS_TIMER_ACTIVE;
+            timer->slots = slots;
+            timer->remaining_slots = slots;
+        }
+
+        /*New timeout is longer than currently enabled timeout*/
+        else if (pl_timer_remaining_slots < slots) {
+            /*Mark hold and update remaining slots*/
+            timer->timer_state = NS_TIMER_HOLD;
+            timer->slots = slots;
+            timer->remaining_slots = (slots - pl_timer_remaining_slots);
+        }
+        /*New timeout is equal to currently enabled timeout*/
+        else {
+            /*Mark it active and it will be handled in next interrupt*/
+            timer->timer_state = NS_TIMER_ACTIVE;
+            timer->slots = slots;
+            timer->remaining_slots = slots;
+        }
+    } else {
+        /*No timers running*/
+        timer->timer_state = NS_TIMER_HOLD;
+        timer->slots = slots;
+        timer->remaining_slots = slots;
+        /*Start next timeout*/
+        ns_timer_get_next_running_to();
+    }
+exit:
+    platform_exit_critical();
+    return ret_val;
+}
+
+static void ns_timer_interrupt_handler(void)
+{
+    uint8_t i = 0;
+
+    platform_enter_critical();
+    /*Clear timer running state*/
+    ns_timer_state &= ~NS_TIMER_RUNNING;
+    /*Mark active timers as NS_TIMER_RUN_INTERRUPT, interrupt functions are called at the end of this function*/
+    ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
+        if (current_timer->timer_state == NS_TIMER_ACTIVE) {
+            current_timer->timer_state = NS_TIMER_RUN_INTERRUPT;
+            /*For optimisation, count the found timers*/
+            i++;
+        }
+    }
+
+    /*Start next timeout*/
+    ns_timer_get_next_running_to();
+
+    /*Call interrupt functions*/
+    ns_list_foreach(ns_timer_struct, current_timer, &ns_timer_list) {
+        if (i == 0) {
+            break;
+        }
+        if (current_timer->timer_state == NS_TIMER_RUN_INTERRUPT) {
+            current_timer->timer_state = NS_TIMER_STOP;
+            current_timer->interrupt_handler(current_timer->ns_timer_id, current_timer->slots);
+            i--;
+        }
+    }
+
+    platform_exit_critical();
+}
+
+int8_t eventOS_callback_timer_stop(int8_t ns_timer_id)
+{
+    uint16_t pl_timer_remaining_slots;
+    bool active_timer_found = false;
+    ns_timer_struct *current_timer;
+    ns_timer_struct *first_timer = NULL;
+    int8_t retval = -1;
+
+    platform_enter_critical();
+    /*Find timer with given timer ID*/
+    current_timer = ns_timer_get_pointer_to_timer_struct(ns_timer_id);
+    if (!current_timer) {
+        goto exit;
+    }
+
+    retval = 0;
+
+    /*Check if already stopped*/
+    if (current_timer->timer_state == NS_TIMER_STOP) {
+        goto exit;
+    }
+
+    current_timer->timer_state = NS_TIMER_STOP;
+    current_timer->remaining_slots = 0;
+
+    /*Check if some timer is already active*/
+    ns_list_foreach(ns_timer_struct, curr_timer, &ns_timer_list) {
+        if (curr_timer->timer_state == NS_TIMER_ACTIVE) {
+            active_timer_found = true;
+            break;
+        }
+    }
+    /*If no active timers found, start one*/
+    if (!active_timer_found) {
+        pl_timer_remaining_slots = platform_timer_get_remaining_slots();
+        /*Find hold-labelled timer with the least remaining slots*/
+        ns_list_foreach(ns_timer_struct, cur_timer, &ns_timer_list) {
+            if (cur_timer->timer_state == NS_TIMER_HOLD) {
+                cur_timer->remaining_slots += pl_timer_remaining_slots;
+
+                if (!first_timer || cur_timer->remaining_slots < first_timer->remaining_slots) {
+                    first_timer = cur_timer;
+                }
+            }
+        }
+        /*If hold-labelled timer found, set it active and start the HAL driver*/
+        if (first_timer) {
+            first_timer->timer_state = NS_TIMER_ACTIVE;
+            /*Start HAL timer*/
+            ns_timer_start_pl_timer(first_timer->remaining_slots);
+            /*If some of the other hold-labelled timers have the same remaining slots as the timer_tmp, mark them active*/
+            ns_list_foreach(ns_timer_struct, cur_timer, &ns_timer_list) {
+                if (cur_timer->timer_state == NS_TIMER_HOLD) {
+                    if (cur_timer->remaining_slots == first_timer->remaining_slots) {
+                        cur_timer->timer_state = NS_TIMER_ACTIVE;
+                    } else {
+                        cur_timer->remaining_slots -= first_timer->remaining_slots;
+                    }
+                }
+            }
+        }
+    }
+
+exit:
+    platform_exit_critical();
+
+    return retval;
+}
+#endif // NS_EXCLUDE_HIGHRES_TIMER
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/ns_timer.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef NS_TIMER_H_
+#define NS_TIMER_H_
+
+#include "platform/eventloop_config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef NS_EXCLUDE_HIGHRES_TIMER
+extern int8_t ns_timer_sleep(void);
+#else
+#define ns_timer_sleep() ((int8_t) 0)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*NS_TIMER_H_*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/system_timer.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#include "ns_types.h"
+#include "ns_list.h"
+#include "timer_sys.h"
+#include "platform/arm_hal_interrupt.h"
+#include "platform/arm_hal_timer.h"
+#include "nsdynmemLIB.h"
+#include "eventOS_event.h"
+#include "eventOS_event_timer.h"
+#include "event.h"
+#include "eventOS_callback_timer.h"
+
+#include "ns_timer.h"
+
+#ifndef ST_MAX
+#define ST_MAX 6
+#endif
+
+static sys_timer_struct_s startup_sys_timer_pool[ST_MAX];
+
+#define TIMER_SLOTS_PER_MS          20
+NS_STATIC_ASSERT(1000 % EVENTOS_EVENT_TIMER_HZ == 0, "Need whole number of ms per tick")
+#define TIMER_SYS_TICK_PERIOD       (1000 / EVENTOS_EVENT_TIMER_HZ) // milliseconds
+
+// timer_sys_ticks must be read in critical section to guarantee
+// atomicity on 16-bit platforms
+static volatile uint32_t timer_sys_ticks;
+
+static NS_LIST_DEFINE(system_timer_free, sys_timer_struct_s, event.link);
+static NS_LIST_DEFINE(system_timer_list, sys_timer_struct_s, event.link);
+
+
+static sys_timer_struct_s *sys_timer_dynamically_allocate(void);
+static void timer_sys_interrupt(void);
+static void timer_sys_add(sys_timer_struct_s *timer);
+
+#ifndef NS_EVENTLOOP_USE_TICK_TIMER
+static int8_t platform_tick_timer_start(uint32_t period_ms);
+/* Implement platform tick timer using eventOS timer */
+// platform tick timer callback function
+static void (*tick_timer_callback)(void);
+static int8_t tick_timer_id = -1;	// eventOS timer id for tick timer
+
+// EventOS timer callback function
+static void tick_timer_eventOS_callback(int8_t timer_id, uint16_t slots)
+{
+    // Not interested in timer id or slots
+    (void)slots;
+    // Call the tick timer callback
+    if (tick_timer_callback != NULL && timer_id == tick_timer_id) {
+        platform_tick_timer_start(TIMER_SYS_TICK_PERIOD);
+        tick_timer_callback();
+    }
+}
+
+static int8_t platform_tick_timer_register(void (*tick_timer_cb)(void))
+{
+    tick_timer_callback = tick_timer_cb;
+    tick_timer_id = eventOS_callback_timer_register(tick_timer_eventOS_callback);
+    return tick_timer_id;
+}
+
+static int8_t platform_tick_timer_start(uint32_t period_ms)
+{
+    return eventOS_callback_timer_start(tick_timer_id, TIMER_SLOTS_PER_MS * period_ms);
+}
+
+static int8_t platform_tick_timer_stop(void)
+{
+    return eventOS_callback_timer_stop(tick_timer_id);
+}
+#endif // !NS_EVENTLOOP_USE_TICK_TIMER
+
+/*
+ * Initializes timers and starts system timer
+ */
+void timer_sys_init(void)
+{
+    for (uint8_t i = 0; i < ST_MAX; i++) {
+        ns_list_add_to_start(&system_timer_free, &startup_sys_timer_pool[i]);
+    }
+
+    platform_tick_timer_register(timer_sys_interrupt);
+    platform_tick_timer_start(TIMER_SYS_TICK_PERIOD);
+}
+
+
+
+/*-------------------SYSTEM TIMER FUNCTIONS--------------------------*/
+void timer_sys_disable(void)
+{
+    platform_tick_timer_stop();
+}
+
+/*
+ * Starts ticking system timer interrupts every 10ms
+ */
+int8_t timer_sys_wakeup(void)
+{
+    return platform_tick_timer_start(TIMER_SYS_TICK_PERIOD);
+}
+
+
+static void timer_sys_interrupt(void)
+{
+    system_timer_tick_update(1);
+}
+
+
+
+/* * * * * * * * * */
+
+static sys_timer_struct_s *sys_timer_dynamically_allocate(void)
+{
+    return ns_dyn_mem_alloc(sizeof(sys_timer_struct_s));
+}
+
+static sys_timer_struct_s *timer_struct_get(void)
+{
+    sys_timer_struct_s *timer;
+    platform_enter_critical();
+    timer = ns_list_get_first(&system_timer_free);
+    if (timer) {
+        ns_list_remove(&system_timer_free, timer);
+    } else {
+        timer = sys_timer_dynamically_allocate();
+    }
+    platform_exit_critical();
+    return timer;
+}
+
+void timer_sys_event_free(arm_event_storage_t *event)
+{
+    platform_enter_critical();
+    sys_timer_struct_s *timer = NS_CONTAINER_OF(event, sys_timer_struct_s, event);
+    if (timer->period == 0) {
+        // Non-periodic - return to free list
+        ns_list_add_to_start(&system_timer_free, timer);
+    } else {
+        // Periodic - check due time of next launch
+        timer->launch_time += timer->period;
+        if (TICKS_BEFORE_OR_AT(timer->launch_time, timer_sys_ticks)) {
+            // next event is overdue - queue event now
+            eventOS_event_send_timer_allocated(&timer->event);
+        } else {
+            // add back to timer queue for the future
+            timer_sys_add(timer);
+        }
+    }
+    platform_exit_critical();
+}
+
+void timer_sys_event_cancel_critical(struct arm_event_storage *event)
+{
+    sys_timer_struct_s *timer = NS_CONTAINER_OF(event, sys_timer_struct_s, event);
+    timer->period = 0;
+    // If its unqueued it is on my timer list, otherwise it is in event-loop.
+    if (event->state == ARM_LIB_EVENT_UNQUEUED) {
+        ns_list_remove(&system_timer_list, timer);
+    }
+}
+
+uint32_t eventOS_event_timer_ticks(void)
+{
+    uint32_t ret_val;
+    // Enter/exit critical is a bit clunky, but necessary on 16-bit platforms,
+    // which won't be able to do an atomic 32-bit read.
+    platform_enter_critical();
+    ret_val = timer_sys_ticks;
+    platform_exit_critical();
+    return ret_val;
+}
+
+/* Called internally with lock held */
+static void timer_sys_add(sys_timer_struct_s *timer)
+{
+    uint32_t at = timer->launch_time;
+
+    // Find first timer scheduled to run after us, and insert before it.
+    // (This means timers scheduled for same time run in order of request)
+    ns_list_foreach(sys_timer_struct_s, t, &system_timer_list) {
+        if (TICKS_BEFORE(at, t->launch_time)) {
+            ns_list_add_before(&system_timer_list, t, timer);
+            return;
+        }
+    }
+
+    // Didn't insert before another timer, so must be last.
+    ns_list_add_to_end(&system_timer_list, timer);
+}
+
+/* Called internally with lock held */
+static arm_event_storage_t *eventOS_event_timer_request_at_(const arm_event_t *event, uint32_t at, uint32_t period)
+{
+    // Because we use user-allocated events, they must get delivered to avoid
+    // a leak. Previously this call queued timers for invalid tasks, then they
+    // would go undelivered. Now it returns an error.
+    if (!event_tasklet_handler_id_valid(event->receiver)) {
+        return NULL;
+    }
+
+    sys_timer_struct_s *timer = timer_struct_get();
+    if (!timer) {
+        return NULL;
+    }
+
+    timer->event.data = *event;
+    timer->event.allocator = ARM_LIB_EVENT_TIMER;
+    timer->event.state = ARM_LIB_EVENT_UNQUEUED;
+    timer->launch_time = at;
+    timer->period = period;
+
+    if (TICKS_BEFORE_OR_AT(at, timer_sys_ticks)) {
+        eventOS_event_send_timer_allocated(&timer->event);
+    } else {
+        timer_sys_add(timer);
+    }
+
+    return &timer->event;
+}
+
+arm_event_storage_t *eventOS_event_timer_request_at(const arm_event_t *event, uint32_t at)
+{
+    platform_enter_critical();
+
+    arm_event_storage_t *ret = eventOS_event_timer_request_at_(event, at, 0);
+
+    platform_exit_critical();
+
+    return ret;
+}
+
+arm_event_storage_t *eventOS_event_timer_request_in(const arm_event_t *event, int32_t in)
+{
+    platform_enter_critical();
+
+    arm_event_storage_t *ret = eventOS_event_timer_request_at_(event, timer_sys_ticks + in, 0);
+
+    platform_exit_critical();
+
+    return ret;
+
+}
+
+arm_event_storage_t *eventOS_event_timer_request_every(const arm_event_t *event, int32_t period)
+{
+    if (period <= 0) {
+        return NULL;
+    }
+
+    platform_enter_critical();
+
+    arm_event_storage_t *ret = eventOS_event_timer_request_at_(event, timer_sys_ticks + period, period);
+
+    platform_exit_critical();
+
+    return ret;
+
+}
+
+int8_t eventOS_event_timer_request(uint8_t event_id, uint8_t event_type, int8_t tasklet_id, uint32_t time)
+{
+    const arm_event_t event = {
+        .event_id = event_id,
+        .event_type = event_type,
+        .receiver = tasklet_id,
+        .sender = 0,
+        .data_ptr = NULL,
+        .event_data = 0,
+        .priority = ARM_LIB_MED_PRIORITY_EVENT,
+    };
+
+    // Legacy time behaviour preserved
+
+    // Note that someone wanting 20ms gets 2 ticks, thanks to this test. 30ms would be 4 ticks.
+    // And why shouldn't they be able to get a 1-tick callback?
+    if (time > 2 * TIMER_SYS_TICK_PERIOD) {
+        time /= TIMER_SYS_TICK_PERIOD;
+        // XXX Why this? Someone wanting 50ms shouldn't get 6 ticks. Round to nearest, maybe?
+        time++;
+    } else {
+        time = 2;
+    }
+
+    platform_enter_critical();
+    arm_event_storage_t *ret = eventOS_event_timer_request_at_(&event, timer_sys_ticks + time, 0);
+    platform_exit_critical();
+    return ret?0:-1;
+}
+
+int8_t eventOS_event_timer_cancel(uint8_t event_id, int8_t tasklet_id)
+{
+    platform_enter_critical();
+
+    /* First check pending timers */
+    ns_list_foreach(sys_timer_struct_s, cur, &system_timer_list) {
+        if (cur->event.data.receiver == tasklet_id && cur->event.data.event_id == event_id) {
+            eventOS_cancel(&cur->event);
+            goto done;
+        }
+    }
+
+    /* No pending timer, so check for already-pending event */
+    arm_event_storage_t *event = eventOS_event_find_by_id_critical(tasklet_id, event_id);
+    if (event && event->allocator == ARM_LIB_EVENT_TIMER) {
+        eventOS_cancel(event);
+        goto done;
+    }
+
+    /* No match found */
+    platform_exit_critical();
+    return -1;
+
+done:
+    platform_exit_critical();
+    return 0;
+}
+
+uint32_t eventOS_event_timer_shortest_active_timer(void)
+{
+    uint32_t ret_val = 0;
+
+    platform_enter_critical();
+    sys_timer_struct_s *first = ns_list_get_first(&system_timer_list);
+    if (first == NULL) {
+        // Weird API has 0 for "no events"
+        ret_val = 0;
+    } else if (TICKS_BEFORE_OR_AT(first->launch_time, timer_sys_ticks)) {
+        // Which means an immediate/overdue event has to be 1
+        ret_val = 1;
+    } else {
+        ret_val = first->launch_time - timer_sys_ticks;
+    }
+
+    platform_exit_critical();
+    return eventOS_event_timer_ticks_to_ms(ret_val);
+}
+
+void system_timer_tick_update(uint32_t ticks)
+{
+    platform_enter_critical();
+    //Keep runtime time
+    timer_sys_ticks += ticks;
+    ns_list_foreach_safe(sys_timer_struct_s, cur, &system_timer_list) {
+        if (TICKS_BEFORE_OR_AT(cur->launch_time, timer_sys_ticks)) {
+            // Unthread from our list
+            ns_list_remove(&system_timer_list, cur);
+            // Make it an event (can't fail - no allocation)
+            // event system will call our timer_sys_event_free on event delivery.
+            eventOS_event_send_timer_allocated(&cur->event);
+        } else {
+            // List is ordered, so as soon as we see a later event, we're done.
+            break;
+        }
+    }
+
+    platform_exit_critical();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/sal-stack-nanostack-eventloop/source/timer_sys.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+#ifndef _PL_NANO_TIMER_SYS_H_
+#define _PL_NANO_TIMER_SYS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "eventOS_event.h"
+
+/* We borrow base event storage, including its list link, and add a time field */
+typedef struct sys_timer_struct_s {
+    arm_event_storage_t event;
+    uint32_t launch_time; // tick value
+    uint32_t period;
+} sys_timer_struct_s;
+
+
+/**
+ * Initialize system timer
+ * */
+extern void timer_sys_init(void);
+
+extern uint32_t timer_get_runtime_ticks(void);
+int8_t timer_sys_wakeup(void);
+void timer_sys_disable(void);
+void timer_sys_event_free(struct arm_event_storage *event);
+
+// This require lock to be held
+void timer_sys_event_cancel_critical(struct arm_event_storage *event);
+
+/**
+ * System Timer update and synch after sleep
+ *
+ * \param ticks Time in 10 ms resolution
+ *
+ * \return none
+ *
+ * */
+void system_timer_tick_update(uint32_t ticks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_PL_NANO_TIMER_SYS_H_*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/CertificateParser.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,66 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include <stdint.h>
+#include "pal.h"
+#include "mbed-trace/mbed_trace.h"
+
+#define TRACE_GROUP "mClt"
+
+bool extract_field_from_certificate(const uint8_t* cer, size_t cer_len, const char *field, char* value)
+{
+#if 1 // TODO : Uncomment once PAL has feature to extract "L" from certificate
+    tr_debug("extract_field_from_certificate");
+
+    palX509Attr_t attr = PAL_X509_L_ATTR;
+    if (strcmp(field,"CN") == 0) {
+        attr = PAL_X509_CN_ATTR;
+    } else if (strcmp(field,"L") == 0) {
+        attr = PAL_X509_L_ATTR;
+    } else {
+        return false;
+    }
+
+    palX509Handle_t cert = NULL;
+    size_t len = 0;
+    palStatus_t ret = pal_x509Initiate(&cert);
+    if (ret != PAL_SUCCESS) {
+        tr_error("extract_field_from_certificate - cert init failed: %d", (int)ret);
+        pal_x509Free(&cert);
+        return false;
+    }
+    ret = pal_x509CertParse(cert, cer, cer_len);
+    if (ret != PAL_SUCCESS) {
+        tr_error("extract_field_from_certificate - cert parse failed: %d", (int)ret);
+        pal_x509Free(&cert);
+        return false;
+    }    
+    ret = pal_x509CertGetAttribute(cert, attr, value, 64, &len);
+    if (ret != PAL_SUCCESS) {
+        tr_error("extract_field_from_certificate - cert attr get failed: %d", (int)ret);
+        pal_x509Free(&cert);
+        return false;
+    }
+    pal_x509Free(&cert);
+    return true;
+#else
+    return false;
+#endif
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/CloudClientStorage.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,359 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include <string.h>
+#include <assert.h>
+#include "key_config_manager.h"
+#include "CloudClientStorage.h"
+#include "mbed-trace/mbed_trace.h"
+#include "mbed-client-libservice/common_functions.h"
+
+#define TRACE_GROUP "mClt"
+
+ccs_status_e uninitialize_storage(void)
+{
+    tr_debug("CloudClientStorage::uninitialize_storage");
+
+    kcm_status_e status = kcm_finalize();
+    if(status != KCM_STATUS_SUCCESS) {
+        tr_error("CloudClientStorage::uninitialize_storage - error %d", status);
+        return CCS_STATUS_ERROR;
+    }
+    return CCS_STATUS_SUCCESS;
+}
+
+ccs_status_e initialize_storage(void)
+{
+    tr_debug("CloudClientStorage::initialize_storage");
+    kcm_status_e status = kcm_init();
+    if(status != KCM_STATUS_SUCCESS) {
+        tr_error("CloudClientStorage::::initialize_storage - error %d", status);
+        return CCS_STATUS_ERROR;
+    }
+    return CCS_STATUS_SUCCESS;
+}
+
+ccs_status_e ccs_get_string_item(const char* key,
+                                 uint8_t *buffer,
+                                 const size_t buffer_size,
+                                 ccs_item_type_e item_type)
+{
+    size_t len = 0;
+    ccs_status_e status = ccs_get_item(key, buffer, buffer_size - 1, &len, item_type);
+
+    if (status == CCS_STATUS_SUCCESS) {
+        // Null terminate after buffer value
+        buffer[len] = 0;
+    }
+
+    return status;
+}
+
+ccs_status_e ccs_check_item(const char* key, ccs_item_type_e item_type)
+{
+    if (key == NULL) {
+        return CCS_STATUS_ERROR;
+    }
+
+    size_t real_size = 0;
+    kcm_status_e kcm_status = kcm_item_get_data_size((const uint8_t*)key, strlen(key), item_type, &real_size);
+    if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND) {
+        return CCS_STATUS_KEY_DOESNT_EXIST;
+    }
+    return CCS_STATUS_SUCCESS;
+}
+
+ccs_status_e ccs_delete_item(const char* key, ccs_item_type_e item_type)
+{
+    if (key == NULL) {
+        tr_error("CloudClientStorage::ccs_delete_item error, invalid parameters");
+        return CCS_STATUS_ERROR;
+    }
+
+    ccs_status_e status = ccs_check_item(key, item_type);
+    if (status == CCS_STATUS_KEY_DOESNT_EXIST) {
+        // No need to call delete as item does not exist.
+        tr_debug("CloudClientStorage::ccs_delete_item [%s], type [%d] does not exist.", key, item_type);
+        return CCS_STATUS_SUCCESS;
+    } else if (status == CCS_STATUS_ERROR) {
+        return CCS_STATUS_ERROR;
+    }
+
+    // Delete parameter from storage
+    tr_debug("CloudClientStorage::ccs_delete_item [%s], type [%d] ", key, item_type);
+    kcm_status_e kcm_status = kcm_item_delete((const uint8_t*)key,
+                                  strlen(key),
+                                  item_type);
+
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        tr_debug("CloudClientStorage::ccs_delete_item [%s] kcm get error %d", key, kcm_status);
+        return CCS_STATUS_ERROR;
+    }
+
+    return CCS_STATUS_SUCCESS;
+}
+
+ccs_status_e ccs_item_size(const char* key, size_t* size_out, ccs_item_type_e item_type)
+{
+    if (key == NULL) {
+        tr_error("CloudClientStorage::ccs_item_size error, invalid parameters");
+        return CCS_STATUS_ERROR;
+    }
+
+    tr_debug("CloudClientStorage::ccs_item_size [%s], item [%d]", key, item_type);
+
+    // Get kcm item size
+    kcm_status_e kcm_status = kcm_item_get_data_size((const uint8_t*)key,
+                                         strlen(key),
+                                         item_type,
+                                         size_out);
+
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        tr_debug("CloudClientStorage::ccs_item_size [%s] kcm get error %d", key, kcm_status);
+        return CCS_STATUS_ERROR;
+    }
+
+    return CCS_STATUS_SUCCESS;
+}
+
+ccs_status_e ccs_get_item(const char* key,
+                          uint8_t *buffer,
+                          const size_t buffer_size,
+                          size_t *value_length,
+                          ccs_item_type_e item_type)
+{
+    if (key == NULL || buffer == NULL || buffer_size == 0) {
+        tr_error("CloudClientStorage::ccs_get_item error, invalid parameters");
+        return CCS_STATUS_ERROR;
+    }
+
+    tr_debug("CloudClientStorage::ccs_get_item [%s], type [%d]", key, item_type);
+
+    kcm_status_e kcm_status = kcm_item_get_data((const uint8_t*)key,
+                                    strlen(key),
+                                    item_type,
+                                    buffer,
+                                    buffer_size,
+                                    value_length);
+
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        tr_debug("CloudClientStorage::ccs_get_item [%s] kcm get error %d", key, kcm_status);
+        return CCS_STATUS_ERROR;
+    }
+
+    return CCS_STATUS_SUCCESS;
+}
+
+ccs_status_e ccs_set_item(const char* key,
+                          const uint8_t *buffer,
+                          const size_t buffer_size,
+                          ccs_item_type_e item_type)
+{
+    if (key == NULL || buffer == NULL || buffer_size == 0) {
+        tr_error("CloudClientStorage::ccs_set_item error, invalid parameters");
+        return CCS_STATUS_ERROR;
+    }
+
+    tr_debug("CloudClientStorage::ccs_set_item kcm [%s], type [%d]", key, item_type);
+
+    kcm_status_e kcm_status = kcm_item_store((const uint8_t*)key,
+                                 strlen(key),
+                                 item_type,
+                                 false,
+                                 buffer,
+                                 buffer_size,
+                                 NULL);
+
+    if (kcm_status == KCM_CRYPTO_STATUS_PRIVATE_KEY_VERIFICATION_FAILED) {
+        tr_error("CloudClientStorage::ccs_set_item kcm validation error");
+        return CCS_STATUS_VALIDATION_FAIL;
+    }
+    else if (kcm_status != KCM_STATUS_SUCCESS) {
+        tr_debug("CloudClientStorage::ccs_set_item kcm [%s] get error %d", key, kcm_status);
+        return CCS_STATUS_ERROR;
+    }
+
+    return CCS_STATUS_SUCCESS;
+}
+
+void *ccs_create_certificate_chain(const char *chain_file_name, size_t chain_len)
+{
+    kcm_status_e kcm_status;
+    kcm_cert_chain_handle chain_handle;
+
+    kcm_status = kcm_cert_chain_create(&chain_handle,
+                                       (uint8_t*)chain_file_name,
+                                       strlen(chain_file_name),
+                                       chain_len,
+                                       false);
+
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        tr_error("CloudClientStorage::ccs_create_certificate_chain - error %d", kcm_status);
+        return NULL;
+    } else {
+        return (void*)chain_handle;
+    }
+}
+
+void *ccs_open_certificate_chain(const char *chain_file_name, size_t *chain_size)
+{
+    kcm_status_e kcm_status;
+    kcm_cert_chain_handle handle;
+
+    kcm_status = kcm_cert_chain_open(&handle,
+                                     (uint8_t*)chain_file_name,
+                                     strlen(chain_file_name),
+                                     chain_size);
+
+    if (kcm_status == KCM_STATUS_SUCCESS) {
+        return (void*)handle;
+    } else {
+        tr_error("CloudClientStorage::ccs_open_certificate_chain - error %d", kcm_status);
+        return NULL;
+    }
+}
+
+ccs_status_e ccs_get_next_cert_chain(void *chain_handle, void *cert_data, size_t *data_size)
+{
+    kcm_status_e kcm_status;
+    size_t max_size = 1024;
+
+    kcm_status = kcm_cert_chain_get_next_size((kcm_cert_chain_handle *) chain_handle, data_size);
+
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        tr_error("CloudClientStorage::ccs_get_next_cert_chain - get_next_size error %d", kcm_status);
+        data_size = 0;
+        return CCS_STATUS_ERROR;
+    }
+
+
+    kcm_status = kcm_cert_chain_get_next_data((kcm_cert_chain_handle *) chain_handle, (uint8_t*)cert_data, max_size, data_size);
+
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        tr_error("CloudClientStorage::ccs_get_next_cert_chain - get_next_data error %d", kcm_status);
+        data_size = 0;
+        return CCS_STATUS_ERROR;
+    } else {
+        return CCS_STATUS_SUCCESS;
+    }
+}
+
+ccs_status_e ccs_close_certificate_chain(void *chain_handle)
+{
+    kcm_status_e kcm_status;
+    kcm_cert_chain_handle *handle = (kcm_cert_chain_handle *) chain_handle;
+    kcm_status = kcm_cert_chain_close(handle);
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        tr_error("CloudClientStorage::ccs_close_certificate_chain - error %d", kcm_status);
+        return CCS_STATUS_ERROR;
+    } else {
+        return CCS_STATUS_SUCCESS;
+    }
+}
+
+ccs_status_e ccs_add_next_cert_chain(void *chain_handle, const uint8_t *cert_data, size_t data_size)
+{
+    kcm_status_e kcm_status;
+    kcm_status = kcm_cert_chain_add_next((kcm_cert_chain_handle *) chain_handle, cert_data, data_size);
+
+    if (kcm_status != KCM_STATUS_SUCCESS) {
+        tr_error("CloudClientStorage::ccs_add_next_cert_chain - error %d", kcm_status);
+        return CCS_STATUS_ERROR;
+    } else {
+        return CCS_STATUS_SUCCESS;
+    }
+}
+
+ccs_status_e ccs_parse_cert_chain_and_store(const uint8_t *cert_chain_name,
+                                            const size_t cert_chain_name_len,
+                                            const uint8_t *cert_chain_data,
+                                            const uint16_t cert_chain_data_len)
+{
+    assert(cert_chain_data);
+    assert(cert_chain_data_len > 0);
+
+    const uint8_t *ptr = cert_chain_data;
+    uint8_t version = *ptr++;
+    uint8_t chain_length = *ptr++;
+    ccs_status_e success = CCS_STATUS_SUCCESS;
+    kcm_cert_chain_handle chain_handle;
+    kcm_status_e status = KCM_STATUS_ERROR;
+
+    // Check overflow
+    if (ptr - cert_chain_data > cert_chain_data_len) {
+        success = CCS_STATUS_VALIDATION_FAIL;
+    }
+
+    // Check version is correct and there are certs in the chain
+    if (version != 1 || chain_length == 0) {
+        success = CCS_STATUS_VALIDATION_FAIL;
+    }
+
+    // Create KCM cert chain
+    if (success == CCS_STATUS_SUCCESS) {
+        status = kcm_cert_chain_create(&chain_handle,
+                                       cert_chain_name,
+                                       cert_chain_name_len,
+                                       chain_length,
+                                       false);
+        tr_debug("Cert chain create %d", status);
+        if (status != KCM_STATUS_SUCCESS) {
+            success = CCS_STATUS_ERROR;
+        }
+    }
+
+    if (success == CCS_STATUS_SUCCESS) {
+        for (uint8_t i = 0; i < chain_length; i++) {
+            // Parse certificate length (2 bytes)
+            uint16_t cert_len = common_read_16_bit(ptr);
+            ptr += 2;
+            // Check overflow
+            if (ptr - cert_chain_data > cert_chain_data_len) {
+                success = CCS_STATUS_VALIDATION_FAIL;
+                break;
+            }
+
+            // Store certificate
+            tr_debug("Storing cert\r\n%s", tr_array(ptr, cert_len));
+            status = kcm_cert_chain_add_next(chain_handle, ptr, cert_len);
+            if (status != KCM_STATUS_SUCCESS) {
+                success = CCS_STATUS_ERROR;
+                break;
+            }
+
+            ptr += cert_len;
+
+            // Check overflow
+            if (ptr - cert_chain_data > cert_chain_data_len) {
+                success = CCS_STATUS_VALIDATION_FAIL;
+                break;
+            }
+        }
+    }
+
+    status = kcm_cert_chain_close(chain_handle);
+    if (status != KCM_STATUS_SUCCESS) {
+        success = CCS_STATUS_ERROR;
+    }
+
+    if (success != CCS_STATUS_SUCCESS) {
+        kcm_cert_chain_delete(cert_chain_name, cert_chain_name_len);
+    }
+
+    return success;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/ConnectorClient.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1350 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+// fixup the compilation on ARMCC for PRId32
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include "include/ConnectorClient.h"
+#include "include/CloudClientStorage.h"
+#include "include/CertificateParser.h"
+#include "MbedCloudClient.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2minterfacefactory.h"
+#include "mbed-client/m2mdevice.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-trace/mbed_trace.h"
+#include "factory_configurator_client.h"
+#include "key_config_manager.h"
+#include "mbed-client/uriqueryparser.h"
+
+#include <assert.h>
+#include <string>
+#include <stdio.h>
+
+#include "ns_hal_init.h"
+
+#ifdef MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
+#define MBED_CLIENT_EVENT_LOOP_SIZE MBED_CONF_MBED_CLIENT_EVENT_LOOP_SIZE
+#else
+#define MBED_CLIENT_EVENT_LOOP_SIZE 1024
+#endif
+
+#define TRACE_GROUP "mClt"
+
+#define INTERNAL_ENDPOINT_PARAM     "&iep="
+#define DEFAULT_ENDPOINT            "endpoint"
+#define INTERFACE_ERROR             "Client interface is not created. Restart"
+#define CREDENTIAL_ERROR            "Failed to read credentials from storage"
+#define DEVICE_NOT_PROVISIONED      "Device not provisioned"
+#define ERROR_NO_MEMORY             "Not enough memory to store LWM2M credentials"
+
+#ifndef MBED_CLIENT_DISABLE_EST_FEATURE
+#define ERROR_EST_ENROLLMENT_REQUEST_FAILED   "EST enrollment request failed"
+#define LWM2M_CSR_SUBJECT_FORMAT              "L=%s,OU=%s,CN=%s"
+#endif
+
+// XXX: nothing here yet
+class EventData {
+
+};
+
+static int read_callback_helper(const char *key, void *buffer, size_t *buffer_len)
+{
+    size_t cert_size = 0;
+    if (strcmp(key, g_fcc_lwm2m_device_private_key_name) == 0 ||
+        strcmp(key, g_fcc_bootstrap_device_private_key_name) == 0) {
+        if (ccs_item_size(key, buffer_len, CCS_PRIVATE_KEY_ITEM) != CCS_STATUS_SUCCESS) {
+            *buffer_len = 0;
+            return CCS_STATUS_ERROR;
+        }
+
+        if (ccs_get_item(key, (uint8_t*)buffer, *buffer_len, &cert_size, CCS_PRIVATE_KEY_ITEM) != CCS_STATUS_SUCCESS) {
+            *buffer_len = 0;
+            return CCS_STATUS_ERROR;
+        }
+    } else {
+        if (ccs_item_size(key, buffer_len, CCS_CERTIFICATE_ITEM) != CCS_STATUS_SUCCESS) {
+            *buffer_len = 0;
+            return CCS_STATUS_ERROR;
+        }
+
+        if (ccs_get_item(key, (uint8_t*)buffer, *buffer_len, &cert_size, CCS_CERTIFICATE_ITEM) != CCS_STATUS_SUCCESS) {
+            *buffer_len = 0;
+            return CCS_STATUS_ERROR;
+        }
+    }
+
+    *buffer_len = cert_size;
+
+    return CCS_STATUS_SUCCESS;
+}
+
+static bool write_security_object_data_to_kcm(const M2MResourceBase& resource, const uint8_t *buffer, const size_t buffer_size, void */*client_args*/)
+{
+    ccs_status_e status = CCS_STATUS_ERROR;
+    uint32_t resource_id = resource.name_id();
+    uint16_t object_instance_id = resource.object_instance_id();
+
+    switch (resource_id) {
+        case M2MSecurity::PublicKey:
+            if (object_instance_id == M2MSecurity::Bootstrap) {
+                ccs_delete_item(g_fcc_bootstrap_device_certificate_name, CCS_CERTIFICATE_ITEM);
+                status = ccs_set_item(g_fcc_bootstrap_device_certificate_name, buffer, buffer_size, CCS_CERTIFICATE_ITEM);
+            } else {
+                ccs_delete_item(g_fcc_lwm2m_device_certificate_name, CCS_CERTIFICATE_ITEM);
+                status = ccs_set_item(g_fcc_lwm2m_device_certificate_name, buffer, buffer_size, CCS_CERTIFICATE_ITEM);
+            }
+            break;
+
+        case M2MSecurity::ServerPublicKey:
+            if (object_instance_id == M2MSecurity::Bootstrap) {
+                ccs_delete_item(g_fcc_bootstrap_server_ca_certificate_name, CCS_CERTIFICATE_ITEM);
+                status = ccs_set_item(g_fcc_bootstrap_server_ca_certificate_name, buffer, buffer_size, CCS_CERTIFICATE_ITEM);
+            } else {
+                ccs_delete_item(g_fcc_lwm2m_server_ca_certificate_name, CCS_CERTIFICATE_ITEM);
+                status = ccs_set_item(g_fcc_lwm2m_server_ca_certificate_name, buffer, buffer_size, CCS_CERTIFICATE_ITEM);
+            }
+            break;
+
+        case M2MSecurity::Secretkey:
+            if (object_instance_id == M2MSecurity::Bootstrap) {
+                ccs_delete_item(g_fcc_bootstrap_device_private_key_name, CCS_PRIVATE_KEY_ITEM);
+                status = ccs_set_item(g_fcc_bootstrap_device_private_key_name, buffer, buffer_size, CCS_PRIVATE_KEY_ITEM);
+            } else {
+                ccs_delete_item(g_fcc_lwm2m_device_private_key_name, CCS_PRIVATE_KEY_ITEM);
+                status = ccs_set_item(g_fcc_lwm2m_device_private_key_name, buffer, buffer_size, CCS_PRIVATE_KEY_ITEM);
+            }
+            break;
+
+        default:
+            break;
+    }
+
+    return (status == CCS_STATUS_SUCCESS) ? true : false;
+}
+
+static int read_security_object_data_from_kcm(const M2MResourceBase& resource, void *buffer, size_t *buffer_len, void */*client_args*/)
+{
+    uint32_t resource_id = resource.name_id();
+    uint16_t object_instance_id = resource.object_instance_id();
+    switch (resource_id) {
+        case M2MSecurity::PublicKey:
+            if (object_instance_id == M2MSecurity::Bootstrap) {
+                return read_callback_helper(g_fcc_bootstrap_device_certificate_name, buffer, buffer_len);
+            } else {
+                return read_callback_helper(g_fcc_lwm2m_device_certificate_name, buffer, buffer_len);
+            }
+
+        case M2MSecurity::ServerPublicKey:
+            if (object_instance_id == M2MSecurity::Bootstrap) {
+                return read_callback_helper(g_fcc_bootstrap_server_ca_certificate_name, buffer, buffer_len);
+            } else {
+                return read_callback_helper(g_fcc_lwm2m_server_ca_certificate_name, buffer, buffer_len);
+            }
+
+        case M2MSecurity::Secretkey:
+            if (object_instance_id == M2MSecurity::Bootstrap) {
+                return read_callback_helper(g_fcc_bootstrap_device_private_key_name, buffer, buffer_len);
+            } else {
+                return read_callback_helper(g_fcc_lwm2m_device_private_key_name, buffer, buffer_len);
+            }
+
+        default:
+            break;
+    }
+
+    return CCS_STATUS_ERROR;
+}
+
+static int open_certificate_chain_callback(const M2MResourceBase& resource, void */*buffer*/, size_t *chain_size, void *client_args)
+{
+    void *handle = NULL;
+    uint16_t object_instance_id = resource.object_instance_id();
+    ConnectorClient *client = (ConnectorClient*)client_args;
+    if (object_instance_id == M2MSecurity::Bootstrap) {
+        handle = ccs_open_certificate_chain(g_fcc_bootstrap_device_certificate_name, chain_size);
+        client->set_certificate_chain_handle(handle);
+    } else {
+        handle = ccs_open_certificate_chain(g_fcc_lwm2m_device_certificate_name, chain_size);
+        client->set_certificate_chain_handle(handle);
+    }
+
+    return (handle) ? CCS_STATUS_SUCCESS : CCS_STATUS_ERROR;
+}
+
+static int read_certificate_chain_callback(const M2MResourceBase& /*resource*/, void *buffer, size_t *buffer_len, void *client_args)
+{
+    ConnectorClient *client = (ConnectorClient*) client_args;
+    ccs_status_e status = CCS_STATUS_ERROR;
+    if (client->certificate_chain_handle()) {
+        status = ccs_get_next_cert_chain(client->certificate_chain_handle(), buffer, buffer_len);
+    }
+
+    return status;
+}
+
+static int close_certificate_chain_callback(const M2MResourceBase& /*resource*/, void */*buffer*/, size_t *, void *client_args)
+{
+    ccs_status_e status = CCS_STATUS_ERROR;
+    ConnectorClient *client = (ConnectorClient*) client_args;
+    if (client->certificate_chain_handle()) {
+        status = ccs_close_certificate_chain(client->certificate_chain_handle());
+        client->set_certificate_chain_handle(NULL);
+    }
+    return status;
+}
+
+ConnectorClient::ConnectorClient(ConnectorClientCallback* callback)
+: _callback(callback),
+  _current_state(State_Bootstrap_Start),
+  _event_generated(false), _state_engine_running(false),
+  _interface(NULL), _security(NULL),
+  _endpoint_info(M2MSecurity::Certificate), _client_objs(NULL),
+  _rebootstrap_timer(*this), _bootstrap_security_instance(1), _lwm2m_security_instance(0), _certificate_chain_handle(NULL)
+{
+    assert(_callback != NULL);
+
+    // XXX: this initialization sequence needs more work, as doing the allocations
+    // and static initializations from constructor is really troublesome.
+    // All this needs to be moved to the separate setup() call.
+
+    // The ns_hal_init() needs to be called by someone before create_interface(),
+    // as it will also initialize the tasklet.
+    ns_hal_init(NULL, MBED_CLIENT_EVENT_LOOP_SIZE, NULL, NULL);
+
+    // Create the lwm2m server security object we need always
+    _security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer);
+    _interface = M2MInterfaceFactory::create_interface(*this,
+                                                      DEFAULT_ENDPOINT,                     // endpoint name string
+                                                      MBED_CLOUD_CLIENT_ENDPOINT_TYPE,      // endpoint type string
+                                                      MBED_CLOUD_CLIENT_LIFETIME,           // lifetime
+                                                      MBED_CLOUD_CLIENT_LISTEN_PORT,        // listen port
+                                                      _endpoint_info.account_id,            // domain string
+                                                      transport_mode(),                     // binding mode
+                                                      M2MInterface::LwIP_IPv4);             // network stack
+
+    initialize_storage();
+}
+
+
+ConnectorClient::~ConnectorClient()
+{
+    uninitialize_storage();
+    M2MDevice::delete_instance();
+    M2MSecurity::delete_instance();
+    delete _interface;
+}
+
+void ConnectorClient::start_bootstrap()
+{
+    tr_debug("ConnectorClient::start_bootstrap()");
+    assert(_callback != NULL);
+    init_security_object();
+    // Stop rebootstrap timer if it was running
+    _rebootstrap_timer.stop_timer();
+
+    if (create_bootstrap_object()) {
+        _interface->update_endpoint(_endpoint_info.endpoint_name);
+        _interface->update_domain(_endpoint_info.account_id);
+        internal_event(State_Bootstrap_Start);
+    } else {
+        tr_error("ConnectorClient::start_bootstrap() - bootstrap object fail");
+    }
+    state_engine();
+}
+
+void ConnectorClient::start_registration(M2MBaseList* client_objs)
+{
+    tr_debug("ConnectorClient::start_registration()");
+    assert(_callback != NULL);
+    init_security_object();
+    _client_objs = client_objs;
+
+    // XXX: actually this call should be external_event() to match the pattern used in other m2m classes
+    create_register_object();
+    if(_security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) {
+        _interface->update_endpoint(_endpoint_info.endpoint_name);
+        _interface->update_domain(_endpoint_info.account_id);
+        internal_event(State_Registration_Start);
+    } else {
+        tr_error("ConnectorClient::start_registration(): failed to create objs");
+        _callback->connector_error(M2MInterface::InvalidParameters, INTERFACE_ERROR);
+    }
+    state_engine();
+}
+
+M2MInterface * ConnectorClient::m2m_interface()
+{
+    return _interface;
+}
+
+void ConnectorClient::update_registration()
+{
+    if(_interface && _security && _security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) {
+        if (_client_objs != NULL) {
+            _interface->update_registration(_security, *_client_objs);
+        }
+        else {
+            _interface->update_registration(_security);
+        }
+    }
+}
+
+// generates an internal event. called from within a state
+// function to transition to a new state
+void ConnectorClient::internal_event(StartupSubStateRegistration new_state)
+{
+    tr_debug("ConnectorClient::internal_event: state: %d -> %d", _current_state, new_state);
+    _event_generated = true;
+    _current_state = new_state;
+
+    // Avoid recursive chain which eats too much of stack
+    if (!_state_engine_running) {
+        state_engine();
+    }
+}
+
+// the state engine executes the state machine states
+void ConnectorClient::state_engine(void)
+{
+    tr_debug("ConnectorClient::state_engine");
+
+    // this simple flagging gets rid of recursive calls to this method
+    _state_engine_running = true;
+
+    // while events are being generated keep executing states
+    while (_event_generated) {
+        _event_generated = false;  // event used up, reset flag
+
+        state_function(_current_state);
+    }
+
+    _state_engine_running = false;
+}
+
+void ConnectorClient::state_function(StartupSubStateRegistration current_state)
+{
+    switch (current_state) {
+        case State_Bootstrap_Start:
+            state_bootstrap_start();
+            break;
+        case State_Bootstrap_Started:
+            state_bootstrap_started();
+            break;
+        case State_Bootstrap_Success:
+            state_bootstrap_success();
+            break;
+        case State_Bootstrap_Failure:
+            state_bootstrap_failure();
+            break;
+#ifndef MBED_CLIENT_DISABLE_EST_FEATURE
+        case State_EST_Start:
+            state_est_start();
+            break;
+        case State_EST_Started:
+            state_est_started();
+            break;
+        case State_EST_Success:
+            state_est_success();
+            break;
+        case State_EST_Failure:
+            state_est_failure();
+            break;
+#endif // !MBED_CLIENT_DISABLE_EST_FEATURE
+        case State_Registration_Start:
+            state_registration_start();
+            break;
+        case State_Registration_Started:
+            state_registration_started();
+            break;
+        case State_Registration_Success:
+            state_registration_success();
+            break;
+        case State_Registration_Failure:
+            state_registration_failure();
+            break;
+        case State_Unregistered:
+            state_unregistered();
+            break;
+        default:
+            break;
+    }
+}
+
+/*
+*  Creates register server object with mbed device server address and other parameters
+*  required for client to connect to mbed device server.
+*/
+void ConnectorClient::create_register_object()
+{
+    tr_debug("ConnectorClient::create_register_object()");
+    int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
+    if (m2m_id == -1) {
+        init_security_object();
+    }
+
+    m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
+    _security->set_resource_value(M2MSecurity::BootstrapServer, M2MSecurity::M2MServer, m2m_id);
+
+    // Add ResourceID's and values to the security ObjectID/ObjectInstance
+    _security->set_resource_value(M2MSecurity::SecurityMode, _endpoint_info.mode, m2m_id);
+
+    // Allocate scratch buffer, this will be used to copy parameters from storage to security object
+    const int max_size = MAX_CERTIFICATE_SIZE;
+    uint8_t *buffer = (uint8_t*)malloc(max_size);
+    size_t real_size = 0;
+    bool success = false;
+
+    if (buffer != NULL) {
+        success = true;
+    }
+    else {
+        tr_error("ConnectorClient::create_register_object - Temporary certificate buffer allocation failed!");
+    }
+
+    // Endpoint
+    if (success) {
+        success = false;
+        char device_id[64];
+
+        size_t cert_size = max_size;
+        uint8_t certificate[MAX_CERTIFICATE_SIZE];
+        uint8_t *certificate_ptr = (uint8_t*)&certificate;
+
+        // TODO! Update to use chain api
+        _security->resource_value_buffer(M2MSecurity::PublicKey, certificate_ptr, m2m_id, &cert_size);
+        real_size = cert_size;
+        if (extract_field_from_certificate((uint8_t*)certificate, real_size, "CN", device_id)) {
+            tr_info("ConnectorClient::create_register_object - CN - endpoint_name : %s", device_id);
+            _endpoint_info.endpoint_name = String(device_id);
+            success = true;
+        } else {
+            tr_error("KEY_ENDPOINT_NAME failed.");
+        }
+    }
+
+    // Connector URL
+    if (success) {
+        success = false;
+        if (ccs_get_item(g_fcc_lwm2m_server_uri_name, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
+            tr_info("ConnectorClient::create_register_object - M2MServerUri %.*s", (int)real_size, buffer);
+            success = true;
+            _security->set_resource_value(M2MSecurity::M2MServerUri, buffer, (uint32_t)real_size, m2m_id);
+        }
+        else
+            tr_error("KEY_CONNECTOR_URL failed.");
+    }
+
+    // Try to get internal endpoint name
+    if (success) {
+        if (ccs_get_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
+            _endpoint_info.internal_endpoint_name = String((const char*)buffer, real_size);
+            tr_info("ConnectorClient::create_register_object - internal endpoint name : %s", _endpoint_info.internal_endpoint_name.c_str());
+        }
+        else {
+            tr_debug("KEY_INTERNAL_ENDPOINT failed.");
+        }
+    }
+
+    // Account ID, not mandatory
+    if (success) {
+        if (ccs_get_item(KEY_ACCOUNT_ID, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
+            tr_info("ConnectorClient::create_register_object - AccountId %.*s", (int)real_size, buffer);
+            _endpoint_info.account_id = String((const char*)buffer, real_size);
+        }
+        else
+            tr_debug("KEY_ACCOUNT_ID failed.");
+    }
+
+    free(buffer);
+    if (!success) {
+        tr_error("ConnectorClient::create_register_object - Failed to read credentials");
+        _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorFailedToReadCredentials,CREDENTIAL_ERROR);
+        // TODO: what to do with the m2mserver security instance
+    }
+}
+
+/*
+*  Creates bootstrap server object with bootstrap server address and other parameters
+*  required for connecting to mbed Cloud bootstrap server.
+*/
+bool ConnectorClient::create_bootstrap_object()
+{
+    tr_debug("ConnectorClient::create_bootstrap_object");
+    bool success = false;
+
+    // Check if bootstrap credentials are already stored in KCM
+    if (bootstrap_credentials_stored_in_kcm() && _security) {
+        int32_t bs_id = _security->get_security_instance_id(M2MSecurity::Bootstrap);
+        _security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate, bs_id);
+
+        tr_info("ConnectorClient::create_bootstrap_object - bs_id = %" PRId32, bs_id);
+        tr_info("ConnectorClient::create_bootstrap_object - use credentials from storage");
+
+        // Allocate scratch buffer, this will be used to copy parameters from storage to security object
+        size_t real_size = 0;
+        const int max_size = MAX_CERTIFICATE_SIZE;
+        uint8_t *buffer = (uint8_t*)malloc(max_size);
+        if (buffer != NULL) {
+            success = true;
+        }
+        else {
+            tr_error("ConnectorClient::create_bootstrap_object - Temporary certificate buffer allocation failed!");
+        }
+
+        // Read internal endpoint name if it exists, we need to append
+        // it to bootstrap uri if device already bootstrapped
+        uint8_t *iep = NULL;
+        if (success && ccs_get_string_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
+            iep = (uint8_t*)malloc(strlen((const char*)buffer) + strlen(INTERNAL_ENDPOINT_PARAM) + 1);
+            if (iep != NULL) {
+                strcpy((char*)iep, INTERNAL_ENDPOINT_PARAM);
+                strcat((char*)iep, (const char*)buffer);
+                tr_info("ConnectorClient::create_bootstrap_object - iep: %s", buffer);
+            }
+            //TODO: Should handle error if iep exists but allocation fails?
+        }
+
+        // Bootstrap URI
+        if (success) {
+            success = false;
+            if (ccs_get_string_item(g_fcc_bootstrap_server_uri_name, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
+                success = true;
+
+                real_size = strlen((const char*)buffer);
+                // Append iep if we 1. have it 2. it doesn't already exist in uri 3. it fits
+                if (iep &&
+                    strstr((const char*)buffer, (const char*)iep) == NULL &&
+                    (real_size + strlen((const char*)iep) + 1) <= max_size) {
+                    strcat((char*)buffer, (const char*)iep);
+                    real_size += strlen((const char*)iep) + 1;
+                }
+
+                tr_info("ConnectorClient::create_bootstrap_object - M2MServerUri %.*s", (int)real_size, buffer);
+                _security->set_resource_value(M2MSecurity::M2MServerUri, buffer, real_size, bs_id);
+            }
+        }
+
+        free(iep);
+
+        // Endpoint
+        if (success) {
+            success = false;
+            if (ccs_get_item(g_fcc_endpoint_parameter_name, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
+                success = true;
+                _endpoint_info.endpoint_name = String((const char*)buffer, real_size);
+                tr_info("ConnectorClient::create_bootstrap_object - Endpoint %s", _endpoint_info.endpoint_name.c_str());
+            }
+        }
+
+        // Account ID, not mandatory
+        if (success) {
+            if (ccs_get_item(KEY_ACCOUNT_ID, buffer, max_size, &real_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
+                _endpoint_info.account_id = String((const char*)buffer, real_size);
+                tr_info("ConnectorClient::create_bootstrap_object - AccountId %s", _endpoint_info.account_id.c_str());
+            }
+        }
+
+        free(buffer);
+
+        if (!success) {
+            tr_error("ConnectorClient::create_bootstrap_object - Failed to read credentials");
+            _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorFailedToReadCredentials,CREDENTIAL_ERROR);
+            _security->remove_object_instance(bs_id);
+        }
+    } else {
+        success = true;
+        tr_info("ConnectorClient::create_bootstrap_object - bootstrap object already done");
+    }
+
+
+    return success;
+}
+
+void ConnectorClient::state_bootstrap_start()
+{
+    tr_info("ConnectorClient::state_bootstrap_start()");
+    assert(_interface != NULL);
+    assert(_security != NULL);
+
+    _interface->bootstrap(_security);
+
+    internal_event(State_Bootstrap_Started);
+}
+
+void ConnectorClient::state_bootstrap_started()
+{
+    // this state may be useful only for verifying the callbacks?
+}
+
+void ConnectorClient::state_bootstrap_success()
+{
+    assert(_callback != NULL);
+    // Parse internal endpoint name from mDS cert
+    _callback->registration_process_result(State_Bootstrap_Success);
+}
+
+void ConnectorClient::state_bootstrap_failure()
+{
+    assert(_callback != NULL);
+    // maybe some additional canceling and/or leanup is needed here?
+    _callback->registration_process_result(State_Bootstrap_Failure);
+}
+
+#ifndef MBED_CLIENT_DISABLE_EST_FEATURE
+void ConnectorClient::state_est_start()
+{
+    // - Generate CSR from data during bootstrap phase
+    // - Call EST enrollment API from InterfaceImpl
+
+    // Update the internal endpoint name and account id to endpoint info structure
+    // as we get those during bootstrap phase
+    _endpoint_info.internal_endpoint_name = _interface->internal_endpoint_name();
+
+    int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
+    uint32_t sec_mode = M2MSecurity::SecurityNotSet;
+    if (m2m_id >= 0) {
+        sec_mode = _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id);
+
+        // We need to parse account id from lwm2m server uri query if it is not yet
+        // set in endpoint info structure
+        if (_endpoint_info.account_id.length() <= 0) {
+            String address = _security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id);
+            tr_debug("ConnectorClient::state_est_start - address: %s", address.c_str());
+            if (address.size() > 0) {
+                const char *aid = NULL;
+                const int aid_size = parse_query_parameter_value_from_uri((const char*)address.c_str(), QUERY_PARAM_AID, &aid);
+                if (aid_size > 0) {
+                    _endpoint_info.account_id.append_raw(aid, aid_size);
+                }
+            }
+        }
+    }
+
+    tr_debug("ConnectorClient::state_est_start - security instance id: %" PRId32, m2m_id);
+    tr_debug("ConnectorClient::state_est_start - ep: %s", _endpoint_info.internal_endpoint_name.c_str());
+    tr_debug("ConnectorClient::state_est_start - iep: %s", _endpoint_info.endpoint_name.c_str());
+    tr_debug("ConnectorClient::state_est_start - aid: %s", _endpoint_info.account_id.c_str());
+
+    // Check EST required parameters are in place
+    if (m2m_id < 0 ||
+        _endpoint_info.endpoint_name.length() <= 0 ||
+        _endpoint_info.internal_endpoint_name.length() <= 0 ||
+        _endpoint_info.account_id.length() <= 0) {
+        tr_error("ConnectorClient::state_est_start - Missing parameters for EST enrollment!");
+        internal_event(State_EST_Failure);
+        return;
+    }
+
+    uint32_t is_bs_server = _security->resource_value_int(M2MSecurity::BootstrapServer, m2m_id);
+    size_t public_key_size = MAX_CERTIFICATE_SIZE;
+    size_t server_key_size = MAX_CERTIFICATE_SIZE;
+    size_t private_key_size = MAX_CERTIFICATE_SIZE;
+
+    // Temp buffer for storing CSR and certificates
+    uint8_t *buffer = (uint8_t*)malloc(MAX_CERTIFICATE_SIZE);
+    size_t real_size = 0;
+    if (buffer == NULL) {
+        tr_error("ConnectorClient::state_est_start - Allocating temp buffer failed!");
+        internal_event(State_EST_Failure);
+        return;
+    }
+    uint8_t *buffer_ptr = buffer;
+
+    // TODO! Update to use chain api
+    if (_security->resource_value_buffer(M2MSecurity::PublicKey, buffer_ptr, m2m_id, &public_key_size) != 0) {
+        public_key_size = 0;
+    }
+    if (_security->resource_value_buffer(M2MSecurity::ServerPublicKey, buffer_ptr, m2m_id, &server_key_size) != 0) {
+        server_key_size = 0;
+    }
+    if (_security->resource_value_buffer(M2MSecurity::Secretkey, buffer_ptr, m2m_id, &private_key_size) != 0) {
+        private_key_size = 0;
+    }
+
+    tr_info("est check - is bs server /0/1: %" PRIu32, is_bs_server);
+    tr_info("est check - Security Mode /0/2: %" PRIu32, sec_mode);
+    tr_info("est check - Public key size /0/3: %" PRIu32, public_key_size);
+    tr_info("est check - Server Public key size /0/4: %" PRIu32, server_key_size);
+    tr_info("est check - Secret key size /0/5: %" PRIu32, private_key_size);
+
+    // Configure CSR params
+    kcm_csr_params_s csr_params;
+    int subject_size = snprintf(NULL, 0, LWM2M_CSR_SUBJECT_FORMAT,
+                                _endpoint_info.internal_endpoint_name.c_str(),
+                                _endpoint_info.account_id.c_str(),
+                                _endpoint_info.endpoint_name.c_str());
+    if (subject_size <= 0) {
+        tr_error("ConnectorClient::state_est_start - CSR Subject formatting failed!");
+        free(buffer);
+        internal_event(State_EST_Failure);
+        return;
+    }
+
+    // For null-terminator
+    subject_size++;
+
+    csr_params.subject = (char*)malloc(subject_size);
+    if (csr_params.subject == NULL) {
+        tr_error("ConnectorClient::state_est_start - CSR Subject formatting failed!");
+        free(buffer);
+        internal_event(State_EST_Failure);
+        return;
+    }
+
+    snprintf(csr_params.subject, subject_size, LWM2M_CSR_SUBJECT_FORMAT,
+             _endpoint_info.internal_endpoint_name.c_str(),
+             _endpoint_info.account_id.c_str(),
+             _endpoint_info.endpoint_name.c_str());
+
+    tr_debug("est csr subject '%s'", csr_params.subject);
+
+    csr_params.md_type = KCM_MD_SHA256;
+    csr_params.key_usage = KCM_CSR_KU_NONE;
+    csr_params.ext_key_usage = KCM_CSR_EXT_KU_NONE;
+
+    kcm_status_e status = kcm_generate_keys_and_csr(KCM_SCHEME_EC_SECP256R1,
+                                                    (const uint8_t*)g_fcc_lwm2m_device_private_key_name,
+                                                    strlen(g_fcc_lwm2m_device_private_key_name),
+                                                    NULL,
+                                                    0,
+                                                    false,
+                                                    &csr_params,
+                                                    buffer,
+                                                    MAX_CERTIFICATE_SIZE,
+                                                    &real_size,
+                                                    NULL);
+
+    free(csr_params.subject);
+
+    if (status != KCM_STATUS_SUCCESS) {
+        tr_error("ConnectorClient::state_est_start - Generating keys and csr failed!");
+        free(buffer);
+        internal_event(State_EST_Failure);
+        return;
+    }
+
+    // Update state and start the enrollment by sending the enroll request
+    internal_event(State_EST_Started);
+    _interface->post_data_request("est/sen",
+                                 false,
+                                 real_size,
+                                 buffer,
+                                 ConnectorClient::est_post_data_cb,
+                                 ConnectorClient::est_post_data_error_cb,
+                                 this);
+
+    free(buffer);
+}
+
+void ConnectorClient::state_est_started()
+{
+}
+
+void ConnectorClient::state_est_success()
+{
+    tr_info("ConnectorClient::state_est_success()");
+    _interface->finish_bootstrap();
+}
+
+void ConnectorClient::state_est_failure()
+{
+    tr_info("ConnectorClient::state_est_failure()");
+    internal_event(State_Bootstrap_Failure);
+    //Failed to store credentials, bootstrap failed
+    _callback->connector_error(M2MInterface::ESTEnrollmentFailed, ERROR_EST_ENROLLMENT_REQUEST_FAILED); // Translated to error code ConnectMemoryConnectFail
+}
+#endif /* !MBED_CLIENT_DISABLE_EST_FEATURE */
+
+void ConnectorClient::state_registration_start()
+{
+    tr_info("ConnectorClient::state_registration_start()");
+    assert(_interface != NULL);
+    assert(_security != NULL);
+    _interface->register_object(_security, *_client_objs);
+    internal_event(State_Registration_Started);
+}
+
+void ConnectorClient::state_registration_started()
+{
+    // this state may be useful only for verifying the callbacks?
+}
+
+void ConnectorClient::state_registration_success()
+{
+    assert(_callback != NULL);
+    _endpoint_info.internal_endpoint_name = _interface->internal_endpoint_name();
+
+    //The endpoint is maximum 32 character long, we put bigger buffer for future extensions
+    const int max_size = 64;
+    uint8_t buffer[max_size];
+
+    bool no_param_update = true;
+
+    if(ccs_get_string_item(KEY_INTERNAL_ENDPOINT, buffer, max_size, CCS_CONFIG_ITEM) == CCS_STATUS_SUCCESS) {
+        if (strcmp((const char*)buffer, _endpoint_info.internal_endpoint_name.c_str()) != 0) {
+            // Update is required as the stored KCM entry is different than _endpoint_info.internal_endpoint_name.
+            no_param_update = false;
+        }
+    }
+
+    // Update INTERNAL_ENDPOINT setting only if there is no such entry or the value is not matching the
+    // _endpoint_info.internal_endpoint_name.
+    if(!no_param_update) {
+        ccs_delete_item(KEY_INTERNAL_ENDPOINT, CCS_CONFIG_ITEM);
+        ccs_set_item(KEY_INTERNAL_ENDPOINT, (const uint8_t*)_endpoint_info.internal_endpoint_name.c_str(),
+                             (size_t)_endpoint_info.internal_endpoint_name.size(),
+                             CCS_CONFIG_ITEM);
+    }
+
+    _callback->registration_process_result(State_Registration_Success);
+}
+
+void ConnectorClient::state_registration_failure()
+{
+    assert(_callback != NULL);
+    // maybe some additional canceling and/or leanup is needed here?
+    _callback->registration_process_result(State_Registration_Failure);
+}
+
+void ConnectorClient::state_unregistered()
+{
+    assert(_callback != NULL);
+    _callback->registration_process_result(State_Unregistered);
+}
+
+void ConnectorClient::bootstrap_data_ready(M2MSecurity *security_object)
+{
+    tr_info("ConnectorClient::bootstrap_data_ready");
+    ccs_status_e status = CCS_STATUS_ERROR;
+    if(security_object) {
+        // Update bootstrap credentials (we could skip this if we knew whether they were updated)
+        // This will also update the address in case of first to claim
+        status = set_bootstrap_credentials(security_object);
+        if (status != CCS_STATUS_SUCCESS) {
+            // TODO: what now?
+            tr_error("ConnectorClient::bootstrap_data_ready - couldn't store bootstrap credentials");
+        }
+
+        // Clear the first to claim flag if it's active
+        if (is_first_to_claim()) {
+            status = clear_first_to_claim();
+            if (status != CCS_STATUS_SUCCESS) {
+                // TODO: what now?
+                tr_error("ConnectorClient::bootstrap_data_ready - couldn't clear first to claim flag!");
+            }
+        }
+
+        // Bootstrap might delete m2mserver security object instance completely to force bootstrap
+        // with new credentials, in that case delete the stored lwm2m credentials as well and re-bootstrap
+        if (security_object->get_security_instance_id(M2MSecurity::M2MServer) == -1) {
+            tr_info("ConnectorClient::bootstrap_data_ready() - Clearing lwm2m credentials");
+            // delete the old connector credentials when BS sends re-direction.
+            ccs_delete_item(g_fcc_lwm2m_server_uri_name, CCS_CONFIG_ITEM);
+            ccs_delete_item(g_fcc_lwm2m_server_ca_certificate_name, CCS_CERTIFICATE_ITEM);
+            ccs_delete_item(g_fcc_lwm2m_device_certificate_name, CCS_CERTIFICATE_ITEM);
+            ccs_delete_item(g_fcc_lwm2m_device_private_key_name, CCS_PRIVATE_KEY_ITEM);
+            // Start re-bootstrap timer
+            tr_info("ConnectorClient::bootstrap_data_ready() - Re-directing bootstrap in 100 milliseconds");
+            _rebootstrap_timer.start_timer(100, M2MTimerObserver::BootstrapFlowTimer, true);
+            return;
+        }
+        // Bootstrap wrote M2MServer credentials, store them and also update first to claim status if it's configured
+        else {
+#ifndef MBED_CLIENT_DISABLE_EST_FEATURE
+            int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
+            if (m2m_id >= 0 &&
+                _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id) == M2MSecurity::EST) {
+                // If EST is supported, continue to EST state to start EST enrollment
+                tr_info("ConnectorClient::bootstrap_data_ready() - Continue to EST enrollment");
+                internal_event(State_EST_Start);
+                return;
+            }
+#endif // MBED_CLIENT_DISABLE_EST_FEATURE
+            // Security mode was not EST, in that case just store the received credentials
+            tr_info("ConnectorClient::bootstrap_data_ready() - Storing lwm2m credentials");
+            status = set_connector_credentials(security_object);
+        }
+
+        if (status != CCS_STATUS_SUCCESS) {
+            internal_event(State_Bootstrap_Failure);
+            //Failed to store credentials, bootstrap failed
+            _callback->connector_error(M2MInterface::MemoryFail, ERROR_NO_MEMORY); // Translated to error code ConnectMemoryConnectFail
+            return;
+        } else {
+            tr_info("ConnectorClient::bootstrap_data_ready - set_credentials status %d", status);
+        }
+    }
+}
+
+void ConnectorClient::bootstrap_done(M2MSecurity *security_object)
+{
+    tr_info("ConnectorClient::bootstrap_done");
+    internal_event(State_Bootstrap_Success);
+}
+
+void ConnectorClient::object_registered(M2MSecurity *security_object, const M2MServer &server_object)
+{
+    internal_event(State_Registration_Success);
+}
+
+void ConnectorClient::object_unregistered(M2MSecurity *server_object)
+{
+    internal_event(State_Unregistered);
+}
+
+void ConnectorClient::registration_updated(M2MSecurity *security_object, const M2MServer & server_object)
+{
+    _callback->registration_process_result(State_Registration_Updated);
+}
+
+void ConnectorClient::error(M2MInterface::Error error)
+{
+    tr_error("ConnectorClient::error() - error: %d", error);
+    assert(_callback != NULL);
+    if (_current_state >= State_Registration_Start &&
+        use_bootstrap() &&
+        (error == M2MInterface::SecureConnectionFailed ||
+         error == M2MInterface::InvalidParameters)) {
+        tr_info("ConnectorClient::error() - Error during lwm2m registration");
+        tr_info("ConnectorClient::error() - Clearing lwm2m credentials");
+        // delete the old connector credentials when DTLS handshake fails or
+        // server rejects the registration.
+        ccs_delete_item(g_fcc_lwm2m_server_uri_name, CCS_CONFIG_ITEM);
+        ccs_delete_item(g_fcc_lwm2m_server_ca_certificate_name, CCS_CERTIFICATE_ITEM);
+        ccs_delete_item(g_fcc_lwm2m_device_certificate_name, CCS_CERTIFICATE_ITEM);
+        ccs_delete_item(g_fcc_lwm2m_device_private_key_name, CCS_PRIVATE_KEY_ITEM);
+        // Delete the lwm2m security instance
+        int32_t id = _security->get_security_instance_id(M2MSecurity::M2MServer);
+        if (id >= 0) {
+            _security->remove_object_instance(id);
+        }
+        // Start re-bootstrap timer
+        tr_info("ConnectorClient::error() - Re-bootstrapping in 100 milliseconds");
+        _rebootstrap_timer.start_timer(100, M2MTimerObserver::BootstrapFlowTimer, true);
+    }
+    else {
+        _callback->connector_error(error, _interface->error_description());
+    }
+}
+
+void ConnectorClient::value_updated(M2MBase *base, M2MBase::BaseType type)
+{
+    assert(_callback != NULL);
+    _callback->value_updated(base, type);
+}
+
+bool ConnectorClient::connector_credentials_available()
+{
+    tr_debug("ConnectorClient::connector_credentials_available");
+    // Read 1 byte of lwm2m private key, should return real_size > 0 if it exists
+    const int max_size = 1;
+    uint8_t buffer;
+    size_t real_size = 0;
+    ccs_get_item(g_fcc_lwm2m_device_private_key_name, &buffer, max_size, &real_size, CCS_PRIVATE_KEY_ITEM);
+    if (real_size > 0) {
+        return true;
+    }
+    return false;
+}
+
+bool ConnectorClient::use_bootstrap()
+{
+    tr_debug("ConnectorClient::use_bootstrap");
+    size_t real_size = 0;
+    uint8_t data[CONFIG_BOOLEAN_ITEM_SIZE] = {0};
+    uint32_t value = 0;
+    ccs_status_e status = ccs_get_item(g_fcc_use_bootstrap_parameter_name, data, CONFIG_BOOLEAN_ITEM_SIZE, &real_size, CCS_CONFIG_ITEM);
+    if (status == CCS_STATUS_SUCCESS) {
+        memcpy(&value, data, CONFIG_BOOLEAN_ITEM_SIZE);
+        // Return true if use_bootstrap is set
+        if (value == 1) {
+            return true;
+        }
+    }
+    return false;
+}
+
+
+bool ConnectorClient::get_key(const char *key, const char *endpoint, char *&key_name)
+{
+    if(key_name) {
+        free(key_name);
+        key_name = NULL;
+    }
+
+    key_name = (char*)malloc(strlen(key)+strlen(endpoint)+1);
+    if(key_name) {
+        strcpy(key_name, key);
+        strcat(key_name, endpoint);
+        tr_debug("key %s", key_name);
+        return true;
+    }
+    return false;
+}
+
+ccs_status_e ConnectorClient::set_connector_credentials(M2MSecurity *security)
+{
+    tr_debug("ConnectorClient::set_connector_credentials");
+    ccs_status_e status = CCS_STATUS_ERROR;
+
+    int32_t m2m_id = security->get_security_instance_id(M2MSecurity::M2MServer);
+    if (m2m_id == -1) {
+        return status;
+    }
+
+    size_t buffer_size = MAX_CERTIFICATE_SIZE;
+    uint8_t public_key[MAX_CERTIFICATE_SIZE];
+    uint8_t *public_key_ptr = (uint8_t*)&public_key;
+
+    // TODO! Update to use chain api
+    if (security->resource_value_buffer(M2MSecurity::PublicKey, public_key_ptr, m2m_id, &buffer_size) != 0) {
+        return status;
+    }
+
+    char device_id[64];
+    memset(device_id, 0, 64);
+    if (extract_field_from_certificate(public_key, buffer_size, "L", device_id)) {
+        tr_info("ConnectorClient::set_connector_credentials - L internal_endpoint_name : %s", device_id);
+        _endpoint_info.internal_endpoint_name = String(device_id);
+        ccs_delete_item(KEY_INTERNAL_ENDPOINT, CCS_CONFIG_ITEM);
+        status = ccs_set_item(KEY_INTERNAL_ENDPOINT,(uint8_t*)device_id, strlen(device_id), CCS_CONFIG_ITEM);
+    }
+
+    memset(device_id, 0, 64);
+    if (extract_field_from_certificate(public_key, buffer_size, "CN", device_id)) {
+        tr_info("ConnectorClient::set_connector_credentials - CN endpoint_name : %s", device_id);
+        _endpoint_info.endpoint_name = String(device_id);
+    }
+
+    if(status == CCS_STATUS_SUCCESS) {
+        ccs_status_e check_status = ccs_check_item(KEY_ACCOUNT_ID, CCS_CONFIG_ITEM);
+        // Do not call delete if KEY does not exist.
+        if ((check_status == CCS_STATUS_KEY_DOESNT_EXIST) || (check_status == CCS_STATUS_ERROR)) {
+            tr_debug("No KEY_ACCOUNT_ID stored.");
+        } else {
+            ccs_delete_item(KEY_ACCOUNT_ID, CCS_CONFIG_ITEM);
+            // AccountID optional so don't fail if unable to store
+            ccs_set_item(KEY_ACCOUNT_ID,
+                         (const uint8_t*)_endpoint_info.account_id.c_str(),
+                         (size_t)_endpoint_info.account_id.size(),
+                         CCS_CONFIG_ITEM);
+        }
+    }
+
+    if (status == CCS_STATUS_SUCCESS) {
+        status = ccs_set_item(g_fcc_lwm2m_server_uri_name,
+                              (const uint8_t*)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).c_str(),
+                              (size_t)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).size(),
+                              CCS_CONFIG_ITEM);
+    }
+
+    M2MDevice *device = M2MInterfaceFactory::create_device();
+    if (status == CCS_STATUS_SUCCESS && device) {
+        String temp = "";
+        uint32_t currenttime = (uint32_t)device->resource_value_int(M2MDevice::CurrentTime, 0);
+        uint8_t data[4];
+        memcpy(data, &currenttime, 4);
+        ccs_delete_item(g_fcc_current_time_parameter_name, CCS_CONFIG_ITEM);
+        ccs_set_item(g_fcc_current_time_parameter_name, data, 4, CCS_CONFIG_ITEM);
+
+        temp = device->resource_value_string(M2MDevice::Timezone, 0);
+        if (temp.size() > 0) {
+            ccs_delete_item(g_fcc_device_time_zone_parameter_name, CCS_CONFIG_ITEM);
+            ccs_set_item(g_fcc_device_time_zone_parameter_name, (const uint8_t*)temp.c_str(), temp.size(), CCS_CONFIG_ITEM);
+        }
+
+        temp = device->resource_value_string(M2MDevice::UTCOffset, 0);
+        if (temp.size() > 0) {
+            ccs_delete_item(g_fcc_offset_from_utc_parameter_name, CCS_CONFIG_ITEM);
+            ccs_set_item(g_fcc_offset_from_utc_parameter_name, (const uint8_t*)temp.c_str(), temp.size(), CCS_CONFIG_ITEM);
+        }
+
+        status = CCS_STATUS_SUCCESS;
+    }
+    else {
+        tr_debug("No device object to store!");
+    }
+
+    return status;
+}
+
+ccs_status_e ConnectorClient::set_bootstrap_credentials(M2MSecurity *security)
+{
+    tr_debug("ConnectorClient::set_bootstrap_credentials");
+    ccs_status_e status = CCS_STATUS_ERROR;
+
+    size_t buffer_size = MAX_CERTIFICATE_SIZE;
+    uint8_t key[MAX_CERTIFICATE_SIZE];
+    uint8_t *key_ptr = (uint8_t*)&key;
+
+    int32_t bs_id = security->get_security_instance_id(M2MSecurity::Bootstrap);
+    if (bs_id == -1) {
+        return status;
+    }
+
+    // TODO! Update to use chain api
+    if (security->resource_value_buffer(M2MSecurity::PublicKey, key_ptr, bs_id, &buffer_size) != 0) {
+        return status;
+    }
+
+    if (buffer_size) {
+        ccs_delete_item(g_fcc_bootstrap_device_certificate_name, CCS_CERTIFICATE_ITEM);
+        status = ccs_set_item(g_fcc_bootstrap_device_certificate_name,
+                                            key_ptr,
+                                            buffer_size,
+                                        CCS_CERTIFICATE_ITEM);
+        buffer_size = MAX_CERTIFICATE_SIZE;
+    }
+
+    if (status == CCS_STATUS_SUCCESS) {
+        if (security->resource_value_buffer(M2MSecurity::Secretkey, key_ptr, bs_id, &buffer_size) != 0) {
+            status = CCS_STATUS_ERROR;
+            buffer_size = 0;
+        }
+
+        if(buffer_size) {
+            ccs_delete_item(g_fcc_bootstrap_device_private_key_name, CCS_PRIVATE_KEY_ITEM);
+            status = ccs_set_item(g_fcc_bootstrap_device_private_key_name,
+                                            key_ptr,
+                                            buffer_size,
+                                            CCS_PRIVATE_KEY_ITEM);
+            buffer_size = MAX_CERTIFICATE_SIZE;
+        }
+    }
+
+    if (status == CCS_STATUS_SUCCESS) {
+        if (security->resource_value_buffer(M2MSecurity::ServerPublicKey, key_ptr, bs_id, &buffer_size) != 0) {
+            status = CCS_STATUS_ERROR;
+            buffer_size = 0;
+        }
+
+        if (buffer_size) {
+            ccs_delete_item(g_fcc_bootstrap_server_ca_certificate_name, CCS_CERTIFICATE_ITEM);
+            status = ccs_set_item(g_fcc_bootstrap_server_ca_certificate_name,
+                              key_ptr,
+                              buffer_size,
+                              CCS_CERTIFICATE_ITEM);
+        }
+    }
+
+    if(status == CCS_STATUS_SUCCESS) {
+        ccs_delete_item(g_fcc_bootstrap_server_uri_name, CCS_CONFIG_ITEM);
+        status = ccs_set_item(g_fcc_bootstrap_server_uri_name,
+                          (const uint8_t*)security->resource_value_string(M2MSecurity::M2MServerUri, bs_id).c_str(),
+                          (size_t)security->resource_value_string(M2MSecurity::M2MServerUri, bs_id).size(),
+                          CCS_CONFIG_ITEM);
+    }
+
+    return status;
+}
+
+ccs_status_e ConnectorClient::store_bootstrap_address(M2MSecurity *security)
+{
+    tr_debug("ConnectorClient::store_bootstrap_address");
+    ccs_status_e status = CCS_STATUS_ERROR;
+
+    const uint8_t *srv_address = NULL;
+    int32_t bs_id = security->get_security_instance_id(M2MSecurity::Bootstrap);
+    if (bs_id == -1) {
+        return status;
+    }
+
+    uint32_t srv_address_size = security->resource_value_buffer(M2MSecurity::M2MServerUri, srv_address, bs_id);
+
+    if(srv_address) {
+        ccs_delete_item(g_fcc_bootstrap_server_uri_name, CCS_CONFIG_ITEM);
+        status = ccs_set_item(g_fcc_bootstrap_server_uri_name,
+                                      srv_address,
+                                      (size_t)srv_address_size,
+                                      CCS_CONFIG_ITEM);
+    }
+
+    return status;
+}
+
+ccs_status_e ConnectorClient::clear_first_to_claim()
+{
+    tr_debug("ConnectorClient::clear_first_to_claim");
+    return ccs_delete_item(KEY_FIRST_TO_CLAIM, CCS_CONFIG_ITEM);
+}
+
+
+const ConnectorClientEndpointInfo *ConnectorClient::endpoint_info() const
+{
+    return &_endpoint_info;
+}
+
+bool ConnectorClient::bootstrap_credentials_stored_in_kcm()
+{
+    size_t real_size = 0;
+    ccs_status_e success = ccs_item_size(g_fcc_bootstrap_server_uri_name, &real_size, CCS_CONFIG_ITEM);
+    // Return true if bootstrap uri exists in KCM
+    if ((success == CCS_STATUS_SUCCESS) && real_size > 0) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+bool ConnectorClient::is_first_to_claim()
+{
+    size_t real_size = 0;
+    uint8_t data[CONFIG_BOOLEAN_ITEM_SIZE] = {0};
+    uint32_t value = 0;
+    ccs_status_e status = ccs_get_item(KEY_FIRST_TO_CLAIM, data, CONFIG_BOOLEAN_ITEM_SIZE, &real_size, CCS_CONFIG_ITEM);
+    if (status == CCS_STATUS_SUCCESS) {
+        memcpy(&value, data, CONFIG_BOOLEAN_ITEM_SIZE);
+        // Return true if first to claim is set
+        if (value == 1) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void ConnectorClient::timer_expired(M2MTimerObserver::Type type)
+{
+    if (type == M2MTimerObserver::BootstrapFlowTimer) {
+        start_bootstrap();
+    }
+}
+
+#ifndef MBED_CLIENT_DISABLE_EST_FEATURE
+void ConnectorClient::est_enrollment_result(bool success,
+                                            const uint8_t *payload_ptr,
+                                            const uint16_t payload_len)
+{
+    tr_debug("ConnectorClient::est_enrollment_result - %s", success ? "successful" : "failed");
+    tr_debug("ConnectorClient::est_enrollment_result - PublicKey size %d", (int)payload_len);
+
+    assert(_security != NULL);
+    int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
+    StartupSubStateRegistration state = State_EST_Failure;
+
+    if (success && payload_ptr && payload_len > 0 && m2m_id >= 0) {
+        const uint8_t *ptr = payload_ptr;
+        tr_debug("Payload start: %s", tr_array(payload_ptr, 10));
+        ccs_status_e ccs_status = ccs_parse_cert_chain_and_store((const uint8_t*)g_fcc_lwm2m_device_certificate_name,
+                                                                 strlen(g_fcc_lwm2m_device_certificate_name),
+                                                                 payload_ptr,
+                                                                 payload_len);
+        if (ccs_status != CCS_STATUS_SUCCESS) {
+            tr_error("ConnectorClient::est_enrollment_result - storing certificate chain failed!");
+        }
+        else {
+            tr_info("ConnectorClient::est_enrollment_result() - Storing lwm2m credentials");
+            if (set_connector_credentials(_security) == CCS_STATUS_SUCCESS) {
+                state = State_EST_Success;
+            }
+        }
+
+    }
+
+    internal_event(state);
+}
+
+void ConnectorClient::est_post_data_cb(const uint8_t *buffer,
+                                       size_t buffer_size,
+                                       size_t total_size,
+                                       void *context)
+{
+    ConnectorClient *cc = static_cast<ConnectorClient*>(context);
+    assert(cc);
+    cc->est_enrollment_result(true, buffer, buffer_size);
+
+}
+
+void ConnectorClient::est_post_data_error_cb(get_data_req_error_t error_code,
+                                             void *context)
+{
+    ConnectorClient *cc = static_cast<ConnectorClient*>(context);
+    assert(cc);
+    cc->est_enrollment_result(false, NULL, 0);
+}
+#endif /* !MBED_CLIENT_DISABLE_EST_FEATURE */
+
+
+M2MInterface::BindingMode ConnectorClient::transport_mode()
+{
+#ifdef MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP
+    return M2MInterface::UDP;
+#elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP
+    return M2MInterface::TCP;
+#elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE
+    return M2MInterface::UDP_QUEUE;
+#elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE
+    return M2MInterface::TCP_QUEUE;
+#else
+    return M2MInterface::UDP;
+#endif
+}
+
+void ConnectorClient::init_security_object()
+{
+    if (_security) {
+        for (int i = 0; i <= M2MSecurity::Bootstrap; i++) {
+            // _security->create_object_instance() returns NULL if object already exists
+            if (_security->create_object_instance((M2MSecurity::ServerType)i)) {
+                M2MResource* res = _security->get_resource(M2MSecurity::ServerPublicKey, i);
+                if (res) {
+                    res->set_resource_read_callback(read_security_object_data_from_kcm, this);
+                    res->set_resource_write_callback(write_security_object_data_to_kcm, this);
+                }
+
+                res = _security->get_resource(M2MSecurity::PublicKey, i);
+                if (res) {
+                    res->set_resource_read_callback(read_security_object_data_from_kcm, this);
+                    res->set_resource_write_callback(write_security_object_data_to_kcm, this);
+                }
+
+                res = _security->get_resource(M2MSecurity::Secretkey, i);
+                if (res) {
+                    res->set_resource_read_callback(read_security_object_data_from_kcm, this);
+                    res->set_resource_write_callback(write_security_object_data_to_kcm, this);
+                }
+
+                res = _security->get_resource(M2MSecurity::OpenCertificateChain, i);
+                if (res) {
+                    res->set_resource_read_callback(open_certificate_chain_callback, this);
+                }
+
+                res = _security->get_resource(M2MSecurity::ReadDeviceCertificateChain, i);
+                if (res) {
+                    res->set_resource_read_callback(read_certificate_chain_callback, this);
+                }
+
+                res = _security->get_resource(M2MSecurity::CloseCertificateChain, i);
+                if (res) {
+                    res->set_resource_read_callback(close_certificate_chain_callback, this);
+                }
+            }
+        }
+    }
+}
+
+void *ConnectorClient::certificate_chain_handle() const
+{
+    return _certificate_chain_handle;
+}
+
+void ConnectorClient::set_certificate_chain_handle(void *cert_handle)
+{
+    _certificate_chain_handle = cert_handle;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/MbedCloudClient.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,250 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "mbed-cloud-client/MbedCloudClientConfig.h"
+#include "mbed-cloud-client/MbedCloudClient.h"
+#include "mbed-cloud-client/SimpleM2MResource.h"
+
+#include "mbed-trace/mbed_trace.h"
+
+#include <assert.h>
+
+#define xstr(s) str(s)
+#define str(s) #s
+
+#define TRACE_GROUP "mClt"
+
+MbedCloudClient::MbedCloudClient()
+:_client(*this),
+ _value_callback(NULL),
+ _error_description(NULL)
+{
+}
+
+MbedCloudClient::~MbedCloudClient()
+{
+    _object_list.clear();
+}
+
+void MbedCloudClient::add_objects(const M2MObjectList& object_list)
+{
+    if(!object_list.empty()) {
+        M2MObjectList::const_iterator it;
+        it = object_list.begin();
+        for (; it!= object_list.end(); it++) {
+            _object_list.push_back((M2MBase*)*it);
+        }
+    }
+}
+
+void MbedCloudClient::add_objects(const M2MBaseList& base_list)
+{
+    if(!base_list.empty()) {
+        M2MBaseList::const_iterator it;
+        it = base_list.begin();
+        for (; it!= base_list.end(); it++) {
+            _object_list.push_back(*it);
+        }
+    }
+}
+
+void MbedCloudClient::remove_object(M2MBase *object)
+{
+    M2MBaseList::const_iterator it;
+    int found_index = -1;
+    int index;
+    tr_debug("MbedCloudClient::remove_object %p", object);
+    for (it = _object_list.begin(), index = 0; it != _object_list.end(); it++, index++) {
+        if(*it == object) {
+            found_index = index;
+            break;
+        }
+    }
+    if(found_index != -1) {
+        tr_debug("  object found at index %d", found_index);
+        _object_list.erase(found_index);
+        _client.connector_client().m2m_interface()->remove_object(object);
+    }
+}
+
+void MbedCloudClient::set_update_callback(MbedCloudClientCallback *callback)
+{
+    _value_callback = callback;
+}
+
+bool MbedCloudClient::setup(void* iface)
+{
+    tr_debug("MbedCloudClient setup()");
+    // Add objects to list
+    map<string, M2MObject*>::iterator it;
+    for (it = _objects.begin(); it != _objects.end(); it++)
+    {
+        _object_list.push_back((M2MBase*)it->second);
+    }
+    _client.connector_client().m2m_interface()->set_platform_network_handler(iface);
+
+    _client.initialize_and_register(_object_list);
+    return true;
+}
+
+void MbedCloudClient::on_registered(void(*fn)(void))
+{
+    FP0<void> fp(fn);
+    _on_registered = fp;
+}
+
+
+void MbedCloudClient::on_error(void(*fn)(int))
+{
+    _on_error = fn;
+}
+
+
+void MbedCloudClient::on_unregistered(void(*fn)(void))
+{
+    FP0<void> fp(fn);
+    _on_unregistered = fp;
+}
+
+void MbedCloudClient::on_registration_updated(void(*fn)(void))
+{
+    FP0<void> fp(fn);
+    _on_registration_updated = fp;
+}
+
+void MbedCloudClient::keep_alive()
+{
+    _client.connector_client().update_registration();
+}
+
+void MbedCloudClient::register_update()
+{
+    _client.connector_client().update_registration();
+}
+
+void MbedCloudClient::close()
+{
+    _client.connector_client().m2m_interface()->unregister_object(NULL);
+}
+
+const ConnectorClientEndpointInfo *MbedCloudClient::endpoint_info() const
+{
+    return _client.connector_client().endpoint_info();
+}
+
+void MbedCloudClient::set_queue_sleep_handler(callback_handler handler)
+{
+    _client.connector_client().m2m_interface()->set_queue_sleep_handler(handler);
+}
+
+void MbedCloudClient::set_random_number_callback(random_number_cb callback)
+{
+    _client.connector_client().m2m_interface()->set_random_number_callback(callback);
+}
+
+void MbedCloudClient::set_entropy_callback(entropy_cb callback)
+{
+    _client.connector_client().m2m_interface()->set_entropy_callback(callback);
+}
+
+bool MbedCloudClient::set_device_resource_value(M2MDevice::DeviceResource resource,
+                                                const std::string &value)
+{
+    return _client.set_device_resource_value(resource, value);
+}
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+void MbedCloudClient::set_update_authorize_handler(void (*handler)(int32_t request))
+{
+    _client.set_update_authorize_handler(handler);
+}
+
+void MbedCloudClient::set_update_progress_handler(void (*handler)(uint32_t progress, uint32_t total))
+{
+    _client.set_update_progress_handler(handler);
+}
+
+void MbedCloudClient::update_authorize(int32_t request)
+{
+    _client.update_authorize(request);
+}
+#endif
+
+const char *MbedCloudClient::error_description() const
+{
+    return _error_description;
+}
+
+
+void MbedCloudClient::register_update_callback(string route,
+                                               SimpleM2MResourceBase* resource)
+{
+    _update_values[route] = resource;
+}
+
+void MbedCloudClient::complete(ServiceClientCallbackStatus status)
+{
+    tr_info("MbedCloudClient::complete status (%d)", status);
+    if (status == Service_Client_Status_Registered) {
+        _on_registered.call();
+    } else if (status == Service_Client_Status_Unregistered) {
+        _object_list.clear();
+        _on_unregistered.call();
+    } else if (status == Service_Client_Status_Register_Updated) {
+        _on_registration_updated.call();
+    }
+}
+
+void MbedCloudClient::error(int error, const char *reason)
+{
+    tr_error("MbedCloudClient::error code (%d)", error);
+    _error_description = reason;
+    _on_error(error);
+}
+
+void MbedCloudClient::value_updated(M2MBase *base, M2MBase::BaseType type)
+{
+    if (base) {
+        tr_info("MbedCloudClient::value_updated path %s", base->uri_path());
+        if (base->uri_path()) {
+            if (_update_values.count(base->uri_path()) != 0) {
+                tr_debug("MbedCloudClient::value_updated calling update() for %s", base->uri_path());
+                _update_values[base->uri_path()]->update();
+            } else {
+                // way to tell application that there is a value update
+                if (_value_callback) {
+                    _value_callback->value_updated(base, type);
+                }
+            }
+        }
+    }
+}
+
+void MbedCloudClient::send_get_request(const char *uri,
+                                       const size_t offset,
+                                       get_data_cb data_cb,
+                                       get_data_error_cb error_cb,
+                                       void *context)
+{
+    _client.connector_client().m2m_interface()->get_data_request(uri,
+                                                                offset,
+                                                                true,
+                                                                data_cb,
+                                                                error_cb,
+                                                                context);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/ServiceClient.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,593 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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 macro is needed on armcc to get the the PRI*32 macros
+// from inttypes.h in a C++ code.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+#include <inttypes.h>
+
+#include <string>
+#include "include/ServiceClient.h"
+#include "include/CloudClientStorage.h"
+#include "include/UpdateClientResources.h"
+#include "include/UpdateClient.h"
+#include "factory_configurator_client.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-trace/mbed_trace.h"
+#include <assert.h>
+
+#define TRACE_GROUP "mClt"
+
+#define CONNECT 0
+#define ERROR_UPDATE "Update has failed, check MbedCloudClient::Error"
+
+/* lookup table for printing hexadecimal values */
+const uint8_t ServiceClient::hex_table[16] = {
+    '0', '1', '2', '3', '4', '5', '6', '7',
+    '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+};
+
+ServiceClient::ServiceClient(ServiceClientCallback& callback)
+: _service_callback(callback),
+  _service_uri(NULL),
+  _stack(NULL),
+  _client_objs(NULL),
+  _current_state(State_Init),
+  _event_generated(false),
+  _state_engine_running(false),
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+  _setup_update_client(false),
+#endif
+  _connector_client(this)
+{
+}
+
+ServiceClient::~ServiceClient()
+{
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+    ARM_UC_HUB_Uninitialize();
+#endif
+}
+
+void ServiceClient::initialize_and_register(M2MBaseList& reg_objs)
+{
+    tr_debug("ServiceClient::initialize_and_register");
+    if(_current_state == State_Init ||
+       _current_state == State_Unregister ||
+       _current_state == State_Failure) {
+        _client_objs = &reg_objs;
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+        tr_debug("ServiceClient::initialize_and_register: update client supported");
+
+        if(!_setup_update_client) {
+            _setup_update_client = true;
+
+#ifdef MBED_CLOUD_DEV_UPDATE_ID
+            /* Overwrite values stored in KCM. This is for development only
+               since these IDs should be provisioned in the factory.
+            */
+            tr_debug("ServiceClient::initialize_and_register: update IDs defined");
+
+            /* Delete VendorId */
+            ccs_delete_item("mbed.VendorId", CCS_CONFIG_ITEM);
+            /* Store Vendor Id to mbed.VendorId. No conversion is performed. */
+            set_device_resource_value(M2MDevice::Manufacturer,
+                                      (const char*) arm_uc_vendor_id,
+                                      arm_uc_vendor_id_size);
+
+            /* Delete ClassId */
+            ccs_delete_item("mbed.ClassId", CCS_CONFIG_ITEM);
+            /* Store Class Id to mbed.ClassId. No conversion is performed. */
+            set_device_resource_value(M2MDevice::ModelNumber,
+                                      (const char*) arm_uc_class_id,
+                                      arm_uc_class_id_size);
+#endif /* MBED_CLOUD_DEV_UPDATE_ID */
+
+#ifdef ARM_UPDATE_CLIENT_VERSION
+            /* Inject Update Client version number if no other software
+               version is present in the KCM.
+            */
+            tr_debug("ServiceClient::initialize_and_register: update version defined");
+;
+            const size_t buffer_size = 16;
+            uint8_t buffer[buffer_size];
+            size_t size = 0;
+
+            /* check if software version is already set */
+            ccs_status_e status = ccs_get_item(KEY_DEVICE_SOFTWAREVERSION,
+                                               buffer, buffer_size, &size, CCS_CONFIG_ITEM);
+
+            if (status == CCS_STATUS_KEY_DOESNT_EXIST) {
+                tr_debug("ServiceClient::initialize_and_register: insert update version");
+
+                /* insert value from Update Client Common */
+                ccs_set_item(KEY_DEVICE_SOFTWAREVERSION,
+                             (const uint8_t*) ARM_UPDATE_CLIENT_VERSION,
+                             sizeof(ARM_UPDATE_CLIENT_VERSION),
+                             CCS_CONFIG_ITEM);
+            }
+#endif /* ARM_UPDATE_CLIENT_VERSION */
+
+            /* Update Client adds the OMA LWM2M Firmware Update object */
+            UpdateClient::populate_object_list(*_client_objs);
+
+            /* Initialize Update Client */
+            FP1<void, int32_t> callback(this, &ServiceClient::update_error_callback);
+            UpdateClient::UpdateClient(callback);
+        }
+#endif /* MBED_CLOUD_CLIENT_SUPPORT_UPDATE */
+
+        /* Device Object is mandatory.
+           Get instance and add it to object list
+        */
+        M2MDevice *device_object = device_object_from_storage();
+
+        if (device_object) {
+            M2MObjectInstance* instance = device_object->object_instance(0);
+            if (instance) {
+                M2MResource *res = instance->resource(DEVICE_MANUFACTURER);
+                if (res) {
+                    res->publish_value_in_registration_msg(true);
+                }
+                res = instance->resource(DEVICE_MODEL_NUMBER);
+                if (res) {
+                    res->publish_value_in_registration_msg(true);
+                }
+                res = instance->resource(DEVICE_SERIAL_NUMBER);
+                if (res) {
+                    res->publish_value_in_registration_msg(true);
+                }
+             }
+            /* Publish device object resource to mds */
+            M2MResourceList list = device_object->object_instance()->resources();
+            if(!list.empty()) {
+                M2MResourceList::const_iterator it;
+                it = list.begin();
+                for ( ; it != list.end(); it++ ) {
+                    (*it)->set_register_uri(true);
+                }
+            }
+
+            /* Add Device Object to object list. */
+            _client_objs->push_back(device_object);
+        }
+
+        internal_event(State_Bootstrap);
+    } else if (_current_state == State_Success) {
+        state_success();
+    }
+}
+
+ConnectorClient &ServiceClient::connector_client()
+{
+    return _connector_client;
+}
+
+const ConnectorClient &ServiceClient::connector_client() const
+{
+    return _connector_client;
+}
+
+// generates an internal event. called from within a state
+// function to transition to a new state
+void ServiceClient::internal_event(StartupMainState new_state)
+{
+    tr_debug("ServiceClient::internal_event: state: %d -> %d", _current_state, new_state);
+
+    _event_generated = true;
+    _current_state = new_state;
+
+    if (!_state_engine_running) {
+        state_engine();
+    }
+}
+
+// the state engine executes the state machine states
+void ServiceClient::state_engine(void)
+{
+    tr_debug("ServiceClient::state_engine");
+
+    // this simple flagging gets rid of recursive calls to this method
+    _state_engine_running = true;
+
+    // while events are being generated keep executing states
+    while (_event_generated) {
+        _event_generated = false;  // event used up, reset flag
+
+        state_function(_current_state);
+    }
+
+    _state_engine_running = false;
+}
+
+void ServiceClient::state_function(StartupMainState current_state)
+{
+    switch (current_state) {
+        case State_Init:        // -> Goes to bootstrap state
+        case State_Bootstrap:    // -> State_Register OR State_Failure
+            state_bootstrap();
+            break;
+        case State_Register:     // -> State_Succes OR State_Failure
+            state_register();
+            break;
+        case State_Success:      // return success to user
+            state_success();
+            break;
+        case State_Failure:      // return error to user
+            state_failure();
+            break;
+        case State_Unregister:   // return error to user
+            state_unregister();
+            break;
+    }
+}
+
+void ServiceClient::state_bootstrap()
+{
+    tr_info("ServiceClient::state_bootstrap()");
+    bool credentials_ready = _connector_client.connector_credentials_available();
+    bool bootstrap = _connector_client.use_bootstrap();
+    tr_info("ServiceClient::state_bootstrap() - lwm2m credentials available: %d", credentials_ready);
+    tr_info("ServiceClient::state_bootstrap() - use bootstrap: %d", bootstrap);
+    if (credentials_ready || !bootstrap) {
+        internal_event(State_Register);
+    } else {
+        _connector_client.start_bootstrap();
+    }
+}
+
+void ServiceClient::state_register()
+{
+    tr_info("ServiceClient::state_register()");
+    _connector_client.start_registration(_client_objs);
+}
+
+void ServiceClient::registration_process_result(ConnectorClient::StartupSubStateRegistration status)
+{
+    tr_debug("ServiceClient::registration_process_result(): status: %d", status);
+    if (status == ConnectorClient::State_Registration_Success) {
+        internal_event(State_Success);
+    } else if(status == ConnectorClient::State_Registration_Failure ||
+              status == ConnectorClient::State_Bootstrap_Failure){
+        internal_event(State_Failure); // XXX: the status should be saved to eg. event object
+    }
+    if(status == ConnectorClient::State_Bootstrap_Success) {
+        internal_event(State_Register);
+    }
+    if(status == ConnectorClient::State_Unregistered) {
+        internal_event(State_Unregister);
+    }
+    if (status == ConnectorClient::State_Registration_Updated) {
+        _service_callback.complete(ServiceClientCallback::Service_Client_Status_Register_Updated);
+    }
+}
+
+void ServiceClient::connector_error(M2MInterface::Error error, const char *reason)
+{
+    tr_error("ServiceClient::connector_error() error %d", (int)error);
+    if (_current_state == State_Register) {
+        registration_process_result(ConnectorClient::State_Registration_Failure);
+    }
+    else if (_current_state == State_Bootstrap) {
+        registration_process_result(ConnectorClient::State_Bootstrap_Failure);
+    }
+    _service_callback.error(int(error),reason);
+    internal_event(State_Failure);
+}
+
+void ServiceClient::value_updated(M2MBase *base, M2MBase::BaseType type)
+{
+    tr_debug("ServiceClient::value_updated()");
+    _service_callback.value_updated(base, type);
+}
+
+void ServiceClient::state_success()
+{
+    tr_info("ServiceClient::state_success()");
+    // this is verified already at client API level, but this might still catch some logic failures
+    _service_callback.complete(ServiceClientCallback::Service_Client_Status_Registered);
+}
+
+void ServiceClient::state_failure()
+{
+    tr_error("ServiceClient::state_failure()");
+    _service_callback.complete(ServiceClientCallback::Service_Client_Status_Failure);
+}
+
+void ServiceClient::state_unregister()
+{
+    tr_debug("ServiceClient::state_unregister()");
+    _service_callback.complete(ServiceClientCallback::Service_Client_Status_Unregistered);
+}
+
+M2MDevice* ServiceClient::device_object_from_storage()
+{
+    M2MDevice *device_object = M2MInterfaceFactory::create_device();
+    if (device_object == NULL) {
+        return NULL;
+    }
+
+    const size_t buffer_size = 128;
+    uint8_t buffer[buffer_size];
+    size_t size = 0;
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+    uint8_t guid[sizeof(arm_uc_guid_t)] = {0};
+    // Read out the binary Vendor UUID
+    ccs_status_e status = (ccs_status_e)UpdateClient::getVendorId(guid, sizeof(arm_uc_guid_t), &size);
+
+    // Format the binary Vendor UUID into a hex string
+    if (status == CCS_STATUS_SUCCESS) {
+        size_t j = 0;
+        for(size_t i = 0; i < size; i++)
+        {
+            buffer[j++] = hex_table[(guid[i] >> 4) & 0xF];
+            buffer[j++] = hex_table[(guid[i] >> 0) & 0xF];
+        }
+        buffer[j] = '\0';
+        const String data((char*)buffer, size * 2);
+        // create_resource() returns NULL if resource already exists
+        if (device_object->create_resource(M2MDevice::Manufacturer, data) == NULL) {
+            device_object->set_resource_value(M2MDevice::Manufacturer, data);
+        }
+    }
+
+    // Read out the binary Class UUID
+    status = (ccs_status_e)UpdateClient::getClassId(guid, sizeof(arm_uc_guid_t), &size);
+
+    // Format the binary Class UUID into a hex string
+    if (status == CCS_STATUS_SUCCESS) {
+        size_t j = 0;
+        for(size_t i = 0; i < size; i++)
+        {
+            buffer[j++] = hex_table[(guid[i] >> 4) & 0xF];
+            buffer[j++] = hex_table[(guid[i] >> 0) & 0xF];
+        }
+        buffer[j] = '\0';
+        const String data((char*)buffer, size * 2);
+        // create_resource() returns NULL if resource already exists
+        if (device_object->create_resource(M2MDevice::ModelNumber, data) == NULL) {
+            device_object->set_resource_value(M2MDevice::ModelNumber, data);
+        }
+    }
+#else
+    // Read values to device object
+    // create_resource() function returns NULL if resource already exists
+    ccs_status_e status = ccs_get_item(g_fcc_manufacturer_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM);
+    if (status == CCS_STATUS_SUCCESS) {
+        const String data((char*)buffer, size);
+        if (device_object->create_resource(M2MDevice::Manufacturer, data) == NULL) {
+            device_object->set_resource_value(M2MDevice::Manufacturer, data);
+        }
+    }
+    status = ccs_get_item(g_fcc_model_number_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM);
+    if (status == CCS_STATUS_SUCCESS) {
+        const String data((char*)buffer, size);
+        if (device_object->create_resource(M2MDevice::ModelNumber, data) == NULL) {
+            device_object->set_resource_value(M2MDevice::ModelNumber, data);
+        }
+    }
+#endif
+    status = ccs_get_item(g_fcc_device_serial_number_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM);
+    if (status == CCS_STATUS_SUCCESS) {
+        const String data((char*)buffer, size);
+        if (device_object->create_resource(M2MDevice::SerialNumber, data) == NULL) {
+            device_object->set_resource_value(M2MDevice::SerialNumber, data);
+        }
+    }
+
+    status = ccs_get_item(g_fcc_device_type_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM);
+    if (status == CCS_STATUS_SUCCESS) {
+        const String data((char*)buffer, size);
+        if (device_object->create_resource(M2MDevice::DeviceType, data) == NULL) {
+            device_object->set_resource_value(M2MDevice::DeviceType, data);
+        }
+    }
+
+    status = ccs_get_item(g_fcc_hardware_version_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM);
+    if (status == CCS_STATUS_SUCCESS) {
+        const String data((char*)buffer, size);
+        if (device_object->create_resource(M2MDevice::HardwareVersion, data) == NULL) {
+            device_object->set_resource_value(M2MDevice::HardwareVersion, data);
+        }
+    }
+
+    status = ccs_get_item(KEY_DEVICE_SOFTWAREVERSION, buffer, buffer_size, &size, CCS_CONFIG_ITEM);
+    if (status == CCS_STATUS_SUCCESS) {
+        const String data((char*)buffer, size);
+        if (device_object->create_resource(M2MDevice::SoftwareVersion, data) == NULL) {
+            device_object->set_resource_value(M2MDevice::SoftwareVersion, data);
+        }
+    }
+
+    uint8_t data[4] = {0};
+    uint32_t value;
+    status = ccs_get_item(g_fcc_memory_size_parameter_name, data, 4, &size, CCS_CONFIG_ITEM);
+    if (status == CCS_STATUS_SUCCESS) {
+        memcpy(&value, data, 4);
+        if (device_object->create_resource(M2MDevice::MemoryTotal, value) == NULL) {
+            device_object->set_resource_value(M2MDevice::MemoryTotal, value);
+        }
+        tr_debug("ServiceClient::device_object_from_storage() - setting memory total value %" PRIu32 " (%s)", value, tr_array(data, 4));
+    }
+
+    status = ccs_get_item(g_fcc_current_time_parameter_name, data, 4, &size, CCS_CONFIG_ITEM);
+    if (status == CCS_STATUS_SUCCESS) {
+        memcpy(&value, data, 4);
+        if (device_object->create_resource(M2MDevice::CurrentTime, value) == NULL) {
+            device_object->set_resource_value(M2MDevice::CurrentTime, value);
+        }
+        tr_debug("ServiceClient::device_object_from_storage() - setting current time value %" PRIu32 " (%s)", value, tr_array(data, 4));
+    }
+
+    status = ccs_get_item(g_fcc_device_time_zone_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM);
+    if (status == CCS_STATUS_SUCCESS) {
+        const String data((char*)buffer, size);
+        if (device_object->create_resource(M2MDevice::Timezone, data) == NULL) {
+            device_object->set_resource_value(M2MDevice::Timezone, data);
+        }
+    }
+
+    status = ccs_get_item(g_fcc_offset_from_utc_parameter_name, buffer, buffer_size, &size, CCS_CONFIG_ITEM);
+    if (status == CCS_STATUS_SUCCESS) {
+        const String data((char*)buffer, size);
+        if (device_object->create_resource(M2MDevice::UTCOffset, data) == NULL) {
+            device_object->set_resource_value(M2MDevice::UTCOffset, data);
+        }
+    }
+
+    return device_object;
+}
+
+/**
+ * \brief Set resource value in the Device Object
+ *
+ * \param resource Device enum to have value set.
+ * \param value String object.
+ * \return True if successful, false otherwise.
+ */
+bool ServiceClient::set_device_resource_value(M2MDevice::DeviceResource resource,
+                                              const std::string& value)
+{
+    return set_device_resource_value(resource,
+                                     value.c_str(),
+                                     value.size() - 1);
+}
+
+/**
+ * \brief Set resource value in the Device Object
+ *
+ * \param resource Device enum to have value set.
+ * \param value Byte buffer.
+ * \param length Buffer length.
+ * \return True if successful, false otherwise.
+ */
+bool ServiceClient::set_device_resource_value(M2MDevice::DeviceResource resource,
+                                              const char* value,
+                                              uint32_t length)
+{
+    bool retval = false;
+
+    /* sanity check */
+    if (value && (length < 256) && (length > 0))
+    {
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+        /* Pass resource value to Update Client.
+           Used for validating the manifest.
+        */
+        switch (resource) {
+            case M2MDevice::Manufacturer:
+                ARM_UC_SetVendorId((const uint8_t*) value, length);
+                break;
+            case M2MDevice::ModelNumber:
+                ARM_UC_SetClassId((const uint8_t*) value, length);
+                break;
+            default:
+                break;
+        }
+#endif
+
+        /* Convert resource to printable string if necessary */
+
+        /* Getting object instance from factory */
+        M2MDevice *device_object = M2MInterfaceFactory::create_device();
+
+        /* Check device object and resource both are present */
+        if (device_object && device_object->is_resource_present(resource)) {
+            /* set counter to not-zero */
+            uint8_t printable_length = 0xFF;
+
+            /* set printable_length to 0 if the buffer is not printable */
+            for (uint8_t index = 0; index < length; index++) {
+                /* break if character is not printable */
+                if ((value[index] < ' ') || (value[index] > '~')) {
+                    printable_length = 0;
+                    break;
+                }
+            }
+
+            /* resource is a string */
+            if (printable_length != 0) {
+                /* reset counter */
+                printable_length = 0;
+
+                /* find actual printable length */
+                for ( ; printable_length < length; printable_length++) {
+                    /* break prematurely if end-of-string character is found */
+                    if (value[printable_length] == '\0') {
+                        break;
+                    }
+                }
+
+                /* convert to string and set value in object */
+                String string_value(value, printable_length);
+                retval = device_object->set_resource_value(resource, string_value);
+            }
+            else
+            {
+                /* resource is a byte array */
+                char value_buffer[0xFF] = { 0 };
+
+                /* count length */
+                uint8_t index = 0;
+
+                /* convert byte array to string */
+                for ( ;
+                    (index < length) && ((2*index +1) < 0xFF);
+                    index++) {
+
+                    uint8_t byte = value[index];
+
+                    value_buffer[2 * index]     = hex_table[byte >> 4];
+                    value_buffer[2 * index + 1] = hex_table[byte & 0x0F];
+                }
+
+                /* convert to string and set value in object */
+                String string_value(value_buffer, 2 * (index - 1));
+                retval = device_object->set_resource_value(resource, string_value);
+            }
+        }
+    }
+
+    return retval;
+}
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+void ServiceClient::set_update_authorize_handler(void (*handler)(int32_t request))
+{
+    UpdateClient::set_update_authorize_handler(handler);
+}
+
+void ServiceClient::update_authorize(int32_t request)
+{
+    UpdateClient::update_authorize(request);
+}
+
+void ServiceClient::set_update_progress_handler(void (*handler)(uint32_t progress, uint32_t total))
+{
+    UpdateClient::set_update_progress_handler(handler);
+}
+
+void ServiceClient::update_error_callback(int32_t error)
+{
+    _service_callback.error(error, ERROR_UPDATE);
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/SimpleM2MResource.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,321 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "mbed-cloud-client/SimpleM2MResource.h"
+#include "mbed-trace/mbed_trace.h"
+
+#include <ctype.h>
+
+#include<stdio.h>
+
+#define TRACE_GROUP "mClt"
+
+
+SimpleM2MResourceBase::SimpleM2MResourceBase()
+: _client(NULL), _route("")
+{
+    tr_debug("SimpleM2MResourceBase::SimpleM2MResourceBase()");
+}
+
+SimpleM2MResourceBase::SimpleM2MResourceBase(MbedCloudClient* client, string route)
+: _client(client),_route(route)
+{
+    tr_debug("SimpleM2MResourceBase::SimpleM2MResourceBase(), resource name %s\r\n", _route.c_str());
+}
+
+SimpleM2MResourceBase::~SimpleM2MResourceBase()
+{
+}
+
+bool SimpleM2MResourceBase::define_resource_internal(std::string v, M2MBase::Operation opr, bool observable)
+{
+    tr_debug("SimpleM2MResourceBase::define_resource_internal(), resource name %s!\r\n", _route.c_str());
+
+    vector<string> segments = parse_route(_route.c_str());
+    if (segments.size() != 3) {
+        tr_debug("[SimpleM2MResourceBase] [ERROR] define_resource_internal(), Route needs to have three segments, split by '/' (%s)\r\n", _route.c_str());
+        return false;
+    }
+
+    // segments[1] should be one digit and numeric
+    if (!isdigit(segments.at(1).c_str()[0])) {
+        tr_debug("[SimpleM2MResourceBase] [ERROR] define_resource_internal(), second route segment should be numeric, but was not (%s)\r\n", _route.c_str());
+        return false;
+    }
+
+    int inst_id = atoi(segments.at(1).c_str());
+
+    // Check if object exists
+    M2MObject* obj;
+    map<string,M2MObject*>::iterator obj_it = _client->_objects.find(segments[0]) ;
+    if(obj_it != _client->_objects.end()) {
+      tr_debug("Found object... %s\r\n", segments.at(0).c_str());
+      obj = obj_it->second;
+    } else {
+        tr_debug("Create new object... %s\r\n", segments.at(0).c_str());
+        obj = M2MInterfaceFactory::create_object(segments.at(0).c_str());
+        if (!obj) {
+            return false;
+        }
+        _client->_objects.insert(std::pair<string, M2MObject*>(segments.at(0), obj));
+    }
+
+    // Check if object instance exists
+    M2MObjectInstance* inst = obj->object_instance(inst_id);
+    if(!inst) {
+        tr_debug("Create new object instance... %s\r\n", segments.at(1).c_str());
+        inst = obj->create_object_instance(inst_id);
+        if(!inst) {
+            return false;
+        }
+    }
+
+    // @todo check if the resource exists yet
+    M2MResource* res = inst->resource(segments.at(2).c_str());
+    if(!res) {
+        res = inst->create_dynamic_resource(segments.at(2).c_str(), "",
+            M2MResourceInstance::STRING, observable);
+        if(!res) {
+            return false;
+        }
+        res->set_operation(opr);
+        res->set_value((uint8_t*)v.c_str(), v.length());
+
+        _client->_resources.insert(pair<string, M2MResource*>(_route, res));
+        _client->register_update_callback(_route, this);
+    }
+
+    return true;
+}
+
+vector<string> SimpleM2MResourceBase::parse_route(const char* route)
+{
+    string s(route);
+    vector<string> v;
+    std::size_t found = s.find_first_of("/");
+
+    while (found!=std::string::npos) {
+        v.push_back(s.substr(0,found));
+        s = s.substr(found+1);
+        found=s.find_first_of("/");
+        if(found == std::string::npos) {
+            v.push_back(s);
+        }
+    }
+    return v;
+}
+
+string SimpleM2MResourceBase::get() const
+{
+    tr_debug("SimpleM2MResourceBase::get() resource (%s)", _route.c_str());
+    if (!_client->_resources.count(_route)) {
+        tr_debug("[SimpleM2MResourceBase] [ERROR] No such route (%s)\r\n", _route.c_str());
+        return string();
+    }
+
+    // otherwise ask mbed Client...
+    uint8_t* buffIn = NULL;
+    uint32_t sizeIn;
+    _client->_resources[_route]->get_value(buffIn, sizeIn);
+
+    string s((char*)buffIn, sizeIn);
+    tr_debug("SimpleM2MResourceBase::get() resource value (%s)", s.c_str());
+    free(buffIn);
+    return s;
+}
+
+bool SimpleM2MResourceBase::set(string v)
+{
+    // Potentially set() happens in InterruptContext. That's not good.
+    tr_debug("SimpleM2MResourceBase::set() resource (%s)", _route.c_str());
+    if (!_client->_resources.count(_route)) {
+        tr_debug("[SimpleM2MResourceBase] [ERROR] No such route (%s)\r\n", _route.c_str());
+        return false;
+    }
+
+    if (v.length() == 0) {
+        _client->_resources[_route]->clear_value();
+    }
+    else {
+        _client->_resources[_route]->set_value((uint8_t*)v.c_str(), v.length());
+    }
+
+    return true;
+}
+
+bool SimpleM2MResourceBase::set(const int& v)
+{
+    char buffer[20];
+    int size = sprintf(buffer,"%d",v);
+    std::string stringified(buffer,size);
+
+    return set(stringified);
+}
+
+bool SimpleM2MResourceBase::set_post_function(void(*fn)(void*))
+{
+    //TODO: Check the resource exists with right operation being set or append the operation into it.
+    M2MResource *resource = get_resource();
+    if(!resource) {
+        return false;
+    }
+    M2MBase::Operation op = resource->operation();
+    op = (M2MBase::Operation)(op | M2MBase::POST_ALLOWED);
+    resource->set_operation(op);
+
+    _client->_resources[_route]->set_execute_function(execute_callback_2(fn));
+    return true;
+}
+
+bool SimpleM2MResourceBase::set_post_function(execute_callback fn)
+{
+    //TODO: Check the resource exists with right operation being set or append the operation into it.
+    M2MResource *resource = get_resource();
+    if(!resource) {
+        return false;
+    }
+    M2MBase::Operation op = resource->operation();
+    op = (M2MBase::Operation)(op | M2MBase::POST_ALLOWED);
+    resource->set_operation(op);
+
+    // No clue why this is not working?! It works with class member, but not with static function...
+    _client->_resources[_route]->set_execute_function(fn);
+    return true;
+}
+
+M2MResource* SimpleM2MResourceBase::get_resource()
+{
+    if (!_client->_resources.count(_route)) {
+        tr_debug("[SimpleM2MResourceBase] [ERROR] No such route (%s)\r\n", _route.c_str());
+        return NULL;
+    }
+    return _client->_resources[_route];
+}
+
+SimpleM2MResourceString::SimpleM2MResourceString(MbedCloudClient* client,
+                               const char* route,
+                               string v,
+                               M2MBase::Operation opr,
+                               bool observable,
+                               FP1<void, string> on_update)
+: SimpleM2MResourceBase(client,route),_on_update(on_update)
+{
+    tr_debug("SimpleM2MResourceString::SimpleM2MResourceString() creating (%s)\r\n", route);
+    define_resource_internal(v, opr, observable);
+}
+
+SimpleM2MResourceString::SimpleM2MResourceString(MbedCloudClient* client,
+                               const char* route,
+                               string v,
+                               M2MBase::Operation opr,
+                               bool observable,
+                               void(*on_update)(string))
+
+: SimpleM2MResourceBase(client,route)
+{
+    tr_debug("SimpleM2MResourceString::SimpleM2MResourceString() overloaded creating (%s)\r\n", route);
+    FP1<void, string> fp;
+    fp.attach(on_update);
+    _on_update = fp;
+    define_resource_internal(v, opr, observable);
+}
+
+SimpleM2MResourceString::~SimpleM2MResourceString()
+{
+}
+
+string SimpleM2MResourceString::operator=(const string& new_value)
+{
+    tr_debug("SimpleM2MResourceString::operator=()");
+    set(new_value);
+    return new_value;
+}
+
+SimpleM2MResourceString::operator string() const
+{
+    tr_debug("SimpleM2MResourceString::operator string()");
+    string value = get();
+    return value;
+}
+
+void SimpleM2MResourceString::update()
+{
+    string v = get();
+    _on_update(v);
+}
+
+SimpleM2MResourceInt::SimpleM2MResourceInt(MbedCloudClient* client,
+                         const char* route,
+                         int v,
+                         M2MBase::Operation opr,
+                         bool observable,
+                         FP1<void, int> on_update)
+: SimpleM2MResourceBase(client,route),_on_update(on_update)
+{
+    tr_debug("SimpleM2MResourceInt::SimpleM2MResourceInt() creating (%s)\r\n", route);
+    char buffer[20];
+    int size = sprintf(buffer,"%d",v);
+    std::string stringified(buffer,size);
+    define_resource_internal(stringified, opr, observable);
+}
+
+SimpleM2MResourceInt::SimpleM2MResourceInt(MbedCloudClient* client,
+                         const char* route,
+                         int v,
+                         M2MBase::Operation opr,
+                         bool observable,
+                         void(*on_update)(int))
+: SimpleM2MResourceBase(client,route)
+{
+    tr_debug("SimpleM2MResourceInt::SimpleM2MResourceInt() overloaded creating (%s)\r\n", route);
+    FP1<void, int> fp;
+    fp.attach(on_update);
+    _on_update = fp;
+    char buffer[20];
+    int size = sprintf(buffer,"%d",v);
+    std::string stringified(buffer,size);
+    define_resource_internal(stringified, opr, observable);
+}
+
+SimpleM2MResourceInt::~SimpleM2MResourceInt()
+{
+}
+
+int SimpleM2MResourceInt::operator=(int new_value)
+{
+    set(new_value);
+    return new_value;
+}
+
+SimpleM2MResourceInt::operator int() const
+{
+    string v = get();
+    if (v.empty()) return 0;
+
+    return atoi((const char*)v.c_str());
+}
+
+void SimpleM2MResourceInt::update()
+{
+    string v = get();
+    if (v.empty()) {
+        _on_update(0);
+    } else {
+        _on_update(atoi((const char*)v.c_str()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/UpdateClient.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,355 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+// Needed for PRIu64 on FreeRTOS
+#include <stdio.h>
+// Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS
+#endif
+
+// Note: this macro is needed on armcc to get the the PRI*32 macros
+// from inttypes.h in a C++ code.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#ifdef MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#include MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#endif
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+#include "update-client-hub/update_client_hub.h"
+
+#include "update-client-source-http/arm_uc_source_http.h"
+#include "update-client-lwm2m/lwm2m-source.h"
+#include "update-client-lwm2m/lwm2m-monitor.h"
+#include "update-client-lwm2m/lwm2m-control.h"
+#include "update-client-lwm2m/FirmwareUpdateResource.h"
+#include "update-client-lwm2m/DeviceMetadataResource.h"
+
+#include "eventOS_scheduler.h"
+#include "eventOS_event.h"
+
+#include "include/UpdateClient.h"
+#include "include/UpdateClientResources.h"
+#include "include/CloudClientStorage.h"
+
+#include "pal.h"
+
+#if (!defined(MBED_CONF_MBED_TRACE_ENABLE) || MBED_CONF_MBED_TRACE_ENABLE == 0) \
+    && ARM_UC_ALL_TRACE_ENABLE == 1
+#define tr_info(...) { printf(__VA_ARGS__); printf("\r\n"); }
+#else
+#include "mbed-trace/mbed_trace.h"
+#define TRACE_GROUP "uccc"
+#endif
+
+/* To be removed once update storage is defined in user config file.
+   Default to filesystem in the meantime.
+*/
+#ifndef MBED_CLOUD_CLIENT_UPDATE_STORAGE
+#define MBED_CLOUD_CLIENT_UPDATE_STORAGE ARM_UCP_FILESYSTEM
+#endif
+
+#ifdef MBED_CLOUD_CLIENT_UPDATE_STORAGE
+extern ARM_UC_PAAL_UPDATE MBED_CLOUD_CLIENT_UPDATE_STORAGE;
+#else
+#error Update client storage must be defined in user configuration file
+#endif
+
+namespace UpdateClient
+{
+    enum UpdateClientEventType {
+        UPDATE_CLIENT_EVENT_INITIALIZE,
+        UPDATE_CLIENT_EVENT_PROCESS_QUEUE
+    };
+
+    static int8_t update_client_tasklet_id = -1;
+    static FP1<void, int32_t> error_callback;
+
+    static void certificate_done(arm_uc_error_t error,
+                                 const arm_uc_buffer_t* fingerprint);
+    static void initialization(void);
+    static void initialization_done(int32_t);
+    static void event_handler(arm_event_s* event);
+    static void queue_handler(void);
+    static void schedule_event(void);
+    static void error_handler(int32_t error);
+}
+
+void UpdateClient::UpdateClient(FP1<void, int32_t> callback)
+{
+    tr_info("Update Client External Initialization: %p", (void*)pal_osThreadGetId());
+
+    /* store callback handler */
+    error_callback = callback;
+
+    /* create event */
+    eventOS_scheduler_mutex_wait();
+    if (update_client_tasklet_id == -1) {
+        update_client_tasklet_id = eventOS_event_handler_create(UpdateClient::event_handler,
+                                                                UPDATE_CLIENT_EVENT_INITIALIZE);
+
+        tr_info("UpdateClient::update_client_tasklet_id: %d",
+                update_client_tasklet_id);
+    }
+    eventOS_scheduler_mutex_release();
+}
+
+/**
+ * @brief Populate M2MObjectList with Update Client objects.
+ */
+void UpdateClient::populate_object_list(M2MBaseList& list)
+{
+    /* Setup Firmware Update LWM2M object */
+    list.push_back(FirmwareUpdateResource::getObject());
+    list.push_back(DeviceMetadataResource::getObject());
+}
+
+void UpdateClient::set_update_authorize_handler(void (*handler)(int32_t request))
+{
+    ARM_UC_SetAuthorizeHandler(handler);
+}
+
+void UpdateClient::update_authorize(int32_t request)
+{
+    switch (request)
+    {
+        case RequestDownload:
+            ARM_UC_Authorize(ARM_UCCC_REQUEST_DOWNLOAD);
+            break;
+        case RequestInstall:
+            ARM_UC_Authorize(ARM_UCCC_REQUEST_INSTALL);
+            break;
+        case RequestInvalid:
+        default:
+            break;
+    }
+}
+
+void UpdateClient::set_update_progress_handler(void (*handler)(uint32_t progress, uint32_t total))
+{
+    ARM_UC_SetProgressHandler(handler);
+}
+
+static void UpdateClient::initialization(void)
+{
+    tr_info("internal initialization: %p", (void*)pal_osThreadGetId());
+
+    /* Register sources */
+    static const ARM_UPDATE_SOURCE* sources[] = {
+        &ARM_UCS_HTTPSource,
+        &ARM_UCS_LWM2M_SOURCE
+    };
+
+    ARM_UC_HUB_SetSources(sources, sizeof(sources)/sizeof(ARM_UPDATE_SOURCE*));
+
+    /* Register sink for telemetry */
+    ARM_UC_HUB_AddMonitor(&ARM_UCS_LWM2M_MONITOR);
+
+    /* Register local error handler */
+    ARM_UC_HUB_AddErrorCallback(UpdateClient::error_handler);
+
+    /* Link internal queue with external scheduler.
+       The callback handler is called whenever a task is posted to
+       an empty queue. This will trigger the queue to be processed.
+    */
+    ARM_UC_HUB_AddNotificationHandler(UpdateClient::queue_handler);
+
+    /* The override function enables the LWM2M Firmware Update Object
+       to authorize both download and installation. The intention is
+       that a buggy user application can't block an update.
+    */
+    ARM_UC_CONTROL_SetOverrideCallback(ARM_UC_OverrideAuthorization);
+
+#ifdef MBED_CLOUD_CLIENT_UPDATE_STORAGE
+    /* Set implementation for storing firmware */
+    ARM_UC_HUB_SetStorage(&MBED_CLOUD_CLIENT_UPDATE_STORAGE);
+#endif
+
+#ifdef MBED_CLOUD_DEV_UPDATE_PSK
+    /* Add pre shared key */
+    ARM_UC_AddPreSharedKey(arm_uc_default_psk, arm_uc_default_psk_bits);
+#endif
+
+    /* Insert default certificate if defined otherwise initialze
+       Update client immediately.
+    */
+#ifdef MBED_CLOUD_DEV_UPDATE_CERT
+    /* Add verification certificate */
+    arm_uc_error_t result = ARM_UC_AddCertificate(arm_uc_default_certificate,
+                                                  arm_uc_default_certificate_size,
+                                                  arm_uc_default_fingerprint,
+                                                  arm_uc_default_fingerprint_size,
+                                                  UpdateClient::certificate_done);
+
+    /* Certificate insertion failed, most likely because the certificate
+       has already been inserted once before.
+
+       Continue initialization regardlessly, since the Update Client can still
+       work if verification certificates are inserted through the Factory
+       Client or by other means.
+    */
+    if (result.code != ARM_UC_CM_ERR_NONE)
+    {
+        tr_info("ARM_UC_AddCertificate failed");
+
+        ARM_UC_HUB_Initialize(UpdateClient::initialization_done);
+    }
+#else
+    ARM_UC_HUB_Initialize(UpdateClient::initialization_done);
+#endif
+}
+
+static void UpdateClient::certificate_done(arm_uc_error_t error,
+                                           const arm_uc_buffer_t* fingerprint)
+{
+    (void) fingerprint;
+
+    /* Certificate insertion failure is not necessarily fatal.
+       If verification certificates have been injected by other means
+       it is still possible to perform updates, which is why the
+       Update client initializes anyway.
+    */
+    if (error.code != ARM_UC_CM_ERR_NONE)
+    {
+        error_callback.call(WarningCertificateInsertion);
+    }
+
+    ARM_UC_HUB_Initialize(UpdateClient::initialization_done);
+}
+
+static void UpdateClient::initialization_done(int32_t result)
+{
+    tr_info("internal initialization done: %" PRIu32 " %p", result, (void*)pal_osThreadGetId());
+}
+
+static void UpdateClient::event_handler(arm_event_s* event)
+{
+    switch (event->event_type)
+    {
+        case UPDATE_CLIENT_EVENT_INITIALIZE:
+            UpdateClient::initialization();
+            break;
+
+        case UPDATE_CLIENT_EVENT_PROCESS_QUEUE:
+            {
+                /* process a single callback, for better cooperability */
+                bool queue_not_empty = ARM_UC_ProcessSingleCallback();
+
+                if (queue_not_empty)
+                {
+                    /* reschedule event handler, if queue is not empty */
+                    UpdateClient::schedule_event();
+                }
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
+static void UpdateClient::queue_handler(void)
+{
+    /* warning: queue_handler can be called from interrupt context.
+    */
+    UpdateClient::schedule_event();
+}
+
+static void UpdateClient::schedule_event()
+{
+    /* schedule event */
+    arm_event_s event = {0};
+    event.receiver = update_client_tasklet_id;
+    event.sender = 0;
+    event.event_type = UPDATE_CLIENT_EVENT_PROCESS_QUEUE;
+    event.event_id = 0;
+    event.data_ptr = NULL;
+    event.priority = ARM_LIB_LOW_PRIORITY_EVENT;
+    event.event_data = 0;
+
+    eventOS_event_send(&event);
+}
+
+static void UpdateClient::error_handler(int32_t error)
+{
+    tr_info("error reported: %" PRIi32, error);
+
+    /* add warning base if less severe than error */
+    if (error < ARM_UC_ERROR)
+    {
+        error_callback.call(WarningBase + error);
+    }
+    /* add error base if less severe than fatal */
+    else if (error < ARM_UC_FATAL)
+    {
+        error_callback.call(ErrorBase + error);
+    }
+    /* add fatal base */
+    else
+    {
+        error_callback.call(FatalBase + error);
+    }
+}
+
+int UpdateClient::getVendorId(uint8_t* buffer, size_t buffer_size_max, size_t* value_size)
+{
+    arm_uc_error_t err = ARM_UC_GetVendorId(buffer, buffer_size_max, value_size);
+    if (err.code == ARM_UC_DI_ERR_SIZE)
+    {
+        return CCS_STATUS_MEMORY_ERROR;
+    }
+    if (err.error == ERR_NONE)
+    {
+        *value_size = 16;
+        return CCS_STATUS_SUCCESS;
+    }
+    return CCS_STATUS_KEY_DOESNT_EXIST;
+}
+int UpdateClient::getClassId(uint8_t* buffer, size_t buffer_size_max, size_t* value_size)
+{
+    arm_uc_error_t err = ARM_UC_GetClassId(buffer, buffer_size_max, value_size);
+    if (err.code == ARM_UC_DI_ERR_SIZE)
+    {
+        return CCS_STATUS_MEMORY_ERROR;
+    }
+    if (err.error == ERR_NONE)
+    {
+        *value_size = 16;
+        return CCS_STATUS_SUCCESS;
+    }
+    return CCS_STATUS_KEY_DOESNT_EXIST;
+}
+int UpdateClient::getDeviceId(uint8_t* buffer, size_t buffer_size_max, size_t* value_size)
+{
+    arm_uc_error_t err = ARM_UC_GetDeviceId(buffer, buffer_size_max, value_size);
+    if (err.code == ARM_UC_DI_ERR_SIZE)
+    {
+        return CCS_STATUS_MEMORY_ERROR;
+    }
+    if (err.error == ERR_NONE)
+    {
+        *value_size = 16;
+        return CCS_STATUS_SUCCESS;
+    }
+    return CCS_STATUS_KEY_DOESNT_EXIST;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/include/CertificateParser.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,40 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef CERTIFICATE_PARSER_H
+#define CERTIFICATE_PARSER_H
+
+#include "ns_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+*  \brief A utility function to extract Locality field from the mDS certificate and store it to KCM.
+*  \param certificate, The certificate from which the field has to be extracted.
+*  \param field, The field to be extracted.
+*  \param value [OUT], buffer containing field value. Maximum value can be 64 bytes.
+*  \return True if success, False if failure.
+*/
+bool extract_field_from_certificate(const uint8_t* cer, size_t cer_len, const char *field, char* value);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // CERTIFICATE_PARSER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/include/CloudClientStorage.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,82 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef CLOUD_CLIENT_STORAGE_H
+#define CLOUD_CLIENT_STORAGE_H
+
+#define KEY_ACCOUNT_ID                          "mbed.AccountID"
+#define KEY_INTERNAL_ENDPOINT                   "mbed.InternalEndpoint"
+#define KEY_DEVICE_SOFTWAREVERSION              "mbed.SoftwareVersion"
+#define KEY_FIRST_TO_CLAIM                      "mbed.FirstToClaim"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    CCS_STATUS_MEMORY_ERROR = -4,
+    CCS_STATUS_VALIDATION_FAIL = -3,
+    CCS_STATUS_KEY_DOESNT_EXIST = -2,
+    CCS_STATUS_ERROR = -1,
+    CCS_STATUS_SUCCESS = 0
+} ccs_status_e;
+
+/**
+* CCS item types
+* Keep these sync with ones that found from kcm_defs.h
+*/
+typedef enum {
+    CCS_PRIVATE_KEY_ITEM,          //!< KCM private key item type. KCM Supports ECC keys with curves defined in palGroupIndex_t(pal_Crypto.h)
+    CCS_PUBLIC_KEY_ITEM,           //!< KCM public key item type.  KCM Supports ECC keys with curves defined in palGroupIndex_t(pal_Crypto.h)
+    CCS_SYMMETRIC_KEY_ITEM,        //!< KCM symmetric key item type.
+    CCS_CERTIFICATE_ITEM,          //!< KCM certificate item type. Supported x509 certificates in der format.
+    CCS_CONFIG_ITEM                //!< KCM configuration parameter item type.
+} ccs_item_type_e;
+
+/**
+*  \brief Uninitializes the CFStore handle.
+*/
+ccs_status_e uninitialize_storage(void);
+
+/**
+*  \brief Initializes the CFStore handle.
+*/
+ccs_status_e initialize_storage(void);
+
+/* Bootstrap credential handling methods */
+ccs_status_e ccs_get_string_item(const char* key, uint8_t *buffer, const size_t buffer_size, ccs_item_type_e item_type);
+ccs_status_e ccs_check_item(const char* key, ccs_item_type_e item_type);
+ccs_status_e ccs_delete_item(const char* key, ccs_item_type_e item_type);
+ccs_status_e ccs_get_item(const char* key, uint8_t *buffer, const size_t buffer_size, size_t *value_length, ccs_item_type_e item_type);
+ccs_status_e ccs_set_item(const char* key, const uint8_t *buffer, const size_t buffer_size, ccs_item_type_e item_type);
+ccs_status_e ccs_item_size(const char* key, size_t* size_out, ccs_item_type_e item_type);
+
+/* Certificate chain handling methods */
+void *ccs_create_certificate_chain(const char *chain_file_name, size_t chain_len);
+void *ccs_open_certificate_chain(const char *chain_file_name, size_t *chain_size);
+ccs_status_e ccs_close_certificate_chain(void *chain_handle);
+ccs_status_e ccs_add_next_cert_chain(void *chain_handle, const uint8_t *cert_data, size_t data_size);
+ccs_status_e ccs_get_next_cert_chain(void *chain_handle, void *cert_data, size_t *data_size);
+ccs_status_e ccs_parse_cert_chain_and_store(const uint8_t *cert_chain_name,
+                                            const size_t cert_chain_name_len,
+                                            const uint8_t *cert_chain_data,
+                                            const uint16_t cert_chain_data_len);
+#ifdef __cplusplus
+}
+#endif
+#endif // CLOUD_CLIENT_STORAGE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/include/ConnectorClient.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,432 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __CONNECTOR_CLIENT_H__
+#define __CONNECTOR_CLIENT_H__
+
+#include "mbed-client/functionpointer.h"
+#include "mbed-client/m2minterfacefactory.h"
+#include "mbed-client/m2mdevice.h"
+#include "mbed-client/m2minterfaceobserver.h"
+#include "mbed-client/m2minterface.h"
+#include "mbed-client/m2mobjectinstance.h"
+#include "mbed-client/m2mresource.h"
+#include "mbed-client/m2mtimerobserver.h"
+#include "mbed-client/m2mtimer.h"
+#include "include/CloudClientStorage.h"
+
+class ConnectorClientCallback;
+
+using namespace std;
+
+
+/**
+ * \brief ConnectorClientEndpointInfo
+ * A structure that contains the needed endpoint information to register with the Cloud service.
+ * Note: this should be changed to a class instead of struct and/or members changed to "const char*".
+ */
+struct ConnectorClientEndpointInfo {
+
+public:
+    ConnectorClientEndpointInfo(M2MSecurity::SecurityModeType m) : mode(m) {};
+    ~ConnectorClientEndpointInfo() {};
+
+public:
+
+    String                          endpoint_name;
+    String                          account_id;
+    String                          internal_endpoint_name;
+    M2MSecurity::SecurityModeType   mode;
+};
+
+/**
+ * \brief ConnectorClient
+ * This class is an interface towards the M2MInterface client to handle all
+ * data flow towards Connector through this client.
+ * This class is intended to be used via ServiceClient, not directly.
+ * This class contains also the bootstrap functionality.
+ */
+class ConnectorClient : public M2MInterfaceObserver, public M2MTimerObserver {
+
+public:
+    /**
+     * \brief An enum defining the different states of
+     * ConnectorClient during the client flow.
+     */
+    enum StartupSubStateRegistration {
+        State_Bootstrap_Start,
+        State_Bootstrap_Started,
+        State_Bootstrap_Success,
+        State_Bootstrap_Failure,
+#ifndef MBED_CLIENT_DISABLE_EST_FEATURE
+        State_EST_Start,
+        State_EST_Started,
+        State_EST_Success,
+        State_EST_Failure,
+#endif // !MBED_CLIENT_DISABLE_EST_FEATURE
+        State_Registration_Start,
+        State_Registration_Started,
+        State_Registration_Success,
+        State_Registration_Failure,
+        State_Registration_Updated,
+        State_Unregistered
+    };
+
+public:
+
+    /**
+    *  \brief Constructor.
+    *  \param callback, A callback for the status from ConnectorClient.
+    */
+    ConnectorClient(ConnectorClientCallback* callback);
+
+    /**
+    *  \brief Destructor.
+    */
+    ~ConnectorClient();
+
+    /**
+    *  \brief Starts the bootstrap sequence from the Service Client.
+    */
+    void start_bootstrap();
+
+    /**
+    *  \brief Starts the registration sequence from the Service Client.
+    *  \param client_objs, A list of objects implementing the M2MBase interface to be registered with Cloud.
+    */
+    void start_registration(M2MBaseList* client_objs);
+
+    /**
+    *  \brief Sends an update registration message to the LWM2M server.
+    */
+    void update_registration();
+
+    /**
+     * \brief Returns the M2MInterface handler.
+     * \return M2MInterface, Handled for M2MInterface.
+    */
+    M2MInterface * m2m_interface();
+
+    /**
+     * \brief Checks whether to use Bootstrap or direct Connector mode.
+     * \return True if bootstrap mode, False if direct Connector flow
+    */
+    bool use_bootstrap();
+
+    /**
+     * \brief Checks whether to go connector registration flow
+     * \return True if connector credentials available otherwise false.
+    */
+    bool connector_credentials_available();
+
+    /**
+     * \brief A utility function to generate the key name.
+     * \param key, The key to get the value for.
+     * \param endpoint, The name of the endpoint to be appended
+     * to the key.
+     * \param key_name, The [OUT] final key name.
+     * \return True if available, else false.
+    */
+    bool get_key(const char *key, const char *endpoint, char *&key_name);
+
+    /**
+     * \brief Returns pointer to the ConnectorClientEndpointInfo object.
+     * \return ConnectorClientEndpointInfo pointer.
+    */
+   const ConnectorClientEndpointInfo *endpoint_info() const;
+
+   void est_enrollment_result(bool success,
+                              const uint8_t *payload_ptr,
+                              const uint16_t payload_len);
+
+   static void est_post_data_cb(const uint8_t *buffer,
+                                size_t buffer_size,
+                                size_t total_size,
+                                void *context);
+
+   static void est_post_data_error_cb(get_data_req_error_t error_code,
+                                      void *context);
+
+   /**
+    * \brief Returns KCM Certificate chain handle pointer.
+    * \return KCM Certificate chain handle pointer.
+   */
+   void *certificate_chain_handle() const;
+
+   /**
+    * \brief Sets the KCM certificate chain handle pointer.
+    * \param cert_handle KCM Certificate chain handle.
+   */
+   void set_certificate_chain_handle(void *cert_handle);
+
+public:
+    // implementation of M2MInterfaceObserver:
+
+    /**
+     * \brief A callback indicating that the bootstap has been performed successfully.
+     * \param server_object, The server object that contains the information fetched
+     * about the LWM2M server from the bootstrap server. This object can be used
+     * to register with the LWM2M server. The object ownership is passed.
+     */
+    virtual void bootstrap_done(M2MSecurity *server_object);
+
+    /**
+     * \brief A callback indicating when all bootstrap data has been received.
+     * \param security_object, The security object that contains the security information.
+     */
+    virtual void bootstrap_data_ready(M2MSecurity *security_object);
+
+    /**
+     * \brief A callback indicating that the device object has been registered
+     * successfully with the LWM2M server.
+     * \param security_object, The server object on which the device object is
+     * registered. The object ownership is passed.
+     * \param server_object, An object containing information about the LWM2M server.
+     * The client maintains the object.
+     */
+    virtual void object_registered(M2MSecurity *security_object, const M2MServer &server_object);
+
+    /**
+     * \brief A callback indicating that the device object has been successfully unregistered
+     * from the LWM2M server.
+     * \param server_object, The server object from which the device object is
+     * unregistered. The object ownership is passed.
+     */
+    virtual void object_unregistered(M2MSecurity *server_object);
+
+    /**
+     * \brief A callback indicating that the device object registration has been successfully
+     * updated on the LWM2M server.
+     * \param security_object, The server object on which the device object registration is
+     * updated. The object ownership is passed.
+     * \param server_object, An object containing information about the LWM2M server.
+     * The client maintains the object.
+     */
+    virtual void registration_updated(M2MSecurity *security_object, const M2MServer & server_object);
+
+    /**
+     * \brief A callback indicating that there was an error during the operation.
+     * \param error, An error code for the occurred error.
+     */
+    virtual void error(M2MInterface::Error error);
+
+    /**
+     * \brief A callback indicating that the value of the resource object is updated by the server.
+     * \param base, The object whose value is updated.
+     * \param type, The type of the object.
+     */
+    virtual void value_updated(M2MBase *base, M2MBase::BaseType type);
+
+protected: // from M2MTimerObserver
+
+    virtual void timer_expired(M2MTimerObserver::Type type);
+
+private:
+    /**
+     * \brief Redirects the state machine to right function.
+     * \param current_state, The current state to be set.
+     * \param data, The data to be passed to the state function.
+     */
+    void state_function(StartupSubStateRegistration current_state);
+
+    /**
+     * \brief The state engine maintaining the state machine logic.
+     */
+    void state_engine(void);
+
+    /**
+    * \brief An internal event generated by the state machine.
+    * \param new_state, The new state to which the state machine should go.
+    * \param data, The data to be passed to the state machine.
+    */
+    void internal_event(StartupSubStateRegistration new_state);
+
+    /**
+    * When the bootstrap starts.
+    */
+    void state_bootstrap_start();
+
+    /**
+    * When the bootstrap is started.
+    */
+    void state_bootstrap_started();
+
+    /**
+    * When the bootstrap is successful.
+    */
+    void state_bootstrap_success();
+
+    /**
+    * When the bootstrap failed.
+    */
+    void state_bootstrap_failure();
+
+    /**
+     * When the EST (enrollment-over-secure-transport) enrollment starts.
+     */
+    void state_est_start();
+
+    /**
+     * When the EST (enrollment-over-secure-transport) enrollment has been started.
+     */
+    void state_est_started();
+
+    /**
+     * When the EST (enrollment-over-secure-transport) enrollment is successful.
+     */
+    void state_est_success();
+
+    /**
+     * When the EST (enrollment-over-secure-transport) enrollment failed.
+     */
+    void state_est_failure();
+
+    /**
+    * When the registration starts.
+    */
+    void state_registration_start();
+
+    /**
+    * When the registration started.
+    */
+    void state_registration_started();
+
+    /**
+    * When the registration is successful.
+    */
+    void state_registration_success();
+
+    /**
+     * When the registration failed.
+    */
+    void state_registration_failure();
+
+    /**
+    * When the client is unregistered.
+    */
+    void state_unregistered();
+
+    /**
+     * \brief A utility function to create an M2MSecurity object
+     * for registration.
+     */
+    void create_register_object();
+
+    /**
+     * \brief A utility function to create an M2MSecurity object
+     * for bootstrap.
+     */
+    bool create_bootstrap_object();
+
+    /**
+     * \brief A utility function to set the connector credentials
+     * in storage. This includes endpoint, domain, connector URI
+     *  and certificates.
+     * \param security, The Connector certificates.
+     */
+    ccs_status_e set_connector_credentials(M2MSecurity *security);
+
+    /**
+     * \brief A utility function to set the bootstrap credentials
+     * in storage. This includes Bootstrap URI and certificates.
+     * \param security, The Bootstrap certificates.
+     */
+    ccs_status_e set_bootstrap_credentials(M2MSecurity *security);
+
+    /**
+     * \brief A utility function to set the bootstrap address in storage.
+     * \param security, The bootstrap security object containing the address.
+     */
+    ccs_status_e store_bootstrap_address(M2MSecurity *security);
+
+    /**
+     * \brief A utility function to check whether bootstrap credentials are stored in KCM.
+     */
+    bool bootstrap_credentials_stored_in_kcm();
+
+    /**
+     * \brief A utility function to check whether first to claim feature is configured.
+     */
+    bool is_first_to_claim();
+
+    /**
+     * \brief A utility function to clear the first to claim parameter in storage.
+     */
+    ccs_status_e clear_first_to_claim();
+
+    /**
+    * \brief Returns the binding mode selected by the client
+    * through the configuration.
+    * \return Binding mode of the client.
+    */
+    static M2MInterface::BindingMode transport_mode();
+
+    /**
+    * \brief Initializes the security object and callbacks.
+    *
+    */
+    void init_security_object();
+
+private:
+    // A callback to be called after the sequence is complete.
+    ConnectorClientCallback*            _callback;
+    StartupSubStateRegistration         _current_state;
+    bool                                _event_generated;
+    bool                                _state_engine_running;
+    M2MInterface                        *_interface;
+    M2MSecurity                         *_security;
+    ConnectorClientEndpointInfo         _endpoint_info;
+    M2MBaseList                         *_client_objs;
+    M2MTimer                            _rebootstrap_timer;
+    uint16_t                            _bootstrap_security_instance;
+    uint16_t                            _lwm2m_security_instance;
+    void                                *_certificate_chain_handle;
+};
+
+/**
+ * \brief ConnectorClientCallback
+ * A callback class for passing the client progress and error condition to the
+ * ServiceClient class object.
+ */
+class ConnectorClientCallback {
+public:
+
+    /**
+    * \brief Indicates that the registration or unregistration operation is complete
+    * with success or failure.
+    * \param status, Indicates success or failure in terms of status code.
+    */
+    virtual void registration_process_result(ConnectorClient::StartupSubStateRegistration status) = 0;
+
+    /**
+    * \brief Indicates the Connector error condition of an underlying M2MInterface client.
+    * \param error, Indicates an error code translated from M2MInterface::Error.
+    * \param reason, Indicates human readable text for error description.
+    */
+    virtual void connector_error(M2MInterface::Error error, const char *reason) = 0;
+
+    /**
+    * \brief A callback indicating that the value of the resource object is updated
+    *  by the LWM2M Cloud server.
+    * \param base, The object whose value is updated.
+    * \param type, The type of the object.
+    */
+    virtual void value_updated(M2MBase *base, M2MBase::BaseType type) = 0;
+};
+
+#endif // !__CONNECTOR_CLIENT_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/include/ServiceClient.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,279 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __SERVICE_CLIENT_H__
+#define __SERVICE_CLIENT_H__
+
+#include "mbed-cloud-client/MbedCloudClientConfig.h"
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+#include "UpdateClient.h"
+#endif
+#include "mbed-client/m2minterface.h"
+#include "mbed-client/m2mdevice.h"
+#include "ConnectorClient.h"
+
+#include <string>
+
+class M2MSecurity;
+class ConnectorClientCallback;
+struct MbedClientDeviceInfo;
+struct MBedClientInterfaceInfo;
+
+/**
+ * \brief ServiceClientCallback
+ * A callback class for passing the client progress and error condition to the
+ * MbedCloudClient class object.
+ */
+class ServiceClientCallback {
+public:
+
+    typedef enum {
+        Service_Client_Status_Failure = -1,
+        Service_Client_Status_Registered = 0,
+        Service_Client_Status_Unregistered = 1,
+        Service_Client_Status_Register_Updated = 2
+    } ServiceClientCallbackStatus;
+
+    /**
+    * \brief Indicates that the setup or close operation is complete
+    * with success or failure.
+    * \param status, Indicates success or failure in terms of status code.
+    */
+    virtual void complete(ServiceClientCallbackStatus status) = 0;
+
+    /**
+    * \brief Indicates an error condition from one of the underlying clients, including
+    * identity, connector or update client.
+    * \param error, Indicates an error code translated to MbedCloudClient::Error.
+    * \param reason, Indicates human readable text for error description.
+    */
+    virtual void error(int error, const char *reason) = 0;
+
+    /**
+    * \brief A callback indicating that the value of the resource object is updated
+    *  by the LWM2M Cloud server.
+    * \param base, The object whose value is updated.
+    * \param type, The type of the object.
+    */
+    virtual void value_updated(M2MBase *base, M2MBase::BaseType type) = 0;
+};
+
+
+/**
+ *  \brief ServiceClient
+ *  This class handles all internal interactions between various client
+ *  components including connector, identity and update.
+ *  This class maintains the state machine for the use case flow of mbed Cloud
+ *  Client.
+ */
+
+class ServiceClient : private ConnectorClientCallback
+{
+public:
+
+    /**
+     * \brief An enum defining the different states of
+     * ServiceClient during the client flow.
+     */
+    enum StartupMainState {
+        State_Init,
+        State_Bootstrap,
+        State_Register,
+        State_Success,
+        State_Failure,
+        State_Unregister
+    };
+
+public:
+
+    /**
+    *  \brief Constructor.
+    *  \param interface, Takes the structure that contains the
+    *   needed information for an endpoint client to register.
+    */
+    ServiceClient(ServiceClientCallback& callback);
+
+    /**
+    *  \brief Destructor.
+    */
+    virtual ~ServiceClient();
+
+    /**
+    *  \brief Starts the registration or bootstrap sequence from MbedCloudClient.
+    *  \param callback, Takes the callback for the status from ConnectorClient.
+    *  \param client_objs, A list of objects to be registered to Cloud.
+    */
+    void initialize_and_register(M2MBaseList& reg_objs);
+
+    /**
+     * \brief Returns the ConnectorClient handler.
+     * \return ConnectorClient, handled for ConnectorClient.
+    */
+    ConnectorClient &connector_client();
+
+    /**
+     * \brief Returns const ConnectorClient handler.
+     * \return const ConnectorClient, handled for ConnectorClient.
+    */
+    const ConnectorClient &connector_client() const;
+
+    /**
+     * \brief Set resource value in the Device Object
+     *
+     * \param resource Device enum to have value set.
+     * \param value String object.
+     * \return True if successful, false otherwise.
+     */
+    bool set_device_resource_value(M2MDevice::DeviceResource resource,
+                                   const std::string& value);
+
+    /**
+     * \brief Set resource value in the Device Object
+     *
+     * \param resource Device enum to have value set.
+     * \param value Byte buffer.
+     * \param length Buffer length.
+     * \return True if successful, false otherwise.
+     */
+    bool set_device_resource_value(M2MDevice::DeviceResource resource,
+                                   const char* value,
+                                   uint32_t length);
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+    /**
+     * \brief Registers a callback function for authorizing firmware downloads and reboots.
+     * \param handler Callback function.
+     */
+    void set_update_authorize_handler(void (*handler)(int32_t request));
+
+    /**
+     * \brief Authorize request passed to authorization handler.
+     * \param request Request being authorized.
+     */
+    void update_authorize(int32_t request);
+
+    /**
+     * \brief Registers a callback function for monitoring download progress.
+     * \param handler Callback function.
+     */
+    void set_update_progress_handler(void (*handler)(uint32_t progress, uint32_t total));
+
+    /**
+     * \brief Callback function for the Update Client.
+     * \param error Internal Update Client error code.
+     */
+    void update_error_callback(int32_t error);
+#endif
+
+protected :
+
+    // Implementation of ConnectorClientCallback
+    /**
+    * \brief Indicates that the registration or unregistration operation is complete
+    * with success or failure.
+    * \param status, Indicates success or failure in terms of status code.
+    */
+    virtual void registration_process_result(ConnectorClient::StartupSubStateRegistration status);
+
+    /**
+    * \brief Indicates a connector error condition from an underlying M2MInterface client.
+    * \param error, Indicates an error code translated from M2MInterface::Error.
+    */
+    virtual void connector_error(M2MInterface::Error error, const char *reason);
+
+    /**
+    * \brief A callback indicating that the value of the resource object is updated
+    *  by the LWM2M Cloud server.
+    * \param base, The object whose value is updated.
+    * \param type, The type of the object.
+    */
+    virtual void value_updated(M2MBase *base, M2MBase::BaseType type);
+
+    /**
+     * \brief Redirects the state machine to the right function.
+     * \param current_state, The current state to be set.
+     * \param data, The data to be passed to the state function.
+     */
+    void state_function(StartupMainState current_state);
+
+    /**
+     * \brief The state engine maintaining the state machine logic.
+     */
+    void state_engine(void);
+
+    /**
+    * An external event that can trigger the state machine.
+    * \param new_state, The new state to which the state machine should go.
+    * \param data, The data to be passed to the state machine.
+    */
+    void external_event(StartupMainState new_state);
+
+    /**
+    * An internal event generated by the state machine.
+    * \param new_state, The new state to which the state machine should go.
+    * \param data, The data to be passed to the state machine.
+    */
+    void internal_event(StartupMainState new_state);
+
+    /**
+    * When the bootstrap is started.
+    */
+    void state_bootstrap();
+
+    /**
+    * When the registration is started.
+    */
+    void state_register();
+
+    /**
+    * When the registration is successful.
+    */
+    void state_success();
+
+    /**
+    * When the registration has failed.
+    */
+
+    void state_failure();
+
+    /**
+    * When the client unregisters.
+    */
+    void state_unregister();
+
+private:
+    M2MDevice* device_object_from_storage();
+
+    /* lookup table for printing hexadecimal values */
+    static const uint8_t hex_table[16];
+
+    ServiceClientCallback           &_service_callback;
+    // data which is pending for the registration
+    const char                      *_service_uri;
+    void                            *_stack;
+    M2MBaseList                     *_client_objs;
+    StartupMainState                _current_state;
+    bool                            _event_generated;
+    bool                            _state_engine_running;
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+    bool                            _setup_update_client;
+#endif
+    ConnectorClient                 _connector_client;
+};
+
+#endif // !__SERVICE_CLIENT_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/include/UpdateClient.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,127 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef MBED_CLOUD_CLIENT_UPDATE_CLIENT_H
+#define MBED_CLOUD_CLIENT_UPDATE_CLIENT_H
+
+#include "mbed-client/m2minterface.h"
+#include "update-client-hub/update_client_public.h"
+
+namespace UpdateClient
+{
+    /**
+     * Error codes used by the Update Client.
+     *
+     * Warning: a recoverable error occured, no user action required.
+     * Error  : a recoverable error occured, action required. E.g. the
+     *          application has to free some space and let the Update
+     *          Service try again.
+     * Fatal  : a non-recoverable error occured, application should safe
+     *          ongoing work and reboot the device.
+     */
+    enum {
+        WarningBase                     = 0x0400, // Range reserved for Update Error from 0x0400 - 0x04FF
+        WarningCertificateNotFound      = WarningBase + ARM_UC_WARNING_CERTIFICATE_NOT_FOUND,
+        WarningIdentityNotFound         = WarningBase + ARM_UC_WARNING_IDENTITY_NOT_FOUND,
+        WarningVendorMismatch           = WarningBase + ARM_UC_WARNING_VENDOR_MISMATCH,
+        WarningClassMismatch            = WarningBase + ARM_UC_WARNING_CLASS_MISMATCH,
+        WarningDeviceMismatch           = WarningBase + ARM_UC_WARNING_DEVICE_MISMATCH,
+        WarningCertificateInvalid       = WarningBase + ARM_UC_WARNING_CERTIFICATE_INVALID,
+        WarningSignatureInvalid         = WarningBase + ARM_UC_WARNING_SIGNATURE_INVALID,
+        WarningURINotFound              = WarningBase + ARM_UC_WARNING_URI_NOT_FOUND,
+        WarningRollbackProtection       = WarningBase + ARM_UC_WARNING_ROLLBACK_PROTECTION,
+        WarningUnknown                  = WarningBase + ARM_UC_WARNING_UNKNOWN,
+        WarningCertificateInsertion,
+        ErrorBase,
+        ErrorWriteToStorage             = ErrorBase + ARM_UC_ERROR_WRITE_TO_STORAGE,
+        ErrorInvalidHash                = ErrorBase + ARM_UC_ERROR_INVALID_HASH,
+        FatalBase
+    };
+
+    enum {
+        RequestInvalid                  = ARM_UCCC_REQUEST_INVALID,
+        RequestDownload                 = ARM_UCCC_REQUEST_DOWNLOAD,
+        RequestInstall                  = ARM_UCCC_REQUEST_INSTALL
+    };
+
+    /**
+     * \brief Initialization function for the Update Client.
+     * \param Callback to error handler.
+     */
+    void UpdateClient(FP1<void, int32_t> callback);
+
+    /**
+     * \brief Populate M2MObjectList with Update Client objects.
+     * \details The function takes an existing object list and adds LWM2M
+     *          objects needed by the Update Client.
+     *
+     * \param list M2MObjectList reference.
+     */
+    void populate_object_list(M2MBaseList& list);
+
+    /**
+     * \brief Registers a callback function for authorizing firmware downloads and reboots.
+     * \param handler Callback function.
+     */
+    void set_update_authorize_handler(void (*handler)(int32_t request));
+
+    /**
+     * \brief Authorize request passed to authorization handler.
+     * \param request Request being authorized.
+     */
+    void update_authorize(int32_t request);
+
+    /**
+     * \brief Registers a callback function for monitoring download progress.
+     * \param handler Callback function.
+     */
+    void set_update_progress_handler(void (*handler)(uint32_t progress, uint32_t total));
+
+    /**
+     * \brief Fills the buffer with the 16-byte vendor UUID
+     * \param buffer The buffer to fill with the UUID
+     * \param buffer_size_max The maximum avaliable space in the buffer
+     * \param value_size A pointer to a length variable to populate with the length of the UUID (always 16)
+     * \retval CCS_STATUS_MEMORY_ERROR when the buffer is less than 16 bytes
+     * \retval CCS_STATUS_KEY_DOESNT_EXIST when no vendor ID is present
+     * \retval CCS_STATUS_SUCCESS on success
+     */
+    int getVendorId(uint8_t* buffer, size_t buffer_size_max, size_t* value_size);
+    /**
+     * \brief Fills the buffer with the 16-byte device class UUID
+     * \param buffer The buffer to fill with the UUID
+     * \param buffer_size_max The maximum avaliable space in the buffer
+     * \param value_size A pointer to a length variable to populate with the length of the UUID (always 16)
+     * \retval CCS_STATUS_MEMORY_ERROR when the buffer is less than 16 bytes
+     * \retval CCS_STATUS_KEY_DOESNT_EXIST when no device class ID is present
+     * \retval CCS_STATUS_SUCCESS on success
+     */
+    int getClassId(uint8_t* buffer, size_t buffer_size_max, size_t* value_size);
+    /**
+     * \brief Fills the buffer with the 16-byte device UUID
+     * \param buffer The buffer to fill with the UUID
+     * \param buffer_size_max The maximum avaliable space in the buffer
+     * \param value_size A pointer to a length variable to populate with the length of the UUID (always 16)
+     * \retval CCS_STATUS_MEMORY_ERROR when the buffer is less than 16 bytes
+     * \retval CCS_STATUS_KEY_DOESNT_EXIST when no device ID is present
+     * \retval CCS_STATUS_SUCCESS on success
+     */
+    int getDeviceId(uint8_t* buffer, size_t buffer_size_max, size_t* value_size);
+}
+
+#endif // MBED_CLOUD_CLIENT_UPDATE_CLIENT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/source/include/UpdateClientResources.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,59 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef MBED_CLOUD_CLIENT_UPDATE_RESOURCES_H
+#define MBED_CLOUD_CLIENT_UPDATE_RESOURCES_H
+
+#ifdef MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#include MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#endif
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+#include "update-client-hub/update_client_hub.h"
+#endif
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef MBED_CLOUD_DEV_UPDATE_ID
+extern const uint8_t arm_uc_vendor_id[];
+extern const uint16_t arm_uc_vendor_id_size;
+extern const uint8_t arm_uc_class_id[];
+extern const uint16_t arm_uc_class_id_size;
+#endif
+
+#ifdef MBED_CLOUD_DEV_UPDATE_CERT
+extern const uint8_t arm_uc_default_fingerprint[];
+extern const uint16_t arm_uc_default_fingerprint_size;
+extern const uint8_t arm_uc_default_certificate[];
+extern const uint16_t arm_uc_default_certificate_size;
+#endif
+
+#ifdef MBED_CLOUD_DEV_UPDATE_PSK
+extern const uint8_t arm_uc_default_psk[];
+extern uint16_t arm_uc_default_psk_bits;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MBED_CLOUD_CLIENT_UPDATE_RESOURCES_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,3 @@
+*/test/*
+*/Test/*
+*/test-utils/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/atomic-queue/atomic-queue.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,270 @@
+// ----------------------------------------------------------------------------
+// Copyright 2015-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+/**
+ * @file atomic-queue.h
+ * @brief A linked-list queue based on atomic access
+ * @details This queue is designed explicitly for use in contexts where atomic
+ * access is desirable. Using an atomic queue comes with three major benefits:
+ *
+ * 1. This allows the queue to be used in contexts where some RTOS primitives
+ *    (mutexes) cannot be used, such as interrupt context.
+ * 2. On many platforms, critical sections are very expensive, while atomics
+ *    are not. Thus, there is a significant performance benefit to using atomic
+ *    primitives wherever possible.
+ * 3. Atomic operations have the least effect on all other execution contexts
+ *    on the device. Critical sections have performance and responsiveness side
+ *    effects. Mutexes can disrupt the execution of other threads. Atomics do 
+ *    not affect the execution of other contexts and are immune to priority
+ *    inversion.
+ * 
+ * In short, the atomics are the most cooperative way of building a queue.
+ * 
+ * Theory of Operation:
+ * The queue is intended to be multi-writer/multi-reader. Multi-writer
+ * semantics have been fully validated, but multi-reader semantics still
+ * require additional validation. It is recommended that the atomic queue be
+ * treated as multi-writer/single-reader until this validation is complete.
+ * 
+ * Assumptions:
+ * The queue MUST own all memory currently in the queue. Any modification
+ * to a queue element that is already enqueued can result in undefined
+ * behaviour.
+ * Because of this, the queue expects queue elements to be pool-allocated prior
+ * to insertion and freed after extraction.
+ * 
+ * To mitigate the possibility of a double-insert, the queue elements are
+ * populated with a "lock" field. This is used to indicate when the element is
+ * in use, to ensure that a parallel thread of execution cannot accidentally
+ * reuse an element that has already been inserted.
+ * 
+ * *NB:* Element locks are unnecessary when the atomic queue is used
+ * exclusively with pool allocated queue elements.
+ * 
+ * Queue Organization:
+ * The queue is a singly linked list. The list pointer is the tail pointer of
+ * the queue. The tail pointer points to the last element in the queue. To find
+ * the head of the queue, the dequeue mechanism traverses the list, starting at
+ * the tail of the queue until it finds the last list element, which is the
+ * head of the queue. Each queue element contains:
+ * * Next pointer
+ * * Lock element
+ * * Data (void* by default, custom element possible)
+ * 
+ * Element Insertion:
+ * To insert an element:
+ * Do: 
+ * * Read the tail pointer (load exclusive).
+ * * Write the tail pointer into the next pointer of the new element.
+ * * Write the tail pointer with the address of the new element 
+ *   (store exclusive).
+ * Until the store is successful.
+ * 
+ * If a different thread of higher priority executed between the read and the
+ * last write, it will cause the new element to have the wrong next pointer.
+ * This is why the load-exclusive and store-exclusive are used. These are ARMv7
+ * instructions that allow a given thread of execution to recognize whether it
+ * has been interrupted. If another thread has set the exclusive bit, then the
+ * store will fail.
+ * 
+ * Element Extraction:
+ * Extracting an element is much more complex than element insertion due to the
+ * need to traverse the queue.
+ * 
+ * 1. Read the tail pointer
+ * 2. If the tail pointer is NULL, return NULL.
+ * 3. Set the current element to the tail pointer.
+ * 4. Read the current element's next pointer (load exclusive).
+ * 5. If the next pointer was NULL, start over (go to 1.)
+ * 6. Load the next element.
+ * 7. Check the value of the next element's next pointer
+ * 8. If it is non-NULL, set the current element pointer to the next element and go to 4.
+ * 9. Otherwise, set the current element's next pointer to NULL (store exclusive).
+ * 10. Return the next element.
+ * 
+ * There is the potential for another thread of execution to interrupt the
+ * search for the head of the queue. This should cause the dequeue mechanism to
+ * find a NULL next pointer in the current element. However, this may depend on
+ * other circumstances in the system, which might break the behaviour of the
+ * queue. Until this is fully analyzed, the queue should be treated as single-
+ * reader/multi-writer.
+ */
+
+#ifndef __ATOMIC_QUEUE_H__
+#define __ATOMIC_QUEUE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+
+#ifndef ATOMIC_QUEUE_CUSTOM_ELEMENT
+struct atomic_queue_element {
+    struct atomic_queue_element * volatile next;
+    uintptr_t lock;
+    void * data;
+};
+#endif
+
+struct atomic_queue {
+    struct atomic_queue_element * volatile tail;
+};
+
+enum aq_failure_codes {
+    ATOMIC_QUEUE_SUCCESS = 0,
+    ATOMIC_QUEUE_NULL_QUEUE,
+    ATOMIC_QUEUE_NULL_ELEMENT,
+    ATOMIC_QUEUE_DUPLICATE_ELEMENT,
+    
+};
+
+/**
+ * \brief Add an element to the tail of the queue
+ *
+ * Since the queue only maintains a tail pointer, this simply inserts the new element before the tail pointer
+ *
+ * Element Insertion:
+ * To insert an element:
+ * Do: 
+ * * Read the tail pointer (load exclusive).
+ * * Write the tail pointer into the next pointer of the new element.
+ * * Write the tail pointer with the address of the new element 
+ *   (store exclusive).
+ * Until the store is successful.
+ *
+ * If a different thread of higher priority executed between the read and the
+ * last write, it will cause the new element to have the wrong next pointer.
+ * This is why the load-exclusive and store-exclusive are used. These are ARMv7
+ * instructions that allow a given thread of execution to recognize whether it
+ * has been interrupted. If another thread has set the exclusive bit, then the
+ * store will fail. 
+ * 
+ * @param[in,out] q the queue structure to operate on
+ * @param[in] e The element to add to the queue
+ */
+int aq_push_tail(struct atomic_queue * q, struct atomic_queue_element * e);
+/**
+ * \brief Get an element from the head of the queue
+ *
+ * This function iterates over the queue and removes an element from the head when it finds the head. This is slower
+ * than maintaining a head pointer, but it is necessary to ensure that a pop is completely atomic.
+ *
+ * Element Extraction:
+ * Extracting an element is much more complex than element insertion due to the
+ * need to traverse the queue.
+ * 
+ * 1. Read the tail pointer
+ * 2. If the tail pointer is NULL, return NULL.
+ * 3. Set the current element to the tail pointer.
+ * 4. Read the current element's next pointer (load exclusive).
+ * 5. If the next pointer was NULL, start over (go to 1.)
+ * 6. Load the next element.
+ * 7. Check the value of the next element's next pointer
+ * 8. If it is non-NULL, set the current element pointer to the next element and go to 4.
+ * 9. Otherwise, set the current element's next pointer to NULL (store exclusive).
+ * 10. Return the next element.
+ * 
+ * There is the potential for another thread of execution to interrupt the
+ * search for the head of the queue. This should cause the dequeue mechanism to
+ * find a NULL next pointer in the current element. However, this may depend on
+ * other circumstances in the system, which might break the behaviour of the
+ * queue. Until this is fully analyzed, the queue should be treated as single-
+ * reader/multi-writer.
+ * 
+ * @param[in,out] q The queue to pop from
+ * @return The popped element or NULL if the queue was empty
+ */
+struct atomic_queue_element * aq_pop_head(struct atomic_queue * q);
+/**
+ * Check if there are any elements in the queue
+ *
+ * Note that there is no guarantee that a queue which is not empty when this API is called will not be become empty
+ * before aq_pop_head is called
+ *
+ * @retval non-zero when the queue is empty
+ * @retval 0 when the queue is not empty
+ */
+int aq_empty(struct atomic_queue * q);
+/**
+ * Iterates over the queue and counts the elements in the queue
+ *
+ * The value returned by this function may be invalid by the time it returns. Do not depend on this value except in
+ * a critical section.
+ *
+ * @return the number of elements in the queue
+ */
+unsigned aq_count(struct atomic_queue * q);
+
+/**
+ * Initialize an atomic queue element.
+ *
+ * WARNING: Only call this function one time per element, or it may result in undefined behaviour.
+ *
+ * @param[in] element Element to initialize
+ */
+void aq_initialize_element(struct atomic_queue_element* e);
+
+/**
+ * Take an element (this acquires the element lock)
+ * 
+ * @param[in] element Element to take
+ */
+int aq_element_take(struct atomic_queue_element * e);
+
+/**
+ * Release an element (this releases the element lock)
+ * 
+ * @param[in] element Element to release
+ */
+int aq_element_release(struct atomic_queue_element * e);
+
+/**
+ * Atomic Compare and Set
+ * 
+ * Take a pointer to a uintptr_t, compare its current value to oldval. If it is
+ * as expected, try to write newval to the pointer target. Fail if interrupted.
+ * 
+ * @param[in,out] ptr A pointer to the target of the atomic compare and set
+ * @param[in]     oldval A value to compare with the target of ptr.
+ * @param[in]     newval A new value to store to the target of ptr.
+ * @retval 1 if newval was stored
+ * @retval 0 if oldval did not match *ptr, or if the store was interrupted.
+ */
+int aq_atomic_cas_uintptr(uintptr_t *ptr, uintptr_t oldval, uintptr_t newval);
+
+/**
+ * Atomic increment
+ * 
+ * Increment the value pointed to by ptr and increment it by inc atomically
+ * This is just a passthrough to __sync_add_and_fetch on platforms where it
+ * is supported.
+ * 
+ * @param[in,out] ptr A pointer to the target of the increment
+ * @param[in]     inc A value by which to increment *ptr
+ * @return the new value of *ptr
+ */
+int32_t aq_atomic_inc_int32(int32_t *ptr, int32_t inc);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __ATOMIC_QUEUE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/aq_critical.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,57 @@
+// ----------------------------------------------------------------------------
+// Copyright 2015-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __ATOMIC_QUEUE_CRITICAL_H__
+#define __ATOMIC_QUEUE_CRITICAL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Mark the start of a critical section
+  *
+  * This function should be called to mark the start of a critical section of code.
+  * \note
+  * NOTES:
+  * 1) The use of this style of critical section is targetted at C based implementations.
+  * 2) These critical sections can be nested.
+  * 3) The interrupt enable state on entry to the first critical section (of a nested set, or single
+  *    section) will be preserved on exit from the section.
+  * 4) This implementation will currently only work on code running in privileged mode.
+  */
+void aq_critical_section_enter(void);
+
+/** Mark the end of a critical section
+  *
+  * This function should be called to mark the end of a critical section of code.
+  * \note
+  * NOTES:
+  * 1) The use of this style of critical section is targetted at C based implementations.
+  * 2) These critical sections can be nested.
+  * 3) The interrupt enable state on entry to the first critical section (of a nested set, or single
+  *    section) will be preserved on exit from the section.
+  * 4) This implementation will currently only work on code running in privileged mode.
+  */
+void aq_critical_section_exit(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
+#endif // __ATOMIC_QUEUE_CRITICAL_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/atomic-cm3.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,58 @@
+// ----------------------------------------------------------------------------
+// Copyright 2015-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "atomic.h"
+
+#if defined(TARGET_LIKE_MBED)
+#include "cmsis.h"
+#endif
+
+#if defined(__CORTEX_M) && (__CORTEX_M >= 0x03)
+
+#define STATIC_ASSERT(STATIC_ASSERT_FAILED,MSG)\
+    switch(0){\
+        case 0:case (STATIC_ASSERT_FAILED): \
+        break;}
+
+#include <stddef.h>
+#include <stdint.h>
+
+int aq_atomic_cas_deref_uintptr(uintptr_t* volatile * ptrAddr,
+                            uintptr_t** currentPtrValue,
+                            uintptr_t expectedDerefValue,
+                            uintptr_t* newPtrValue,
+                            uintptr_t valueOffset)
+{
+    STATIC_ASSERT(sizeof(uintptr_t) == sizeof(uint32_t), Error: Pointer size mismatch)
+    uint32_t *current;
+    current = (uint32_t *)__LDREXW((volatile uint32_t *)ptrAddr);
+    if (currentPtrValue != NULL) {
+        *currentPtrValue = (uintptr_t *)current;
+    }
+    if (current == NULL) {
+        return AQ_ATOMIC_CAS_DEREF_NULLPTR;
+    } else if ( *(uint32_t *)((uintptr_t)current + valueOffset) != expectedDerefValue) {
+        return AQ_ATOMIC_CAS_DEREF_VALUE;
+    } else if(__STREXW((uint32_t)newPtrValue, (volatile uint32_t *)ptrAddr)) {
+        return AQ_ATOMIC_CAS_DEREF_INTERUPTED;
+    } else {
+        return AQ_ATOMIC_CAS_DEREF_SUCCESS;
+    }
+}
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/atomic-queue.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,127 @@
+// ----------------------------------------------------------------------------
+// Copyright 2015-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "atomic-queue/atomic-queue.h"
+#include "atomic.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#define CORE_UTIL_ASSERT_MSG(test, msg)
+
+
+int aq_element_take(struct atomic_queue_element * e)
+{
+    if (!e) { return ATOMIC_QUEUE_NULL_ELEMENT;}
+    // Duplicate element check using lock
+    uintptr_t lock; // This is initialized in the do/while loop.
+    // Check/obtain a lock on the element.
+    do {
+        lock = e->lock;
+        if (lock) {
+            return ATOMIC_QUEUE_DUPLICATE_ELEMENT;
+        }
+    } while (!aq_atomic_cas_uintptr(&e->lock, lock, 1));
+    return ATOMIC_QUEUE_SUCCESS;
+}
+
+int aq_element_release(struct atomic_queue_element * e)
+{
+    if (!e) { return ATOMIC_QUEUE_NULL_ELEMENT;}
+    e->lock = 0;
+    return ATOMIC_QUEUE_SUCCESS;
+}
+
+int aq_push_tail(struct atomic_queue * q, struct atomic_queue_element * e)
+{
+    CORE_UTIL_ASSERT_MSG(q != NULL, "null queue used");
+    if (!e) { return ATOMIC_QUEUE_NULL_ELEMENT;}
+    if (q == NULL) {
+        return ATOMIC_QUEUE_NULL_QUEUE;
+    }
+
+    do {
+        e->next = q->tail;
+    } while (!aq_atomic_cas_uintptr((uintptr_t *)&q->tail, (uintptr_t)e->next, (uintptr_t)e));
+
+    return ATOMIC_QUEUE_SUCCESS;
+}
+
+struct atomic_queue_element * aq_pop_head(struct atomic_queue * q)
+{
+    CORE_UTIL_ASSERT_MSG(q != NULL, "null queue used");
+    if (q == NULL) {
+        return NULL;
+    }
+    struct atomic_queue_element * current;
+    int fail = AQ_ATOMIC_CAS_DEREF_VALUE;
+    while (fail != AQ_ATOMIC_CAS_DEREF_SUCCESS) {
+        // Set the element reference pointer to the tail pointer
+        struct atomic_queue_element * volatile * px = &q->tail;
+        if (*px == NULL) {
+            return NULL;
+        }
+        fail = AQ_ATOMIC_CAS_DEREF_VALUE;
+        while (fail == AQ_ATOMIC_CAS_DEREF_VALUE) {
+            fail = aq_atomic_cas_deref_uintptr((uintptr_t * volatile *)px,
+                            (uintptr_t **)&current,
+                            (uintptr_t) NULL,
+                            NULL,
+                            offsetof(struct atomic_queue_element, next));
+            if (fail == AQ_ATOMIC_CAS_DEREF_VALUE) {
+                // Detect a loop to the tail of the queue
+                if (current->next == q->tail) {
+                    return NULL;
+                }
+                px = &current->next;
+            }
+        }
+    }
+
+    return current;
+}
+
+
+int aq_empty(struct atomic_queue * q)
+{
+    return q->tail == NULL;
+}
+
+unsigned aq_count(struct atomic_queue *q)
+{
+    unsigned x;
+    struct atomic_queue_element * volatile e;
+    if (aq_empty(q)) {
+        return 0;
+    }
+    e = q->tail;
+    for (x = 1; e->next != NULL; x++, e = e->next) {
+        if (e->next == q->tail){
+            return (unsigned)-1;
+        }
+    }
+    return x;
+}
+
+void aq_initialize_element(struct atomic_queue_element* e)
+{
+    if (!e) { return;}
+    e->lock = 0;
+    e->next = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/atomic.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,85 @@
+// ----------------------------------------------------------------------------
+// Copyright 2015-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include <stddef.h>
+#include "atomic.h"
+#include "aq_critical.h"
+
+#if defined(TARGET_LIKE_MBED)
+#include "cmsis.h"
+#endif
+
+#if !defined(__CORTEX_M) || (__CORTEX_M < 0x03)
+
+int aq_atomic_cas_deref_uintptr(uintptr_t* volatile * ptrAddr,
+                            uintptr_t** currentPtrValue,
+                            uintptr_t expectedDerefValue,
+                            uintptr_t* newPtrValue,
+                            uintptr_t valueOffset)
+{
+    int rc;
+    aq_critical_section_enter();
+    uintptr_t *current = *ptrAddr;
+    if (currentPtrValue != NULL) {
+        *currentPtrValue = current;
+    }
+    if (current == NULL) {
+        rc = AQ_ATOMIC_CAS_DEREF_NULLPTR;
+    } else if ( *(uintptr_t *)((uintptr_t)current + valueOffset) != expectedDerefValue) {
+        rc = AQ_ATOMIC_CAS_DEREF_VALUE;
+    } else {
+        *ptrAddr = newPtrValue;
+        rc = AQ_ATOMIC_CAS_DEREF_SUCCESS;
+    }
+    aq_critical_section_exit();
+    return rc;
+}
+#endif
+
+
+#if defined(__GNUC__) && (!defined(__CORTEX_M) || (__CORTEX_M >= 0x03))
+int aq_atomic_cas_uintptr(uintptr_t *ptr, uintptr_t oldval, uintptr_t newval) {
+    return __sync_bool_compare_and_swap(ptr, oldval, newval);
+}
+
+int32_t aq_atomic_inc_int32(int32_t *ptr, int32_t inc) {
+    return __sync_add_and_fetch(ptr, inc);
+}
+#else
+int aq_atomic_cas_uintptr(uintptr_t *ptr, uintptr_t oldval, uintptr_t newval)
+{
+    int rc;
+    aq_critical_section_enter();
+    if (*ptr == oldval) {
+        rc = 1;
+        *ptr = newval;
+    } else {
+        rc = 0;
+    }
+    aq_critical_section_exit();
+    return rc;
+}
+int32_t aq_atomic_inc_int32(int32_t *ptr, int32_t inc) {
+    int32_t ret;
+    aq_critical_section_enter();
+    ret = *ptr + inc;
+    *ptr = ret;
+    aq_critical_section_exit();
+    return ret;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/atomic.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,68 @@
+// ----------------------------------------------------------------------------
+// Copyright 2015-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ATOMIC_QUEUE_ATOMIC_H
+#define ATOMIC_QUEUE_ATOMIC_H
+#include <stdint.h>
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+   AQ_ATOMIC_CAS_DEREF_SUCCESS = 0,
+   AQ_ATOMIC_CAS_DEREF_NULLPTR,
+   AQ_ATOMIC_CAS_DEREF_VALUE,
+   AQ_ATOMIC_CAS_DEREF_INTERUPTED,
+};
+
+/**
+ * @brief Atomically compares the value of a dereferenced pointer, replacing the pointer on success.
+ * @detail aq_atomic_cas_deref_uintptr provides a mechanism to atomically change a pointer based on a value contained
+ *     in the structure referenced by the pointer. This is done in the following sequence of operations:
+ *
+ *     1. Load the value of `*ptrAddr`
+ *     2. Optionally store the current value of `*ptrAddr`
+ *     3. Check that the pointer is valid: `*ptrAddr != NULL`
+ *     4. Check the value of the referenced location: `*(*ptrAddr + valueOffset) == expectedDerefValue` (casts omitted)
+ *     5. If 3 and 4 succeeded, store newPtrValue: `*ptrAddr = newPtrValue` (NOTE: in non-blocking implementations, this step can fail)
+ *     6. Return a status code based on the results of 3, 4, 5.
+ *
+ * @param[in,out] ptrAddr            The address of the pointer to manipulate
+ * @param[out]    currentPtrValue    A pointer to a container for the current value of *ptrAddr
+ * @param[in]     expectedDerefValue This is the value that is expected at *(uintptr_t *)((uintptr_t)*ptrAddr + valueOffset)
+ * @param[in]     newPtrValue        The value to store to *ptrAddr if the comparison is successful
+ * @param[in]     valueOffset        The offset of the target value from *ptrAddr
+ *
+ * @retval AQ_ATOMIC_CAS_DEREF_SUCCESS    The compare and set has succeeded
+ * @retval AQ_ATOMIC_CAS_DEREF_NULLPTR    `*ptrAddr` was `NULL`
+ * @retval AQ_ATOMIC_CAS_DEREF_VALUE      The value test failed (*(*ptrAddr + valueOffset) != expectedDerefValue`)
+ * @retval AQ_ATOMIC_CAS_DEREF_INTERUPTED Another context modified `*ptrAddr`
+ */
+int aq_atomic_cas_deref_uintptr(uintptr_t* volatile * ptrAddr,
+                            uintptr_t** currentPtrValue,
+                            uintptr_t expectedDerefValue,
+                            uintptr_t* newPtrValue,
+                            uintptr_t valueOffset);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+#endif // ATOMIC_QUEUE_ATOMIC_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/critical-nordic.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,90 @@
+// ----------------------------------------------------------------------------
+// Copyright 2015-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifdef TARGET_MCU_NRF51
+
+#include <stdint.h>                  // uint32_t, UINT32_MAX
+#include <stddef.h>                  // NULL
+#include <cmsis-core/core_generic.h> //__disable_irq, __enable_irq
+#include <assert.h>
+#include <stdbool.h>
+#include <nrf_soc.h>
+#include <nrf_sdm.h>
+
+// Module include
+#include "aq_critical.h"
+
+static volatile union {
+    uint32_t _PRIMASK_state;
+    uint8_t  _sd_state;
+} _state = { 0 } ;
+static volatile uint32_t _entry_count = 0;
+static volatile bool _use_softdevice_routine = false;
+
+void aq_critical_section_enter()
+{
+    // if a critical section has already been entered, just update the counter
+    if (_entry_count) {
+        ++_entry_count;
+        return;
+    }
+
+    // in this path, a critical section has never been entered
+    uint32_t primask = __get_PRIMASK();
+
+    // if interrupts are enabled, try to use the soft device
+    uint8_t sd_enabled;
+    if ((primask == 0) && (sd_softdevice_is_enabled(&sd_enabled) == NRF_SUCCESS) && sd_enabled == 1) {
+        // if the soft device can be use, use it
+        sd_nvic_critical_region_enter(&_state._sd_state);
+        _use_softdevice_routine = true;
+    } else {
+        // if interrupts where enabled, disable them
+        if(primask == 0) {
+            __disable_irq();
+        }
+
+        // store the PRIMASK state, it will be restored at the end of the critical section
+        _state._PRIMASK_state = primask;
+        _use_softdevice_routine = false;
+    }
+
+    assert(_entry_count == 0); // entry count should always be equal to 0 at this point
+    ++_entry_count;
+}
+
+void aq_critical_section_exit(void)
+{
+    assert(_entry_count > 0);
+    --_entry_count;
+
+    // If their is other segments which have entered the critical section, just leave
+    if (_entry_count) {
+        return;
+    }
+
+    // This is the last segment of the critical section, state should be restored as before entering
+    // the critical section
+    if (_use_softdevice_routine) {
+        sd_nvic_critical_region_exit(_state._sd_state);
+    } else {
+        __set_PRIMASK(_state._PRIMASK_state);
+    }
+}
+
+#endif //TARGET_MCU_NRF51
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/critical-pal.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,52 @@
+// ----------------------------------------------------------------------------
+// Copyright 2015-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(ATOMIC_QUEUE_USE_PAL) && !defined(TARGET_LIKE_MBED)
+
+#include <stdint.h>
+#include <assert.h>
+#include <unistd.h>
+
+#include "pal.h"
+// Module include
+#include "aq_critical.h"
+
+static palMutexID_t mutex = NULLPTR;
+static volatile unsigned irq_nesting_depth = 0;
+
+void aq_critical_section_enter() {
+    if (mutex == NULLPTR) {
+        palStatus_t rc = pal_osMutexCreate(&mutex);
+        assert(rc == PAL_SUCCESS);
+    }
+    if (++irq_nesting_depth > 1) {
+        return;
+    }
+    palStatus_t rc = pal_osMutexWait(mutex, PAL_RTOS_WAIT_FOREVER);
+    assert(rc == PAL_SUCCESS);
+}
+
+void aq_critical_section_exit(void) {
+    assert(irq_nesting_depth > 0);
+    if (--irq_nesting_depth == 0) {
+        palStatus_t rc = pal_osMutexRelease(mutex);
+        assert(rc == PAL_SUCCESS);
+    }
+}
+
+#endif // defined(ATOMIC_QUEUE_USE_PAL)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/critical-posix.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,72 @@
+// ----------------------------------------------------------------------------
+// Copyright 2015-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(TARGET_LIKE_POSIX) && !defined(ATOMIC_QUEUE_USE_PAL)
+
+// It's probably a better idea to define _POSIX_SOURCE in the target description
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 600
+#endif
+
+#include <stdint.h>
+#include <assert.h>
+#include <unistd.h>
+#include <signal.h>
+#include <pthread.h>
+
+// Module include
+#include "aq_critical.h"
+
+static pthread_mutex_t* get_mutex() {
+    static int initialized = 0;
+    static pthread_mutex_t Mutex;
+    if (!initialized)
+    {
+        pthread_mutexattr_t Attr;
+        pthread_mutexattr_init(&Attr);
+        pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
+        pthread_mutex_init(&Mutex, &Attr);
+        initialized = 1;
+    }
+    return &Mutex;
+}
+
+static volatile unsigned irq_nesting_depth = 0;
+static sigset_t old_sig_set;
+
+void aq_critical_section_enter() {
+    pthread_mutex_lock(get_mutex());
+    if (++irq_nesting_depth == 1) {
+        int rc;
+        sigset_t full_set;
+        rc = sigfillset(&full_set);
+        assert(rc == 0);
+        rc = sigprocmask(SIG_BLOCK, &full_set, &old_sig_set);
+        assert(rc == 0);
+    }
+}
+
+void aq_critical_section_exit(void) {
+    assert(irq_nesting_depth > 0);
+    if (--irq_nesting_depth == 0) {
+        int rc = sigprocmask(SIG_SETMASK, &old_sig_set, NULL);
+        assert(rc == 0);
+    }
+    pthread_mutex_unlock(get_mutex());
+}
+#endif // defined(TARGET_LIKE_POSIX)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/critical.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,108 @@
+// ----------------------------------------------------------------------------
+// Copyright 2015-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+// This critical section implementation is generic for mbed OS targets,
+// except Nordic ones
+#if defined(TARGET_LIKE_MBED) && !defined(TARGET_NORDIC)
+
+#include <stdint.h>                  // uint32_t, UINT32_MAX
+#include <stddef.h>                  // NULL
+
+#if defined(YOTTA_CFG_MBED_OS)
+#include "cmsis-core/core_generic.h" //__disable_irq, __enable_irq
+#else
+#include "cmsis.h"
+#endif
+
+#include <assert.h>
+
+// Module include
+#include "aq_critical.h"
+
+static volatile uint32_t interruptEnableCounter = 0;
+static volatile uint32_t critical_primask = 0;
+
+void aq_critical_section_enter()
+{
+    uint32_t primask;
+#if defined(__CORTEX_A9)
+    primask = __get_CPSR(); // get the current interrupt enabled state
+#else
+    primask = __get_PRIMASK(); // get the current interrupt enabled state
+#endif
+    __disable_irq();
+
+    // Save the interrupt enabled state as it was prior to any nested critical section lock use
+    if (!interruptEnableCounter) {
+#if defined(__CORTEX_A9)
+        critical_primask = primask & 0x80;
+#else
+        critical_primask = primask & 0x1;
+#endif
+    }
+#if 0
+    /* If the interruptEnableCounter overflows or we are in a nested critical section and interrupts
+       are enabled, then something has gone badly wrong thus assert an error.
+    */
+
+    /* FIXME: This assertion needs to be commented out for the moment, as it
+     *        triggers a fault when uVisor is enabled. For more information on
+     *        the fault please checkout ARMmbed/mbed-drivers#176. */
+
+    assert(interruptEnableCounter < UINT32_MAX);
+    if (interruptEnableCounter > 0) {
+         assert(primask & 0x1);
+    }
+#endif
+
+    if (interruptEnableCounter < UINT32_MAX) {
+        interruptEnableCounter++;
+    }
+}
+
+void aq_critical_section_exit(void)
+{
+    // If critical_section_enter has not previously been called, do nothing
+    if (interruptEnableCounter) {
+#if 0
+        /* FIXME: This assertion needs to be commented out for the moment, as it
+         *        triggers a fault when uVisor is enabled. For more information
+         *        on the fault please checkout ARMmbed/mbed-drivers#176. */
+
+        uint32_t primask;
+#if defined(__CORTEX_A9)
+        primask = __get_CPSR(); // get the current interrupt enabled state
+#else
+        primask = __get_PRIMASK(); // get the current interrupt enabled state
+#endif
+         assert(primask & 0x1); // Interrupts must be disabled on invoking an exit from a critical section
+#endif
+
+        interruptEnableCounter--;
+
+
+        /* Only re-enable interrupts if we are exiting the last of the nested critical sections and
+           interrupts were enabled on entry to the first critical section.
+        */
+        if (!interruptEnableCounter && !critical_primask) {
+            __enable_irq();
+        }
+    }
+}
+
+#endif // defined(TARGET_LIKE_MBED) && !defined(TARGET_NORDIC)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/atomic-queue/source/posix.cmake	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,23 @@
+# ----------------------------------------------------------------------------
+# Copyright 2015-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+if(TARGET_LIKE_POSIX)
+    target_link_libraries(${YOTTA_MODULE_NAME} "-pthread")
+    set_target_properties(${YOTTA_MODULE_NAME} PROPERTIES
+        COMPILE_FLAGS " -pthread ")
+endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/mbed_lib.json	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,33 @@
+{
+    "name": "update-client",
+    "config": {
+        "application-details": {
+            "help": "Location in memory where the application information can be read.",
+            "value": "0"
+        },
+        "bootloader-details": {
+            "help": "Location in memory where the bootloader information can be read.",
+            "value": "0"
+        },
+        "storage-address": {
+            "help": "When using address based storage (FlashIAP, Block Device), this is the starting address.",
+            "value": "0"
+        },
+        "storage-size": {
+            "help": "Total storage allocated.",
+            "value": "0"
+        },
+        "storage-locations": {
+            "help": "Number of equally sized locations the storage space should be split into.",
+            "value": "1"
+        },
+        "storage-page": {
+            "help": "Smallest write unit on storage device. Used for compile time check of download/write buffers.",
+            "value": "512"
+        },
+        "firmware-header-version": {
+            "help": "Version of the firmware metadata header.",
+            "value": "0"
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_crypto.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,432 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-common/arm_uc_config.h"
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_crypto.h"
+
+#include <string.h>
+
+
+#if ARM_UC_USE_PAL_CRYPTO
+#include "pal.h"
+#include "sotp.h"
+#ifndef palMDHandle_t
+#include "pal_Crypto.h"
+#else
+#include "mbedtls/md.h"
+#endif
+
+#define ARM_UC_CU_SHA256 PAL_SHA256
+arm_uc_error_t ARM_UC_verifyPkSignature(const arm_uc_buffer_t* ca, const arm_uc_buffer_t* hash, const arm_uc_buffer_t* sig)
+{
+    arm_uc_error_t err = {MFST_ERR_CERT_INVALID};
+    palX509Handle_t x509Cert;
+    if (PAL_SUCCESS == pal_x509Initiate(&x509Cert))
+    {
+        err.code = MFST_ERR_CERT_INVALID;
+        if (PAL_SUCCESS == pal_x509CertParse(x509Cert, ca->ptr, ca->size))
+        {
+            // if (PAL_SUCCESS == pal_x509CertVerify(x509Cert, palX509Handle_t x509CertChain))
+            // {
+                err.code = MFST_ERR_INVALID_SIGNATURE;
+                if (PAL_SUCCESS == pal_verifySignature(x509Cert, PAL_SHA256, hash->ptr, hash->size, sig->ptr, sig->size))
+                {
+                    err.code = MFST_ERR_NONE;
+                }
+            // }
+        }
+        pal_x509Free(&x509Cert);
+    }
+    return err;
+}
+
+arm_uc_error_t ARM_UC_cryptoHashSetup(arm_uc_mdHandle_t* hDigest, arm_uc_mdType_t mdType)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+    if (hDigest)
+    {
+        palStatus_t rc = pal_mdInit(hDigest, mdType);
+        if (rc == PAL_SUCCESS)
+        {
+            result.code = ARM_UC_CU_ERR_NONE;
+        }
+    }
+    return result;
+}
+
+arm_uc_error_t ARM_UC_cryptoHashUpdate(arm_uc_mdHandle_t* hDigest, arm_uc_buffer_t* input)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+    if (hDigest && input)
+    {
+        palStatus_t rc = pal_mdUpdate(*hDigest, input->ptr, input->size);
+        if (rc == PAL_SUCCESS)
+        {
+            result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
+        }
+    }
+    return result;
+}
+
+arm_uc_error_t ARM_UC_cryptoHashFinish(arm_uc_mdHandle_t* hDigest, arm_uc_buffer_t* output)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+
+    // TODO: validate buffer size? I guess we just hope for the best!
+    if (hDigest && output && output->size_max >= 256/8) // FIXME:PAL does not provide a method to extract this
+    {
+        palStatus_t rc = pal_mdFinal(*hDigest, output->ptr);
+
+        if (rc == PAL_SUCCESS)
+        {
+            result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
+            output->size = 256/8; // FIXME:PAL does not provide a method to extract this
+        }
+    }
+    if (hDigest)
+    {
+        palStatus_t rc = pal_mdFree(hDigest);
+        if (rc != PAL_SUCCESS && result.error == ERR_NONE)
+        {
+            result.module = TWO_CC('P','A');
+            result.error  = rc;
+        }
+    }
+    return result;
+}
+
+arm_uc_error_t ARM_UC_cryptoDecryptSetup(arm_uc_cipherHandle_t* hCipher, arm_uc_buffer_t* key, arm_uc_buffer_t* iv, int32_t aesKeySize)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+
+    if (key && key->ptr && iv && iv->ptr)
+    {
+        palStatus_t rc = 1;
+
+        switch (aesKeySize)
+        {
+            case 128:
+            case 256:
+            {
+                rc = pal_initAes(&hCipher->aes_context);
+                /* NOTE: From the mbedtls documentation:
+                 * Due to the nature of CTR you should use the same key schedule for
+                 * both encryption and decryption. So a context initialized with
+                 * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
+                 */
+                if (rc == PAL_SUCCESS)
+                {
+                    rc = pal_setAesKey(hCipher->aes_context, key->ptr, aesKeySize, PAL_KEY_TARGET_ENCRYPTION);
+                }
+                hCipher->aes_iv = iv->ptr;
+                break;
+            }
+            default:
+                // rc is still 1, this means the function returns Invalid Parameter
+                break;
+        }
+
+        if (rc == PAL_SUCCESS)
+        {
+            result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
+        }
+    }
+
+    return result;
+}
+
+arm_uc_error_t ARM_UC_cryptoDecryptUpdate(arm_uc_cipherHandle_t* hCipher, const uint8_t* input_ptr, uint32_t input_size, arm_uc_buffer_t* output)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+    size_t data_size = input_size < output->size_max ? input_size : output->size_max;
+    output->size = 0;
+    palStatus_t rc = pal_aesCTR(
+        hCipher->aes_context,
+        input_ptr,
+        output->ptr,
+        data_size,
+        hCipher->aes_iv
+    );
+    if (rc == PAL_SUCCESS)
+    {
+        result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
+        output->size = data_size;
+    }
+    return result;
+}
+
+arm_uc_error_t ARM_UC_cryptoDecryptFinish(arm_uc_cipherHandle_t* hCipher, arm_uc_buffer_t* output)
+{
+    pal_freeAes(&hCipher->aes_context);
+    (void) output;
+    return (arm_uc_error_t){ARM_UC_CU_ERR_NONE};
+}
+
+arm_uc_error_t ARM_UC_cryptoHMACSHA256(arm_uc_buffer_t* key,
+                                       arm_uc_buffer_t* input,
+                                       arm_uc_buffer_t* output)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+
+    palStatus_t pal_st = pal_mdHmacSha256(key->ptr, key->size,
+                                          input->ptr, input->size,
+                                          output->ptr, &(output->size));
+    if ((pal_st == PAL_SUCCESS) && (output->size == ARM_UC_SHA256_SIZE))
+    {
+        result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
+    }
+
+    return result;
+}
+
+int8_t mbed_cloud_client_get_rot_128bit(uint8_t *key_buf, uint32_t length)
+{
+    int8_t rv = -1;
+    palStatus_t status = PAL_ERR_GENERIC_FAILURE;
+
+#if (PAL_USE_HW_ROT)
+    status = pal_plat_osGetRoTFromHW(key_buf, length);
+#else
+    uint16_t actual_size;
+
+    sotp_result_e sotp_status = sotp_get(SOTP_TYPE_ROT, length, (uint32_t *)key_buf, &actual_size);
+    if (SOTP_SUCCESS == sotp_status && actual_size == ARM_UC_ROT_SIZE)
+    {
+        status = PAL_SUCCESS;
+    }
+#endif
+
+    if (status == PAL_SUCCESS)
+    {
+        rv = 0;
+    }
+    else
+    {
+        /* clear buffer on failure so we don't leak the rot */
+        memset(key_buf, 0, length);
+    }
+
+    return rv;
+}
+
+#else
+
+arm_uc_error_t ARM_UC_verifyPkSignature(const arm_uc_buffer_t* ca, const arm_uc_buffer_t* hash, const arm_uc_buffer_t* sig)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    mbedtls_x509_crt crt;
+    mbedtls_x509_crt_init(&crt);
+    int rc = mbedtls_x509_crt_parse_der(&crt, ca->ptr, ca->size);
+    if (rc < 0) {
+        err.code = MFST_ERR_CERT_INVALID;
+    } else {
+        rc = mbedtls_pk_verify(&crt.pk, MBEDTLS_MD_SHA256, hash->ptr, hash->size, sig->ptr, sig->size);
+        if (rc < 0) {
+            err.code = MFST_ERR_INVALID_SIGNATURE;
+        }
+    }
+    return err;
+}
+
+arm_uc_error_t ARM_UC_cryptoHashSetup(arm_uc_mdHandle_t* hDigest, arm_uc_mdType_t mdType)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+
+    const mbedtls_md_info_t* md_info = NULL;
+
+    if (hDigest)
+    {
+        mbedtls_md_init(hDigest);
+        md_info = mbedtls_md_info_from_type(mdType);
+        int mbedtls_result = mbedtls_md_setup(hDigest, md_info, 0);
+        mbedtls_result |= mbedtls_md_starts(hDigest);
+
+        if (mbedtls_result == 0)
+        {
+            result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
+        }
+    }
+
+    return result;
+}
+
+arm_uc_error_t ARM_UC_cryptoHashUpdate(arm_uc_mdHandle_t* hDigest, arm_uc_buffer_t* input)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+
+    if (hDigest && input)
+    {
+        int mbedtls_result = mbedtls_md_update(hDigest, input->ptr, input->size);
+
+        if (mbedtls_result == 0)
+        {
+            result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
+        }
+    }
+
+    return result;
+}
+
+arm_uc_error_t ARM_UC_cryptoHashFinish(arm_uc_mdHandle_t* hDigest, arm_uc_buffer_t* output)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+
+    if (hDigest && output && (output->size_max >= (unsigned)hDigest->md_info->size))
+    {
+        int mbedtls_result = mbedtls_md_finish(hDigest, output->ptr);
+
+        if (mbedtls_result == 0)
+        {
+            result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
+
+            output->size = hDigest->md_info->size;
+        }
+    }
+
+    // free memory
+    mbedtls_md_free(hDigest);
+
+    return result;
+}
+
+arm_uc_error_t ARM_UC_cryptoDecryptSetup(arm_uc_cipherHandle_t* hCipher, arm_uc_buffer_t* key, arm_uc_buffer_t* iv, int32_t aesKeySize)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+
+    if (key && key->ptr && iv && iv->ptr)
+    {
+        int mbedtls_result = 1;
+
+        switch (aesKeySize)
+        {
+            case 128:
+            case 256:
+            {
+                memset(hCipher->aes_partial, 0, sizeof(hCipher->aes_partial));
+                hCipher->aes_nc_off = 0;
+                mbedtls_aes_init(&hCipher->aes_context);
+                /* NOTE: From the mbedtls documentation:
+                 * Due to the nature of CTR you should use the same key schedule for
+                 * both encryption and decryption. So a context initialized with
+                 * mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
+                 */
+                mbedtls_result = mbedtls_aes_setkey_enc(&hCipher->aes_context, key->ptr, aesKeySize);
+                hCipher->aes_iv = iv->ptr;
+                break;
+            }
+            default:
+                // mbedtls_result is still 1, this means the function returns Invalid Parameter
+                break;
+        }
+
+        if (mbedtls_result == 0)
+        {
+            result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
+        }
+    }
+
+    return result;
+}
+
+arm_uc_error_t ARM_UC_cryptoDecryptUpdate(arm_uc_cipherHandle_t* hCipher, const uint8_t* input_ptr, uint32_t input_size, arm_uc_buffer_t* output)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+    size_t data_size = input_size < output->size_max ? input_size : output->size_max;
+    output->size = 0;
+    int mbedtls_result = mbedtls_aes_crypt_ctr(
+        &hCipher->aes_context,
+        data_size,
+        &hCipher->aes_nc_off,
+        hCipher->aes_iv,
+        hCipher->aes_partial,
+        input_ptr,
+        output->ptr
+
+    );
+    if (mbedtls_result == 0)
+    {
+        result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
+        output->size = data_size;
+    }
+    return result;
+}
+
+arm_uc_error_t ARM_UC_cryptoDecryptFinish(arm_uc_cipherHandle_t* hCipher, arm_uc_buffer_t* output)
+{
+    (void) output;
+    return (arm_uc_error_t){ARM_UC_CU_ERR_NONE};
+}
+
+arm_uc_error_t ARM_UC_cryptoHMACSHA256(arm_uc_buffer_t* key,
+                                       arm_uc_buffer_t* input,
+                                       arm_uc_buffer_t* output)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+
+    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
+    if (md_info != NULL)
+    {
+        int8_t rv = mbedtls_md_hmac(md_info,
+                                    key->ptr, key->size,
+                                    input->ptr, input->size,
+                                    output->ptr);
+        if (rv == 0)
+        {
+            output->size = ARM_UC_SHA256_SIZE;
+            result = (arm_uc_error_t){ ARM_UC_CU_ERR_NONE };
+        }
+    }
+
+    return result;
+}
+
+#endif
+
+arm_uc_error_t ARM_UC_getDeviceKey256Bit(arm_uc_buffer_t* output)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ARM_UC_CU_ERR_INVALID_PARAMETER };
+
+    if (output->size_max >= ARM_UC_DEVICE_KEY_SIZE)
+    {
+        int8_t rv = mbed_cloud_client_get_rot_128bit(output->ptr, output->size_max);
+        if (rv == 0)
+        {
+            arm_uc_buffer_t input = {
+                .size_max = ARM_UC_DEVICE_HMAC_KEY_SIZE,
+                .size = ARM_UC_DEVICE_HMAC_KEY_SIZE,
+                .ptr = (uint8_t *) &ARM_UC_DEVICE_HMAC_KEY
+            };
+            output->size = ARM_UC_ROT_SIZE;
+#if defined(PAL_DEVICE_KEY_DERIVATION_BACKWARD_COMPATIBILITY_CALC) && \
+    (PAL_DEVICE_KEY_DERIVATION_BACKWARD_COMPATIBILITY_CALC == 1)
+            result = ARM_UC_cryptoHMACSHA256(&input, output, output);
+#else
+            result = ARM_UC_cryptoHMACSHA256(output, &input, output);
+#endif
+        }
+    }
+
+    if (result.code != ARM_UC_CU_ERR_NONE)
+    {
+        /* clear buffer on failure so we don't leak the rot */
+        memset(output->ptr, 0, output->size_max);
+    }
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_error.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,32 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-common/arm_uc_error.h"
+
+const char* ARM_UC_err2Str(arm_uc_error_t err)
+{
+    switch (err.code) {
+        #define ENUM_AUTO(name) case name: return #name;
+        #define ENUM_FIXED(name, val) ENUM_AUTO(name)
+        ARM_UC_ERR_LIST
+        #undef ENUM_FIXED
+        #undef ENUM_AUTO
+    default:
+        return "Unknown Error Code";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_metadata_header_v2.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,259 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-common/arm_uc_metadata_header_v2.h"
+
+#include "update-client-common/arm_uc_utilities.h"
+#include "update-client-common/arm_uc_crypto.h"
+
+arm_uc_error_t arm_uc_parse_internal_header_v2(const uint8_t* input,
+                                               arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (input && details)
+    {
+        /* calculate CRC */
+        uint32_t calculatedChecksum = arm_uc_crc32(input, ARM_UC_INTERNAL_HEADER_CRC_OFFSET_V2);
+
+        /* read out CRC */
+        uint32_t temp32 = arm_uc_parse_uint32(&input[ARM_UC_INTERNAL_HEADER_CRC_OFFSET_V2]);
+
+        if (temp32 == calculatedChecksum)
+        {
+            /* parse content */
+            details->version = arm_uc_parse_uint64(&input[ARM_UC_INTERNAL_FIRMWARE_VERSION_OFFSET_V2]);
+            details->size = arm_uc_parse_uint64(&input[ARM_UC_INTERNAL_FIRMWARE_SIZE_OFFSET_V2]);
+
+            memcpy(details->hash,
+                   &input[ARM_UC_INTERNAL_FIRMWARE_HASH_OFFSET_V2],
+                   ARM_UC_SHA256_SIZE);
+
+            memcpy(details->campaign,
+                   &input[ARM_UC_INTERNAL_CAMPAIGN_OFFSET_V2],
+                   ARM_UC_GUID_SIZE);
+
+            /* set result */
+            result.code = ERR_NONE;
+        }
+    }
+
+    return result;
+}
+
+arm_uc_error_t arm_uc_create_internal_header_v2(const arm_uc_firmware_details_t* input,
+                                                arm_uc_buffer_t* output)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (input &&
+        output &&
+        (output->size_max >= ARM_UC_INTERNAL_HEADER_SIZE_V2))
+    {
+        /* zero buffer */
+        memset(output->ptr, 0, ARM_UC_INTERNAL_HEADER_SIZE_V2);
+
+        /* MSB encode header magic and version */
+        arm_uc_write_uint32(&output->ptr[0],
+                            ARM_UC_INTERNAL_HEADER_MAGIC_V2);
+        arm_uc_write_uint32(&output->ptr[4],
+                            ARM_UC_INTERNAL_HEADER_VERSION_V2);
+
+        /* MSB encode firmware version */
+        arm_uc_write_uint64(&output->ptr[ARM_UC_INTERNAL_FIRMWARE_VERSION_OFFSET_V2],
+                            input->version);
+
+        /* MSB encode firmware size to header */
+        arm_uc_write_uint64(&output->ptr[ARM_UC_INTERNAL_FIRMWARE_SIZE_OFFSET_V2],
+                            input->size);
+
+        /* raw copy firmware hash to header */
+        memcpy(&output->ptr[ARM_UC_INTERNAL_FIRMWARE_HASH_OFFSET_V2],
+               input->hash,
+               ARM_UC_SHA256_SIZE);
+
+        /* raw copy campaign ID to header */
+        memcpy(&output->ptr[ARM_UC_INTERNAL_CAMPAIGN_OFFSET_V2],
+               input->campaign,
+               ARM_UC_GUID_SIZE);
+
+        /* calculate CRC */
+        uint32_t checksum = arm_uc_crc32(output->ptr,
+                                         ARM_UC_INTERNAL_HEADER_CRC_OFFSET_V2);
+
+        /* MSB encode checksum to header */
+        arm_uc_write_uint32(&output->ptr[ARM_UC_INTERNAL_HEADER_CRC_OFFSET_V2],
+                            checksum);
+
+        /* set output size */
+        output->size = ARM_UC_INTERNAL_HEADER_SIZE_V2;
+
+        /* set error code */
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+arm_uc_error_t arm_uc_parse_external_header_v2(const uint8_t* input,
+                                               arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (input && details)
+    {
+
+        /* read 128 bit root-of-trust */
+        uint8_t key_buf[ARM_UC_DEVICE_KEY_SIZE] = { 0 };
+        arm_uc_buffer_t key = {
+            .size_max = ARM_UC_DEVICE_KEY_SIZE,
+            .size = 0,
+            .ptr = key_buf
+        };
+        arm_uc_error_t status = ARM_UC_getDeviceKey256Bit(&key);
+
+        if (status.error == ERR_NONE)
+        {
+            arm_uc_buffer_t input_buf = {
+                .size_max = ARM_UC_EXTERNAL_HMAC_OFFSET_V2,
+                .size = ARM_UC_EXTERNAL_HMAC_OFFSET_V2,
+                .ptr = (uint8_t *) input
+            };
+            arm_uc_hash_t hmac = { 0 };
+            arm_uc_buffer_t output_buf = {
+                .size_max = sizeof(arm_uc_hash_t),
+                .size = sizeof(arm_uc_hash_t),
+                .ptr = (uint8_t *) &hmac
+            };
+
+            /* calculate header HMAC */
+            status = ARM_UC_cryptoHMACSHA256(&key, &input_buf, &output_buf);
+
+            if (status.error == ERR_NONE)
+            {
+                input_buf.size_max = sizeof(arm_uc_hash_t);
+                input_buf.size = sizeof(arm_uc_hash_t);
+                input_buf.ptr = (uint8_t *) &input[ARM_UC_EXTERNAL_HMAC_OFFSET_V2];
+
+                int diff = ARM_UC_BinCompareCT(&input_buf, &output_buf);
+
+                if (diff == 0)
+                {
+                    details->version = arm_uc_parse_uint64(&input[ARM_UC_EXTERNAL_FIRMWARE_VERSION_OFFSET_V2]);
+                    details->size = arm_uc_parse_uint64(&input[ARM_UC_EXTERNAL_FIRMWARE_SIZE_OFFSET_V2]);
+
+                    memcpy(details->hash,
+                           &input[ARM_UC_EXTERNAL_FIRMWARE_HASH_OFFSET_V2],
+                           ARM_UC_SHA256_SIZE);
+
+                    memcpy(details->campaign,
+                           &input[ARM_UC_EXTERNAL_CAMPAIGN_OFFSET_V2],
+                           ARM_UC_GUID_SIZE);
+
+                    details->signatureSize = 0;
+
+                    result.code = ERR_NONE;
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+arm_uc_error_t arm_uc_create_external_header_v2(const arm_uc_firmware_details_t* input,
+                                                arm_uc_buffer_t* output)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (input &&
+        output &&
+        (output->size_max >= ARM_UC_EXTERNAL_HEADER_SIZE_V2))
+    {
+        /* zero buffer and reset size*/
+        memset(output->ptr, 0, ARM_UC_EXTERNAL_HEADER_SIZE_V2);
+        output->size = 0;
+
+        /* MSB encode header magic and version */
+        arm_uc_write_uint32(&output->ptr[0],
+                            ARM_UC_EXTERNAL_HEADER_MAGIC_V2);
+        arm_uc_write_uint32(&output->ptr[4],
+                            ARM_UC_EXTERNAL_HEADER_VERSION_V2);
+
+        /* MSB encode firmware version */
+        arm_uc_write_uint64(&output->ptr[ARM_UC_EXTERNAL_FIRMWARE_VERSION_OFFSET_V2],
+                            input->version);
+
+        /* MSB encode firmware size to header */
+        arm_uc_write_uint64(&output->ptr[ARM_UC_EXTERNAL_FIRMWARE_SIZE_OFFSET_V2],
+                            input->size);
+
+        /* raw copy firmware hash to header */
+        memcpy(&output->ptr[ARM_UC_EXTERNAL_FIRMWARE_HASH_OFFSET_V2],
+               input->hash,
+               ARM_UC_SHA256_SIZE);
+
+        /* MSB encode payload size to header */
+        arm_uc_write_uint64(&output->ptr[ARM_UC_EXTERNAL_PAYLOAD_SIZE_OFFSET_V2],
+                            input->size);
+
+        /* raw copy payload hash to header */
+        memcpy(&output->ptr[ARM_UC_EXTERNAL_PAYLOAD_HASH_OFFSET_V2],
+               input->hash,
+               ARM_UC_SHA256_SIZE);
+
+        /* raw copy campaign ID to header */
+        memcpy(&output->ptr[ARM_UC_EXTERNAL_CAMPAIGN_OFFSET_V2],
+               input->campaign,
+               ARM_UC_GUID_SIZE);
+
+        /* read 256 bit device key */
+        uint8_t key_buf[ARM_UC_DEVICE_KEY_SIZE] = { 0 };
+        arm_uc_buffer_t key = {
+            .size_max = ARM_UC_DEVICE_KEY_SIZE,
+            .size = 0,
+            .ptr = key_buf
+        };
+
+        arm_uc_error_t status = ARM_UC_getDeviceKey256Bit(&key);
+
+        if (status.error == ERR_NONE)
+        {
+            arm_uc_buffer_t input_buf = {
+                .size_max = ARM_UC_EXTERNAL_HMAC_OFFSET_V2,
+                .size = ARM_UC_EXTERNAL_HMAC_OFFSET_V2,
+                .ptr = output->ptr
+            };
+            arm_uc_buffer_t output_buf = {
+                .size_max = sizeof(arm_uc_hash_t),
+                .size = sizeof(arm_uc_hash_t),
+                .ptr = &output->ptr[ARM_UC_EXTERNAL_HMAC_OFFSET_V2]
+            };
+
+            /* calculate header HMAC */
+            result = ARM_UC_cryptoHMACSHA256(&key, &input_buf, &output_buf);
+            if (result.error == ERR_NONE)
+            {
+                /* set output size */
+                output->size = ARM_UC_EXTERNAL_HEADER_SIZE_V2;
+            }
+        }
+    }
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_scheduler.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,388 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-common/arm_uc_config.h"
+#include "update-client-common/arm_uc_scheduler.h"
+#include "update-client-common/arm_uc_trace.h"
+#include "update-client-common/arm_uc_error.h"
+
+#include "atomic-queue/atomic-queue.h"
+
+static struct atomic_queue arm_uc_queue = { 0 };
+static void (*arm_uc_notificationHandler)(void) = NULL;
+static volatile int32_t arm_uc_queue_counter = 0;
+
+int32_t ARM_UC_SchedulerGetQueuedCount(void) {
+    return arm_uc_queue_counter;
+}
+
+#if ARM_UC_SCHEDULER_STORAGE_POOL_SIZE
+/* Define the scheduler's callback pool storage.
+ * The scheduler will allocate out of this pool whenever it encounters a
+ * callback that is already locked or a callback that is NULL.
+ */
+static arm_uc_callback_t callback_pool_storage[ARM_UC_SCHEDULER_STORAGE_POOL_SIZE];
+static arm_uc_callback_t* callback_pool_root;
+#endif
+
+static void (*scheduler_error_cb)(uint32_t parameter);
+static arm_uc_callback_t callback_pool_exhausted_error_callback = {0};
+static arm_uc_callback_t callback_failed_take_error_callback = {0};
+
+#define POOL_WATERMARK 0xABABABAB
+
+void ARM_UC_SchedulerInit(void)
+{
+#if ARM_UC_SCHEDULER_STORAGE_POOL_SIZE
+    /* Initialize the storage pool */
+    callback_pool_root = callback_pool_storage;
+    for (size_t i = 0; i < ARM_UC_SCHEDULER_STORAGE_POOL_SIZE-1; i++)
+    {
+        callback_pool_storage[i].next = &callback_pool_storage[i+1];
+        /* watermark pool elements by setting the lock to POOL_WATERMARK.
+         * This allows checking of the maximum number of concurrent allocations.
+         */
+        callback_pool_storage[i].lock = POOL_WATERMARK;
+    }
+    callback_pool_storage[ARM_UC_SCHEDULER_STORAGE_POOL_SIZE-1].next = NULL;
+    callback_pool_storage[ARM_UC_SCHEDULER_STORAGE_POOL_SIZE-1].lock = POOL_WATERMARK;
+#endif
+    memset(&callback_pool_exhausted_error_callback, 0, sizeof(arm_uc_callback_t));
+    memset(&callback_failed_take_error_callback, 0, sizeof(arm_uc_callback_t));
+}
+
+/**
+ * @brief Allocate a block from the pool
+ * @details Gets a non-null block from the callback pool.
+ * 
+ * Theory of operation:
+ * * callback_pool_alloc starts by fetching the current value of the pool's
+ *   root. This value should be the next free item in the pool. 
+ * * If the value is NULL, then there are no elements left in the pool, so 
+ *   callback_pool_alloc returns NULL.
+ * * callback_pool_alloc tries to take this element by replacing the root
+ *   node with the following element. If replacement fails, callback_pool_alloc
+ *   tries the whole process again. This is repeated until allocation succeeds
+ *   or the root pointer is NULL.
+ * 
+ * @retval NULL the no element was available to allocate
+ * @retval non-NULL An allocated element
+ */
+static arm_uc_callback_t* callback_pool_alloc()
+{
+    while (true) {
+        arm_uc_callback_t* prev_free = callback_pool_root;
+        if (NULL == prev_free){
+            return NULL;
+        }
+        arm_uc_callback_t* new_free = prev_free->next;
+        
+        if (aq_atomic_cas_uintptr((uintptr_t*)&callback_pool_root, (uintptr_t)prev_free, (uintptr_t)new_free)) {
+            return prev_free;
+        }
+    }
+}
+
+/**
+ * @brief Check if the pool owns a block 
+ * @detail callback_pool_owns() checks whether the pointer supplied exists
+ * within the callback_pool_storage array. If it does, that means that the pool
+ * should own the block.
+ * 
+ * @param[in] e the element to evaluate for pool ownership
+ * 
+ * @retval 1 the pool owns the callback
+ * @retval 0 the pool does not own the callback
+ */
+
+static int callback_pool_owns(arm_uc_callback_t* e)
+{
+    int isGreater = e >= callback_pool_storage;
+    int isLesser = (uintptr_t)e < ((uintptr_t)callback_pool_storage + sizeof(callback_pool_storage));
+    return isGreater && isLesser;
+}
+
+/**
+ * @brief Free a block owned by the pool.
+ * @details Checks whether the supplied callback is owned by the pool and frees
+ * it if so. Performs no operation for a callback that is not owned by the pool.
+ * 
+ * @param[in] e the element to free
+ */
+static void callback_pool_free(arm_uc_callback_t* e)
+{
+    UC_COMM_TRACE("%s (%p)", __PRETTY_FUNCTION__, e);
+    if (callback_pool_owns(e)) {
+        while (true) {
+            arm_uc_callback_t* prev_free = callback_pool_root;
+
+            e->next = prev_free;
+            UC_COMM_TRACE("%s inserting r:%p p:%p, e:%p, ", __PRETTY_FUNCTION__, callback_pool_root, prev_free, e);
+            if (aq_atomic_cas_uintptr((uintptr_t*)&callback_pool_root, (uintptr_t)prev_free, (uintptr_t)e)) {
+                break;
+            }
+            UC_COMM_TRACE("%s inserting failed", __PRETTY_FUNCTION__);
+        }
+    } 
+}
+
+uint32_t ARM_UC_SchedulerGetHighWatermark(void)
+{
+    uint32_t i;
+    for (i = 0; i < ARM_UC_SCHEDULER_STORAGE_POOL_SIZE; i++)
+    {
+        if (callback_pool_storage[i].lock == POOL_WATERMARK) {
+            break;
+        }
+    }
+    return i;
+}
+
+
+void ARM_UC_AddNotificationHandler(void (*handler)(void))
+{
+    arm_uc_notificationHandler = handler;
+}
+
+void ARM_UC_SetSchedulerErrorHandler(void(*handler)(uint32_t))
+{
+    scheduler_error_cb = handler;
+}
+
+bool ARM_UC_PostCallback(arm_uc_callback_t* _storage,
+                         void (*_callback)(uint32_t),
+                         uint32_t _parameter)
+{
+    bool success = true;
+    UC_COMM_TRACE("%s Scheduling %p(%lu) with %p", __PRETTY_FUNCTION__, _callback, _parameter, _storage);
+
+    if (_callback == NULL)
+    {
+        return false;
+    }
+
+    if (_storage)
+    {
+        int result = aq_element_take((void *) _storage);
+        if (result != ATOMIC_QUEUE_SUCCESS)
+        {
+
+// NOTE: This may be useful for detecting double-allocation of callbacks on mbed-os too
+#if defined(TARGET_IS_PC_LINUX)
+            /* On Linux, issue an error message if the callback was not added
+               to the queue. This is dangerous in mbed-os, since writing to the
+               console from an interrupt context might crash the program. */
+                UC_COMM_TRACE("ARM_UC_PostCallback failed to acquire lock on: %p %p; allocating a temporary callback",
+                                _storage,
+                                _callback);
+
+#endif
+            _storage = NULL;
+        }
+    }
+    if (_storage == NULL)
+    {
+        _storage = callback_pool_alloc();
+        if (_storage == NULL)
+        {
+            success = false;
+            /* Handle a failed alloc */
+
+#ifdef TARGET_IS_PC_LINUX
+            /* On Linux, issue an error message if the callback was not added
+               to the queue. This is dangerous in mbed-os, since writing to the
+               console from an interrupt context might crash the program. */
+            UC_COMM_ERR_MSG("Failed to allocate a callback block");
+#endif
+            if (scheduler_error_cb)
+            {
+                _storage = &callback_pool_exhausted_error_callback;
+                int result = aq_element_take((void *) _storage);
+                if (result == ATOMIC_QUEUE_SUCCESS) {
+                    _parameter = ARM_UC_EQ_ERR_POOL_EXHAUSTED;
+                    _callback = scheduler_error_cb;
+                }
+                else 
+                {
+                    _storage = NULL;
+                }
+            }
+        }
+        else
+        {
+            /* This thread is guaranteed to exclusively own _storage here */
+            aq_initialize_element((void*) _storage);
+            int result = aq_element_take((void*) _storage);
+            if (result != ATOMIC_QUEUE_SUCCESS)
+            {
+                success = false;
+                /* This should be impossible */
+                UC_COMM_ERR_MSG("Failed to take an allocated a callback block... this should be impossible...");
+                if (scheduler_error_cb)
+                {
+                    _storage = &callback_failed_take_error_callback;
+                    int result = aq_element_take((void *) _storage);
+                    if (result == ATOMIC_QUEUE_SUCCESS) {
+                        _parameter = ARM_UC_EQ_ERR_FAILED_TAKE;
+                        _callback = scheduler_error_cb;
+                    }
+                    else
+                    {
+                        _storage = NULL;
+                    }
+                }
+            }
+        }
+    }
+    if (_storage)
+    {
+        /* populate callback struct */
+        _storage->callback = _callback;
+        _storage->parameter = _parameter;
+
+        UC_COMM_TRACE("%s Queueing %p(%lu) in %p", __PRETTY_FUNCTION__, _callback, _parameter, _storage);
+
+        /* push struct to atomic queue */
+        int result = aq_push_tail(&arm_uc_queue, (void *) _storage);
+
+        if (result == ATOMIC_QUEUE_SUCCESS)
+        {
+            UC_COMM_TRACE("%s Scheduling success!", __PRETTY_FUNCTION__);
+
+            /*  The queue is processed by removing an element first and then
+                decrementing the queue counter. This continues until the counter
+                reaches 0 (process single callback) or the queue is empty
+                (process queue).
+
+                If the counter is greater than zero at this point, there should
+                already be a notification in progress, so no new notification
+                is required.
+
+                If the counter is zero at this point, there is one element in
+                the queue, and incrementing the counter will return 1 and which
+                triggers a notification.
+
+                Because the scheduler could run at any time and consume queue
+                elements, it's possible for the scheduler to remove the queue
+                element before the counter is incremented.
+
+                Therefore, If the queue is empty at this point, the counter is
+                -1 and incrementing the counter will return 0. This does not
+                trigger a notification, which is correct since the queue is 
+                empty.
+            */
+            int32_t count = aq_atomic_inc_int32((int32_t*) &arm_uc_queue_counter, 1);
+
+            /* if notification handler is set, check if this is the first
+            insertion
+            */
+            if ((arm_uc_notificationHandler) && (count == 1))
+            {
+                UC_COMM_TRACE("%s Invoking notify!", __PRETTY_FUNCTION__);
+
+                /* disable: UC_COMM_TRACE("notify nanostack scheduler"); */
+                arm_uc_notificationHandler();
+            }
+        }
+        else
+        {
+            success = false;
+        }
+    }
+
+    return success;
+}
+
+void ARM_UC_ProcessQueue(void)
+{
+    arm_uc_callback_t* element = (arm_uc_callback_t*) aq_pop_head(&arm_uc_queue);
+
+    while (element != NULL)
+    {
+        UC_COMM_TRACE("%s Invoking %p(%lu)", __PRETTY_FUNCTION__, element->callback, element->parameter);
+        /* Store the callback locally */
+        void (*callback)(uint32_t) = element->callback;
+        /* Store the parameter locally */
+        uint32_t parameter = element->parameter;
+        /* Release the lock on the element */
+        UC_COMM_TRACE("%s Releasing %p", __PRETTY_FUNCTION__, element);
+        aq_element_release((void*) element);
+        /* Free the element if it was pool allocated */
+        UC_COMM_TRACE("%s Freeing %p", __PRETTY_FUNCTION__, element);
+        callback_pool_free((void*) element);
+
+        /* execute callback */
+        callback(parameter);
+
+        /*  decrement element counter after executing the callback.
+            otherwise further callbacks posted inside this callback could
+            trigger notifications eventhough we are still processing the queue.
+        */
+        int32_t count = aq_atomic_inc_int32((int32_t*) &arm_uc_queue_counter, -1);
+
+        if (count > 0) {
+            /* get next element */
+            element = (arm_uc_callback_t*) aq_pop_head(&arm_uc_queue);
+        }
+        else {
+            element = NULL;
+        }
+    }
+}
+
+bool ARM_UC_ProcessSingleCallback(void)
+{
+    /* elements in queue */
+    int32_t count = 0;
+
+    /* get first element */
+    arm_uc_callback_t* element = (arm_uc_callback_t*) aq_pop_head(&arm_uc_queue);
+
+    if (element != NULL)
+    {
+        UC_COMM_TRACE("%s Invoking %p(%lu)", __PRETTY_FUNCTION__, element->callback, element->parameter);
+        /* Store the callback locally */
+        void (*callback)(uint32_t) = element->callback;
+        /* Store the parameter locally */
+        uint32_t parameter = element->parameter;
+        /* Release the lock on the element */
+        UC_COMM_TRACE("%s Releasing %p", __PRETTY_FUNCTION__, element);
+        aq_element_release((void*) element);
+        /* Free the element if it was pool allocated */
+        UC_COMM_TRACE("%s Freeing %p", __PRETTY_FUNCTION__, element);
+        callback_pool_free((void*) element);
+
+        /* execute callback */
+        callback(parameter);
+
+        UC_COMM_TRACE("%s Decrementing callback counter", __PRETTY_FUNCTION__);
+
+        /*  decrement element counter after executing the callback.
+            otherwise further callbacks posted inside this callback could
+            trigger notifications eventhough we are still processing the queue.
+
+            when this function returns false, the counter is 0 and there are
+            either 1 or 0 elements in the queue. if there is 1 element in
+            the queue, it means the counter hasn't been incremented yet, and
+            incrmenting it will return 1, which will trigger a notification.
+        */
+        count = aq_atomic_inc_int32((int32_t*) &arm_uc_queue_counter, -1);
+    }
+
+    return (count > 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_test_rot.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,57 @@
+// ----------------------------------------------------------------------------
+// Copyright 2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(ARM_UC_TEST_DUMMY_ROT) && ARM_UC_TEST_DUMMY_ROT == 1
+
+#include <inttypes.h>
+#include <stddef.h>
+
+#define DEVICE_KEY_SIZE_IN_BYTES (128/8)
+
+/**
+ * @brief Function to get the device root of trust
+ * @details The device root of trust should be a 128 bit value. It should never leave the device.
+ *          It should be unique to the device. It should have enough entropy to avoid contentional
+ *          entropy attacks. The porter should implement the following device signature to provide
+ *          device root of trust on different platforms.
+ *
+ * @param key_buf buffer to be filled with the device root of trust.
+ * @param length  length of the buffer provided to make sure no overflow occurs.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+
+// THIS CODE IS FOR TESTING PURPOSES ONLY. DO NOT USE IN PRODUCTION ENVIRONMENTS. REPLACE WITH A PROPER IMPLEMENTATION BEFORE USE
+int8_t mbed_cloud_client_get_rot_128bit(uint8_t *key_buf, uint32_t length)
+{
+#warning "You are using insecure Root Of Trust implementation, DO NOT USE IN PRODUCTION ENVIRONMENTS. REPLACE WITH A PROPER IMPLEMENTATION BEFORE USE"
+
+    if (length < DEVICE_KEY_SIZE_IN_BYTES || key_buf == NULL)
+    {
+        return -1;
+    }
+
+    for (uint8_t i = 0; i < DEVICE_KEY_SIZE_IN_BYTES; i++)
+    {
+        key_buf[i] = i;
+    }
+
+    return 0;
+}
+
+#endif // #if !defined(ARM_UC_TEST_DUMMY_ROT) || ARM_UC_TEST_DUMMY_ROT == 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/source/arm_uc_utilities.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,554 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-common/arm_uc_utilities.h"
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* lookup table for printing hexadecimal values */
+const uint8_t arm_uc_hex_table[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
+                                      '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+/**
+ * @brief Parse a uri string to populate a arm_uc_uri_t struct
+ * @detail Format of uri scheme:[//]host[:port]/path
+ *         [] means optional, path will always start with a '/'
+ *
+ * @param str Pointer to string containing URI.
+ * @param size String length.
+ * @param uri The arm_uc_uri_t struct to be populated
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_str2uri(const uint8_t* buffer,
+                              uint32_t buffer_size,
+                              arm_uc_uri_t* uri)
+{
+    arm_uc_error_t result = (arm_uc_error_t){ ERR_INVALID_PARAMETER };
+
+    if (buffer &&
+        uri &&
+        uri->ptr &&
+        (buffer_size < uri->size_max))
+    {
+        const uint8_t* str = buffer;
+        uint8_t* colon = NULL;
+        uint8_t* slash = NULL;
+        uint32_t len = 0;
+
+        /* find scheme by searching for first colon */
+        colon = memchr(str, ':', buffer_size);
+        len = colon - str;
+
+        if (len < uri->size_max)
+        {
+            /* copy scheme to temporary uri buffer and convert to lower case.
+            */
+            for (uint32_t index = 0; index < len; index++)
+            {
+                /* lower case characters have higher ASCII value */
+                if (str[index] < 'a')
+                {
+                    uri->ptr[index] = str[index] + ('a' - 'A');
+                }
+                else
+                {
+                    uri->ptr[index] = str[index];
+                }
+            }
+
+            /* copy ':' */
+            uri->ptr[len] = str[len];
+
+            /* convert scheme string to scheme type */
+            if (memcmp(uri->ptr, "http:", 5) == 0)
+            {
+                uri->scheme = URI_SCHEME_HTTP;
+
+                /* set default port based on scheme - can be overwritten */
+                uri->port   = 80;
+            }
+            else
+            {
+                uri->scheme = URI_SCHEME_NONE;
+            }
+
+            /* only continue if scheme is supported */
+            if (uri->scheme != URI_SCHEME_NONE)
+            {
+                /* strip any leading '/' */
+                str = colon + 1;
+                for (str += 1;
+                     (str[0] == '/') && (str < (buffer + buffer_size));
+                     ++str);
+
+                /* find separation between host and path */
+                slash = memchr(str, '/', buffer_size - (str - buffer));
+
+                if (slash != NULL)
+                {
+                    bool parsed = true;
+
+                    /* find optional port */
+                    colon = memchr(str, ':', buffer_size - (slash - buffer));
+
+                    if (colon != NULL)
+                    {
+                        uri->port = arm_uc_str2uint32(colon + 1,
+                                                      buffer_size - (colon - buffer),
+                                                      &parsed);
+                        len = colon - str;
+                    }
+                    else
+                    {
+                        len = slash - str;
+                    }
+
+                    /* check */
+                    if ((parsed == 1) && (len < uri->size_max))
+                    {
+                        /* copy host name to URI buffer */
+                        memcpy(uri->ptr, str, len);
+
+                        /* \0 terminate string */
+                        uri->ptr[len] = '\0';
+
+                        /* update length */
+                        uri->size = len + 1;
+
+                        /* set host pointer */
+                        uri->host = (char*) uri->ptr;
+
+                        /* find remaining path length */
+                        str = slash;
+                        len = arm_uc_strnlen(str, buffer_size - (str - buffer));
+
+                        /* check */
+                        if ((len > 0) && (len < (uri->size_max - uri->size)))
+                        {
+                            /* copy path to URI buffer */
+                            memcpy(&uri->ptr[uri->size], str, len);
+
+                            /* set path pointer */
+                            uri->path = (char*) &uri->ptr[uri->size];
+
+                            /* \0 terminate string */
+                            uri->ptr[uri->size + len] = '\0';
+
+                            /* update length after path pointer is set */
+                            uri->size += len + 1;
+
+                            /* parsing passed all checks */
+                            result = (arm_uc_error_t){ ERR_NONE };
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Find substring inside string.
+ * @details The size of both string and substring is explicitly passed so no
+ *          assumptions are made about NULL termination.
+ *
+ * @param big_buffer Pointer to the string to be searched.
+ * @param big_length Length of the string to be searched.
+ * @param little_buffer Pointer to the substring being searched for.
+ * @param little_length Length of the substring being searched for.
+ * @return Index to where the substring was found inside the string. If the
+ *         string doesn't contain the subtring, UINT32_MAX is returned.
+ */
+ uint32_t arm_uc_strnstrn(const uint8_t* big_buffer,
+                          uint32_t big_length,
+                          const uint8_t* little_buffer,
+                          uint32_t little_length)
+{
+    uint32_t result = UINT32_MAX;
+
+    /* Sanity check. Pointers are not NULL. The little buffer is smaller than
+       the big buffer. The little buffer is not empty.
+    */
+    if (big_buffer &&
+        little_buffer &&
+        (big_length >= little_length) &&
+        (little_length > 0))
+    {
+        uint8_t little_hash = 0;
+        uint8_t big_hash = 0;
+        uint32_t little_length_m1 = little_length - 1;
+
+        /* Prepare hashes. The last byte for the big hash is added in the
+           comparison loop.
+        */
+        for (uint32_t index = 0; index < little_length_m1; index++)
+        {
+            little_hash ^= little_buffer[index];
+            big_hash ^= big_buffer[index];
+        }
+
+        /* Add the last byte for the little hash. */
+        little_hash ^= little_buffer[little_length_m1];
+
+        /* Comparison loop. In each loop the big hash is updated and compared
+           to the little hash. If the hash matches, a more thorough byte-wise
+           comparison is performed. The complexity of the hash determines how
+           often a collision occures and how often a full comparison is done.
+        */
+        for (uint32_t index = 0;
+             index < (big_length - (little_length_m1));
+             index++)
+        {
+            /* update hash */
+            big_hash ^= big_buffer[index + (little_length_m1)];
+
+            /* cursory check */
+            if (little_hash == big_hash)
+            {
+                /* hash checks out do comprehensive check */
+                uint32_t checks = 0;
+
+                for ( ; checks < little_length; checks++)
+                {
+                    /* stop counting if bytes differ */
+                    if (big_buffer[index + checks] != little_buffer[checks])
+                    {
+                        break;
+                    }
+                }
+
+                /* check if all bytes matched */
+                if (checks == little_length)
+                {
+                    /* save pointer and break loop */
+                    result = index;
+                    break;
+                }
+            }
+
+            /* update hash - remove tail */
+            big_hash ^= big_buffer[index];
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Find string length.
+ * @details Custom implementation of strnlen which is a GNU extension.
+ *          Returns either the string length or max_length.
+ *
+ * @param buffer Pointer to string.
+ * @param max_length Maximum buffer length.
+ *
+ * @return String length or max_length.
+ */
+uint32_t arm_uc_strnlen(const uint8_t* buffer, uint32_t max_length)
+{
+    uint32_t length = 0;
+
+    for ( ; length < max_length; length++)
+    {
+        if (buffer[length] == '\0')
+        {
+            break;
+        }
+    }
+
+    return length;
+}
+
+/**
+ * @brief Convert string to unsigned 32 bit integer.
+ * @details Function tries to parse string as an unsigned 32 bit integer
+ *          and return the value. The function expects the first byte to be an
+ *          integer and will continue until:
+ *           1. the buffer is empty
+ *           2. the intermediate result is larger then UINT32_MAX
+ *           3. the next byte is not a number
+ *
+ *          If a valid 32 bit unsigned integer is found the third parameter is
+ *          set to true and the return value holds the parsed number. Otherwise,
+ *          the third parameter will be false and the return value will be 0.
+ *
+ * @param buffer Pointer to string.
+ * @param max_length Maximum buffer length.
+ * @param success Pointer to boolean indicating whether the parsing was successful.
+ * @return Parsed value. Only valid if success it true.
+ */
+uint32_t arm_uc_str2uint32(const uint8_t* buffer,
+                           uint32_t max_length,
+                           bool* success)
+{
+    uint64_t result = 0;
+    bool found = false;
+
+    /* default output and return status is 0 and false */
+    uint32_t output = 0;
+
+    if (success)
+    {
+        *success = false;
+    }
+
+    /* null pointer and length check */
+    if (buffer && (max_length > 0))
+    {
+        /* loop through string */
+        for (uint32_t index = 0; index < max_length; index++)
+        {
+            /* check if character is a number */
+            if (('0' <= buffer[index]) &&
+                (buffer[index] <= '9') &&
+                (result < UINT64_MAX))
+            {
+                /* shift one decimal position and append next digit */
+                result *= 10;
+                result += buffer[index] - '0';
+
+                /* found at least one integer, mark as found */
+                found = true;
+            }
+            else
+            {
+                /* character is not a number, stop loop */
+                break;
+            }
+        }
+
+        /* set output and return value only if a valid number was found */
+        if (found && (result <= UINT64_MAX))
+        {
+            output = result;
+
+            if (success)
+            {
+                *success = true;
+            }
+        }
+    }
+
+    return output;
+}
+
+uint32_t arm_uc_crc32(const uint8_t* buffer, uint32_t length)
+{
+    const uint8_t* current = buffer;
+    uint32_t crc = 0xFFFFFFFF;
+
+    while (length--)
+    {
+        crc ^= *current++;
+
+        for (uint32_t counter = 0; counter < 8; counter++)
+        {
+            if (crc & 1)
+            {
+                crc = (crc >> 1) ^ 0xEDB88320;
+            }
+            else
+            {
+                crc = crc >> 1;
+            }
+        }
+    }
+
+    return (crc ^ 0xFFFFFFFF);
+}
+
+uint32_t arm_uc_parse_uint32(const uint8_t* input)
+{
+    uint32_t result = 0;
+
+    if (input)
+    {
+        result = input[0];
+        result = (result << 8) | input[1];
+        result = (result << 8) | input[2];
+        result = (result << 8) | input[3];
+    }
+
+    return result;
+}
+
+uint64_t arm_uc_parse_uint64(const uint8_t* input)
+{
+    uint64_t result = 0;
+
+    if (input)
+    {
+        result = input[0];
+        result = (result << 8) | input[1];
+        result = (result << 8) | input[2];
+        result = (result << 8) | input[3];
+        result = (result << 8) | input[4];
+        result = (result << 8) | input[5];
+        result = (result << 8) | input[6];
+        result = (result << 8) | input[7];
+    }
+
+    return result;
+}
+
+void arm_uc_write_uint32(uint8_t* buffer, uint32_t value)
+{
+    if (buffer)
+    {
+        buffer[3] = value;
+        buffer[2] = (value >> 8);
+        buffer[1] = (value >> 16);
+        buffer[0] = (value >> 24);
+    }
+}
+
+void arm_uc_write_uint64(uint8_t* buffer, uint64_t value)
+{
+    if (buffer)
+    {
+        buffer[7] = value;
+        buffer[6] = (value >> 8);
+        buffer[5] = (value >> 16);
+        buffer[4] = (value >> 24);
+        buffer[3] = (value >> 32);
+        buffer[2] = (value >> 40);
+        buffer[1] = (value >> 48);
+        buffer[0] = (value >> 56);
+    }
+}
+
+// Constant time binary comparison
+uint32_t ARM_UC_BinCompareCT(const arm_uc_buffer_t* a, const arm_uc_buffer_t* b)
+{
+    uint32_t result;
+    uint32_t i;
+    const uint32_t *wa = (uint32_t *)a->ptr;
+    const uint32_t *wb = (uint32_t *)b->ptr;
+    const uint32_t bytes_aligned = a->size & ~((1 << sizeof(uint32_t)) - 1);
+    const uint32_t bytes = a->size;
+
+    // Check sizes
+    if (a->size != b->size)
+    {
+        return 1;
+    }
+    result = 0;
+    for (i = 0; i < bytes_aligned; i += sizeof(uint32_t))
+    {
+        const uint32_t idx = i/sizeof(uint32_t);
+        result = result | (wa[idx] ^ wb[idx]);
+    }
+    for (; i < bytes; i++)
+    {
+        result = result | (a->ptr[i] ^ b->ptr[i]);
+    }
+    // Reduce to 0 or 1 in constant time
+    return (result | -result) >> 31;
+}
+
+static const uint8_t base64EncodeArray[65] = {MBED_CLOUD_UPDATE_BASE64_CHARSET};
+
+uint8_t * ARM_UC_Base64Enc(uint8_t* buf, const uint32_t size, const arm_uc_buffer_t* bin)
+{
+    uint32_t partial = 0;
+    const uint8_t * lastPos = buf + size;
+    uint32_t i;
+    uint32_t pad2 = (bin->size - bin->size % 3);
+    uint32_t pad1 = (bin->size - bin->size % 3) + 1;
+    for (i = 0; i < bin->size && buf <= lastPos - 4; i+=3) {
+        partial = (bin->ptr[i] << 16);
+        if ( i < pad1 )
+        {
+            partial = partial | (bin->ptr[i+1] << 8);
+        }
+        if ( i < pad2)
+        {
+            partial = partial | (bin->ptr[i+2] << 0);
+        }
+        buf[0] = base64EncodeArray[(partial >> 18) & 0x3f];
+        buf[1] = base64EncodeArray[(partial >> 12) & 0x3f];
+        buf[2] = (i < pad1) ? base64EncodeArray[(partial >>  6) & 0x3f] : base64EncodeArray[64];
+        buf[3] = (i < pad2) ? base64EncodeArray[(partial >>  0) & 0x3f] : base64EncodeArray[64];
+        buf += 4;
+    }
+    buf[0] = 0;
+    return buf;
+}
+
+uint32_t ARM_UC_Base64DecodeChar(uint8_t c)
+{
+    if (c == MBED_CLOUD_UPDATE_BASE64_CHARSET[64] || c == MBED_CLOUD_UPDATE_BASE64_CHARSET[0])
+    {
+        return 0;
+    }
+    uint32_t idx = 0;
+    int32_t i;
+    for (i = 5; i >= 0; i--)
+    {
+        uint32_t tmpidx = idx | 1 << i;
+        uint8_t ct = MBED_CLOUD_UPDATE_BASE64_CHARSET[tmpidx];
+        if (c == ct)
+        {
+            return tmpidx;
+        }
+        else if (c > ct)
+        {
+            idx = tmpidx;
+        }
+    }
+    return (uint32_t) -1;
+}
+
+void ARM_UC_Base64Dec(arm_uc_buffer_t* bin, const uint32_t size, const uint8_t* buf)
+{
+    uintptr_t optr = (uintptr_t)bin->ptr;
+    const uint8_t*  iptr = buf;
+    while ((uintptr_t)iptr + 4 < (uintptr_t) buf + size && optr + 1 < (uintptr_t)bin->ptr + bin->size_max) {
+        uint8_t partial[3];
+        uint8_t a = (ARM_UC_Base64DecodeChar(iptr[0]));
+        uint8_t b = (ARM_UC_Base64DecodeChar(iptr[1]));
+        uint8_t c = (ARM_UC_Base64DecodeChar(iptr[2]));
+        uint8_t d = (ARM_UC_Base64DecodeChar(iptr[3]));
+        uint8_t l = 3;
+        if (d == MBED_CLOUD_UPDATE_BASE64_CHARSET[64])
+        {
+            l--;
+        }
+        if (c == MBED_CLOUD_UPDATE_BASE64_CHARSET[64])
+        {
+            l--;
+        }
+        partial[0] = ((a << 2) & 0xfc) | ((b >> 4) & 0x3);
+        partial[1] = ((b << 4) & 0xf0) | ((c >> 2) & 0xf);
+        partial[2] = ((c << 6) & 0xc0) | ((d >> 0) & 0x3f);
+        memcpy((void*)optr, partial, l);
+        iptr += 4;
+        optr += l;
+        if (d == MBED_CLOUD_UPDATE_BASE64_CHARSET[64])
+        {
+            break;
+        }
+    }
+    bin->size = optr - (uintptr_t)bin->ptr;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_common.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,31 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_COMMON_H
+#define ARM_UPDATE_COMMON_H
+
+#include "update-client-common/arm_uc_config.h"
+#include "update-client-common/arm_uc_crypto.h"
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_public.h"
+#include "update-client-common/arm_uc_scheduler.h"
+#include "update-client-common/arm_uc_trace.h"
+#include "update-client-common/arm_uc_types.h"
+#include "update-client-common/arm_uc_utilities.h"
+
+#endif // ARM_UPDATE_COMMON_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_config.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,72 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_CONFIG_H
+#define ARM_UPDATE_CONFIG_H
+
+#ifdef MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#include MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#endif
+
+#ifndef MAX_SOURCES
+#define MAX_SOURCES 10
+#endif
+
+#ifndef ARM_UC_SOCKET_MAX_RETRY
+#define ARM_UC_SOCKET_MAX_RETRY 3
+#endif
+
+/* Total memory allocated for download buffers.
+   For HTTP sources, this number cannot be below 1 KiB.
+*/
+#ifdef MBED_CLOUD_CLIENT_UPDATE_BUFFER
+#if MBED_CLOUD_CLIENT_UPDATE_BUFFER < 1024
+#error MBED_CLOUD_CLIENT_UPDATE_BUFFER must be 1024 bytes or more
+#else
+#define ARM_UC_BUFFER_SIZE MBED_CLOUD_CLIENT_UPDATE_BUFFER
+#endif
+#endif
+
+#ifndef ARM_UC_BUFFER_SIZE
+#define ARM_UC_BUFFER_SIZE 1024
+#endif
+
+#ifndef ARM_UC_USE_KCM
+#define ARM_UC_USE_KCM 1
+#define ARM_UPDATE_USE_KCM 1
+#endif
+
+#ifndef ARM_UC_USE_PAL_CRYPTO
+#define ARM_UC_USE_PAL_CRYPTO 1
+#endif
+
+#define MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX "mbed.UpdateAuthCert."
+#define MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT "mbed.UpdateAuthCert"
+#define MBED_CLOUD_SHA256_BYTES (256/8)
+#define MBED_CLOUD_BASE64_SIZE(X) (((X + 2)/3)*4)
+#define MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE (MBED_CLOUD_BASE64_SIZE(MBED_CLOUD_SHA256_BYTES) + sizeof(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX))
+
+
+// NOTE: The charset must be sorted except for the trailing character which is used as a padding character.
+#define MBED_CLOUD_UPDATE_BASE64_CHARSET "0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz-"
+
+#ifndef ARM_UC_SCHEDULER_STORAGE_POOL_SIZE
+#define ARM_UC_SCHEDULER_STORAGE_POOL_SIZE 32
+#endif
+
+#endif // ARM_UPDATE_CONFIG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_crypto.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,134 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_CRYPTO_H
+#define ARM_UPDATE_CRYPTO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "arm_uc_error.h"
+#include "arm_uc_types.h"
+#include "arm_uc_config.h"
+
+#ifndef ARM_UC_USE_PAL_CRYPTO
+#define ARM_UC_USE_PAL_CRYPTO 0
+#endif
+
+#if ARM_UC_USE_PAL_CRYPTO
+#include "pal.h"
+#ifndef palMDHandle_t
+#include "pal_Crypto.h"
+#endif
+
+typedef palMDHandle_t arm_uc_mdHandle_t;
+typedef palMDType_t arm_uc_mdType_t;
+typedef struct arm_uc_cipherHandle_t {
+    palAesHandle_t aes_context;
+    uint8_t* aes_iv;
+} arm_uc_cipherHandle_t;
+
+#define ARM_UC_CU_SHA256 PAL_SHA256
+
+#else // ARM_UC_USE_PAL_CRYPTO
+
+#include "mbedtls/md_internal.h"
+#include "mbedtls/sha256.h"
+#include "mbedtls/x509_crt.h"
+#include "mbedtls/aes.h"
+#include "mbedtls/cipher.h"
+typedef mbedtls_md_context_t arm_uc_mdHandle_t;
+typedef mbedtls_md_type_t arm_uc_mdType_t;
+typedef struct arm_uc_cipherHandle_t {
+    mbedtls_aes_context aes_context;
+    uint8_t  aes_partial[MBEDTLS_MAX_BLOCK_LENGTH];
+    uint8_t* aes_iv;
+    size_t   aes_nc_off;
+} arm_uc_cipherHandle_t;
+
+#define ARM_UC_CU_SHA256 MBEDTLS_MD_SHA256
+
+#endif // ARM_UC_USE_PAL_CRYPTO
+
+/**
+ * @brief Verify a public key signature
+ * @details This function loads a certificate out of `ca`, and validates `hash` using the certificate and `sig`. If the
+ *          certificate used by this function requires a certificate chain validation (i.e. it is not the root of trust,
+ *          or it has not been previously validated), certificate chain validation should be done prior to calling this
+ *          function.
+ *
+ * WARNING: this function is to be used only inside a function where its arguments have been error checked.
+ * WARNING: This is an internal utility function and is not accessible outside of the manifest manager.
+ *
+ * @param[in] ca A pointer to a buffer that contains the signing certificate.
+ * @param[in] hash A pointer to a buffer containing the hash to verify.
+ * @param[in] sig A pointer to a buffer containing a signature by `ca`
+ * @retval MFST_ERR_CERT_INVALID when the certificate fails to load
+ * @retval MFST_ERR_INVALID_SIGNATURE when signature verification fails
+ * @retval MFST_ERR_NONE for a valid signature
+ */
+arm_uc_error_t ARM_UC_verifyPkSignature(const arm_uc_buffer_t* ca, const arm_uc_buffer_t* hash, const arm_uc_buffer_t* sig);
+arm_uc_error_t ARM_UC_cryptoHashSetup(arm_uc_mdHandle_t* h, arm_uc_mdType_t mdType);
+arm_uc_error_t ARM_UC_cryptoHashUpdate(arm_uc_mdHandle_t* h, arm_uc_buffer_t* input);
+arm_uc_error_t ARM_UC_cryptoHashFinish(arm_uc_mdHandle_t* h, arm_uc_buffer_t* output);
+arm_uc_error_t ARM_UC_cryptoDecryptSetup(arm_uc_cipherHandle_t* h, arm_uc_buffer_t* key, arm_uc_buffer_t* iv, int32_t bits);
+arm_uc_error_t ARM_UC_cryptoDecryptUpdate(arm_uc_cipherHandle_t* h, const uint8_t* input_ptr, uint32_t input_size, arm_uc_buffer_t* output);
+arm_uc_error_t ARM_UC_cryptoDecryptFinish(arm_uc_cipherHandle_t* h, arm_uc_buffer_t* output);
+
+/**
+ * @brief Calculate HAMC-SHA256
+ *
+ * @param key    buffer struct containing the hmac key
+ * @param input  buffer struct containing the input data
+ * @param output buffer struct to cotain output HMAC, it is safe to use the same buffer
+ *               as input to save memory. The size member of the struct will be set on success.
+ *
+ * @return ARM_UC_CU_ERR_NONE on success, error code on failure.
+ */
+arm_uc_error_t ARM_UC_cryptoHMACSHA256(arm_uc_buffer_t* key, arm_uc_buffer_t* input, arm_uc_buffer_t* output);
+
+/**
+ * @brief Get a 256 device key.
+ *
+ * @param output buffer struct to cotain output device key.
+                 The size member of the struct will be set on success.
+ *
+ * @return ARM_UC_CU_ERR_NONE on success, error code on failure.
+ */
+arm_uc_error_t ARM_UC_getDeviceKey256Bit(arm_uc_buffer_t* output);
+
+/**
+ * @brief Function to get the device root of trust
+ * @details The device root of trust should be a 128 bit value. It should never leave the device.
+ *          It should be unique to the device. It should have enough entropy to avoid contentional
+ *          entropy attacks. The porter should implement the following device signature to provide
+ *          device root of trust on different platforms.
+ *
+ * @param key_buf buffer to be filled with the device root of trust.
+ * @param length  length of the buffer provided to make sure no overflow occurs.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int8_t mbed_cloud_client_get_rot_128bit(uint8_t *key_buf, uint32_t length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ARM_UPDATE_CRYPTO_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_error.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,218 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_ERROR_H
+#define ARM_UPDATE_ERROR_H
+
+#include <stdint.h>
+
+// Use two characters to form the 16bit module code
+#define TWO_CC(A,B) (((A) & 0xFF) | (((B) & 0xFF) << 8))
+
+#define MANIFEST_MANAGER_PREFIX    TWO_CC('M','M')
+#define CERTIFICATE_MANAGER_PREFIX TWO_CC('C','M')
+#define SOURCE_MANAGER_PREFIX      TWO_CC('S','M')
+#define SOURCE_PREFIX              TWO_CC('S','E')
+#define FIRMWARE_MANAGER_PREFIX    TWO_CC('F','M')
+#define DER_PARSER_PREFIX          TWO_CC('D','P')
+#define MBED_TLS_ERROR_PREFIX      TWO_CC('M','T')
+#define UPDATE_CRYPTO_PREFIX       TWO_CC('C','U')
+#define DEVICE_IDENTITY_PREFIX     TWO_CC('D','I')
+#define HUB_PREFIX                 TWO_CC('H','B')
+#define EVENT_QUEUE_PREFIX         TWO_CC('E','Q')
+
+#define ARM_UC_COMMON_ERR_LIST\
+    ENUM_FIXED(ERR_NONE,0)\
+    ENUM_AUTO(ERR_UNSPECIFIED)\
+    ENUM_AUTO(ERR_INVALID_PARAMETER)\
+    ENUM_AUTO(ERR_NULL_PTR)\
+    ENUM_AUTO(ERR_NOT_READY)\
+    ENUM_AUTO(ERR_INVALID_STATE)\
+
+// Manifest manager
+#define ARM_UC_MM_ERR_LIST\
+    ENUM_FIXED(MFST_ERR_NONE, MANIFEST_MANAGER_PREFIX << 16)\
+    ENUM_AUTO(MFST_ERR_NULL_PTR)\
+    ENUM_AUTO(MFST_ERR_PENDING)\
+    ENUM_AUTO(MFST_ERR_SIZE)\
+    ENUM_AUTO(MFST_ERR_DER_FORMAT)\
+    ENUM_AUTO(MFST_ERR_FORMAT)\
+    ENUM_AUTO(MFST_ERR_VERSION)\
+    ENUM_AUTO(MFST_ERR_ROLLBACK)\
+    ENUM_AUTO(MFST_ERR_CRYPTO_MODE)\
+    ENUM_AUTO(MFST_ERR_HASH)\
+    ENUM_AUTO(MFST_ERR_GUID_VENDOR)\
+    ENUM_AUTO(MFST_ERR_GUID_DEVCLASS)\
+    ENUM_AUTO(MFST_ERR_GUID_DEVICE)\
+    ENUM_AUTO(MFST_ERR_CFG_CREATE_FAILED)\
+    ENUM_AUTO(MFST_ERR_KEY_SIZE)\
+    ENUM_AUTO(MFST_ERR_CERT_INVALID)\
+    ENUM_AUTO(MFST_ERR_CERT_NOT_FOUND)\
+    ENUM_AUTO(MFST_ERR_CERT_READ)\
+    ENUM_AUTO(MFST_ERR_INVALID_SIGNATURE)\
+    ENUM_AUTO(MFST_ERR_INVALID_STATE)\
+    ENUM_AUTO(MFST_ERR_BAD_EVENT)\
+    ENUM_AUTO(MFST_ERR_EMPTY_FIELD)\
+    ENUM_AUTO(MFST_ERR_NO_MANIFEST)\
+    ENUM_AUTO(MFST_ERR_SIGNATURE_ALGORITHM)\
+    ENUM_AUTO(MFST_ERR_UNSUPPORTED_CONDITION)\
+    ENUM_AUTO(MFST_ERR_CTR_IV_SIZE)\
+    ENUM_AUTO(MFST_ERR_BAD_KEYTABLE_REF)\
+    ENUM_AUTO(MFST_ERR_BAD_KEYTABLE)\
+
+// Certificate Manager
+#define ARM_UC_CM_ERR_LIST\
+    ENUM_FIXED(ARM_UC_CM_ERR_NONE, CERTIFICATE_MANAGER_PREFIX << 16)\
+    ENUM_AUTO(ARM_UC_CM_ERR_INVALID_PARAMETER)\
+    ENUM_AUTO(ARM_UC_CM_ERR_NOT_FOUND)\
+    ENUM_AUTO(ARM_UC_CM_ERR_INVALID_CERT)\
+    ENUM_AUTO(ARM_UC_CM_ERR_BLACKLISTED)\
+
+// DER Parser
+#define ARM_UC_DP_ERR_LIST\
+    ENUM_FIXED(ARM_UC_DP_ERR_NONE, DER_PARSER_PREFIX << 16)\
+    ENUM_AUTO(ARM_UC_DP_ERR_UNKNOWN)\
+    ENUM_AUTO(ARM_UC_DP_ERR_NOT_FOUND)\
+    ENUM_AUTO(ARM_UC_DP_ERR_NO_MORE_ELEMENTS)\
+
+// Source Manager
+#define ARM_UC_SM_ERR_LIST\
+    ENUM_FIXED(SOMA_ERR_NONE, SOURCE_MANAGER_PREFIX << 16)\
+    ENUM_AUTO(SOMA_ERR_UNSPECIFIED)\
+    ENUM_AUTO(SOMA_ERR_NO_ROUTE_TO_SOURCE)\
+    ENUM_AUTO(SOMA_ERR_SOURCE_REGISTRY_FULL)\
+    ENUM_AUTO(SOMA_ERR_SOURCE_NOT_FOUND)\
+    ENUM_AUTO(SOMA_ERR_INVALID_URI)\
+    ENUM_AUTO(SOMA_ERR_INVALID_REQUEST)\
+    ENUM_AUTO(SOMA_ERR_INVALID_PARAMETER)\
+    ENUM_AUTO(SOMA_ERR_INVALID_MANIFEST_STATE)\
+    ENUM_AUTO(SOMA_ERR_INVALID_FW_STATE)\
+    ENUM_AUTO(SOMA_ERR_INVALID_EVENT)
+
+// Source
+#define ARM_UC_SRC_ERR_LIST\
+    ENUM_FIXED(SRCE_ERR_NONE, SOURCE_PREFIX << 16)\
+    ENUM_AUTO(SRCE_ERR_UNINITIALIZED)\
+    ENUM_AUTO(SRCE_ERR_INVALID_PARAMETER)\
+    ENUM_AUTO(SRCE_ERR_FAILED)\
+    ENUM_AUTO(SRCE_ERR_ABORT)\
+    ENUM_AUTO(SRCE_ERR_BUSY)
+
+// Firmware Manager
+#define ARM_UC_FM_ERR_LIST\
+    ENUM_FIXED(FIRM_ERR_NONE, FIRMWARE_MANAGER_PREFIX << 16)\
+    ENUM_AUTO(FIRM_ERR_WRITE)\
+    ENUM_AUTO(FIRM_ERR_INVALID_PARAMETER)\
+    ENUM_AUTO(FIRM_ERR_ACTIVATE)\
+    ENUM_AUTO(FIRM_ERR_UNINITIALIZED)\
+    ENUM_AUTO(FIRM_ERR_INVALID_HASH)
+
+#define ARM_UC_CU_ERR_LIST\
+    ENUM_FIXED(ARM_UC_CU_ERR_NONE, UPDATE_CRYPTO_PREFIX << 16)\
+    ENUM_AUTO(ARM_UC_CU_ERR_INVALID_PARAMETER)\
+
+#define ARM_UC_DI_ERR_LIST\
+    ENUM_FIXED(ARM_UC_DI_ERR_NONE, DEVICE_IDENTITY_PREFIX << 16)\
+    ENUM_AUTO(ARM_UC_DI_ERR_INVALID_PARAMETER)\
+    ENUM_AUTO(ARM_UC_DI_ERR_NOT_READY)\
+    ENUM_AUTO(ARM_UC_DI_ERR_NOT_FOUND)\
+    ENUM_AUTO(ARM_UC_DI_ERR_SIZE)\
+
+#define ARM_UC_HB_ERR_LIST\
+    ENUM_FIXED(HUB_ERR_NONE, HUB_PREFIX << 16)\
+    ENUM_AUTO(HUB_ERR_INTERNAL_ERROR)\
+    ENUM_AUTO(HUB_ERR_ROLLBACK_PROTECTION)\
+    ENUM_AUTO(ARM_UC_HUB_ERR_NOT_AVAILABLE)\
+    ENUM_AUTO(HUB_ERR_CONNECTION)\
+
+#define ARM_UC_EQ_ERR_LIST\
+    ENUM_FIXED(ARM_UC_EQ_ERR_NONE, EVENT_QUEUE_PREFIX)\
+    ENUM_AUTO(ARM_UC_EQ_ERR_POOL_EXHAUSTED)\
+    ENUM_AUTO(ARM_UC_EQ_ERR_FAILED_TAKE)\
+
+#define ARM_UC_ERR_LIST\
+    ARM_UC_COMMON_ERR_LIST\
+    ARM_UC_MM_ERR_LIST\
+    ARM_UC_CM_ERR_LIST\
+    ARM_UC_DP_ERR_LIST\
+    ARM_UC_SM_ERR_LIST\
+    ARM_UC_SRC_ERR_LIST\
+    ARM_UC_FM_ERR_LIST\
+    ARM_UC_CU_ERR_LIST\
+    ARM_UC_DI_ERR_LIST\
+    ARM_UC_HB_ERR_LIST\
+    ARM_UC_EQ_ERR_LIST\
+
+enum arm_uc_error {
+    #define ENUM_AUTO(name) name,
+    #define ENUM_FIXED(name, val) name = val,
+    ARM_UC_ERR_LIST
+    #undef ENUM_AUTO
+    #undef ENUM_FIXED
+};
+union arm_uc_error_code {
+    int32_t code;
+    struct {
+        int16_t error;
+        union {
+            uint16_t module;
+            uint8_t  modulecc[2];
+        };
+    };
+};
+
+typedef union arm_uc_error_code arm_uc_error_t;
+
+
+#define ARM_UC_ERROR(CODE)              ((arm_uc_error_t){ CODE })
+#define ARM_UC_IS_ERROR(VAR)            ((VAR).error != ERR_NONE)
+#define ARM_UC_IS_NOT_ERROR(VAR)        (!ARM_UC_IS_ERROR(VAR))
+
+#define ARM_UC_CLEAR_ERROR(ERR)\
+    ((ERR).code = (ERR_NONE))
+#define ARM_UC_INIT_ERROR(VAR, CODE)    arm_uc_error_t (VAR) = arm_uc_code_to_error( CODE )
+#define ARM_UC_GET_ERROR(VAR)           ((VAR).code)
+
+#if ARM_UC_ERROR_TRACE_ENABLE
+#define ARM_UC_SET_ERROR(VAR, CODE)\
+    do { (VAR).code = (CODE);\
+    if ( ARM_UC_IS_ERROR(VAR) ) \
+        UC_ERROR_TRACE("set error %" PRIx32, (long unsigned int)CODE);\
+    } while (0)
+#else
+#define ARM_UC_SET_ERROR(VAR, CODE)                 (VAR).code = (CODE)
+#endif
+// have a way to set errors without trace for values that are not strictly errors.
+#define ARM_UC_SET_ERROR_NEVER_TRACE(VAR, CODE)     (VAR).code = (CODE)
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const char* ARM_UC_err2Str(arm_uc_error_t err);
+static inline arm_uc_error_t arm_uc_code_to_error(uint32_t code) {
+    arm_uc_error_t err;
+    err.code = code;
+    return err;
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif // ARM_UPDATE_ERROR_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_metadata_header_v2.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,190 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_METADATA_HEADER_V2_H
+#define ARM_UC_METADATA_HEADER_V2_H
+
+#include "update-client-common/arm_uc_types.h"
+#include "update-client-common/arm_uc_error.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ARM_UC_INTERNAL_HEADER_MAGIC_V2   (0x5a51b3d4UL)
+#define ARM_UC_INTERNAL_HEADER_VERSION_V2 (2)
+
+#define ARM_UC_EXTERNAL_HEADER_MAGIC_V2   (0x5a51b3d4UL)
+#define ARM_UC_EXTERNAL_HEADER_VERSION_V2 (2)
+
+#define ARM_UC_INTERNAL_FIRMWARE_VERSION_OFFSET_V2 (8)
+#define ARM_UC_INTERNAL_FIRMWARE_SIZE_OFFSET_V2    (16)
+#define ARM_UC_INTERNAL_FIRMWARE_HASH_OFFSET_V2    (24)
+#define ARM_UC_INTERNAL_CAMPAIGN_OFFSET_V2         (88)
+#define ARM_UC_INTERNAL_SIGNATURE_SIZE_OFFSET_V2   (104)
+#define ARM_UC_INTERNAL_HEADER_CRC_OFFSET_V2       (108)
+
+#define ARM_UC_INTERNAL_HEADER_SIZE_V2 (112)
+
+#define ARM_UC_EXTERNAL_FIRMWARE_VERSION_OFFSET_V2 (8)
+#define ARM_UC_EXTERNAL_FIRMWARE_SIZE_OFFSET_V2    (16)
+#define ARM_UC_EXTERNAL_FIRMWARE_HASH_OFFSET_V2    (24)
+#define ARM_UC_EXTERNAL_PAYLOAD_SIZE_OFFSET_V2     (88)
+#define ARM_UC_EXTERNAL_PAYLOAD_HASH_OFFSET_V2     (96)
+#define ARM_UC_EXTERNAL_CAMPAIGN_OFFSET_V2         (160)
+#define ARM_UC_EXTERNAL_HMAC_OFFSET_V2             (232)
+
+#define ARM_UC_EXTERNAL_HEADER_SIZE_V2 (296)
+
+typedef struct _arm_uc_internal_header_t
+{
+    /* Metadata-header specific magic code */
+    uint32_t headerMagic;
+
+    /* Revision number for metadata header. */
+    uint32_t headerVersion;
+
+    /* Version number accompanying the firmware. Larger numbers imply more
+       recent and preferred versions. This is used for determining the
+       selection order when multiple versions are available. For downloaded
+       firmware the manifest timestamp is used as the firmware version.
+    */
+    uint64_t firmwareVersion;
+
+    /* Total space (in bytes) occupied by the firmware BLOB. */
+    uint64_t firmwareSize;
+
+    /* Firmware hash calculated over the firmware size. Should match the hash
+       generated by standard command line tools, e.g., shasum on Linux/Mac.
+    */
+    uint8_t firmwareHash[ARM_UC_SHA512_SIZE];
+
+    /* The ID for the update campaign that resulted in the firmware update.
+    */
+    uint8_t campaign[ARM_UC_GUID_SIZE];
+
+    /* Size of the firmware signature. Must be 0 if no signature is supplied. */
+    uint32_t firmwareSignatureSize;
+
+    /* Header 32 bit CRC. Calculated over the entire header, including the CRC
+       field, but with the CRC set to zero.
+    */
+    uint32_t headerCRC;
+
+    /* Optional firmware signature. Hashing algorithm should be the same as the
+       one used for the firmware hash. The firmwareSignatureSize must be set.
+    */
+    uint8_t firmwareSignature[0];
+} arm_uc_internal_header_t;
+
+typedef struct _arm_uc_external_header_t
+{
+    /* Metadata-header specific magic code */
+    uint32_t headerMagic;
+
+    /* Revision number for metadata header. */
+    uint32_t headerVersion;
+
+    /* Version number accompanying the firmware. Larger numbers imply more
+       recent and preferred versions. This is used for determining the
+       selection order when multiple versions are available. For downloaded
+       firmware the manifest timestamp is used as the firmware version.
+    */
+    uint64_t firmwareVersion;
+
+    /* Total space (in bytes) occupied by the firmware BLOB. */
+    uint64_t firmwareSize;
+
+    /* Firmware hash calculated over the firmware size. Should match the hash
+       generated by standard command line tools, e.g., shasum on Linux/Mac.
+    */
+    uint8_t firmwareHash[ARM_UC_SHA512_SIZE];
+
+    /* Total space (in bytes) occupied by the payload BLOB.
+       The payload is the firmware after some form of transformation like
+       encryption and/or compression.
+    */
+    uint64_t payloadSize;
+
+    /* Payload hash calculated over the payload size. Should match the hash
+       generated by standard command line tools, e.g., shasum on Linux/Mac.
+       The payload is the firmware after some form of transformation like
+       encryption and/or compression.
+    */
+    uint8_t payloadHash[ARM_UC_SHA512_SIZE];
+
+    /* The ID for the update campaign that resulted in the firmware update.
+    */
+    uint8_t campaign[ARM_UC_GUID_SIZE];
+
+    /* Type of transformation used to turn the payload into the firmware image.
+       Possible values are:
+     * * NONE
+     * * AES128_CTR
+     * * AES128_CBC
+     * * AES256_CTR
+     * * AES256_CBC
+     */
+    uint32_t firmwareTransformationMode;
+
+    /* Encrypted firmware encryption key.
+     * To decrypt the firmware, the bootloader combines the bootloader secret
+     * and the firmwareKeyDerivationFunctionSeed to create an AES key. It uses
+     * This AES key to decrypt the firmwareCipherKey. The decrypted
+     * firmwareCipherKey is the FirmwareKey, which is used with the
+     * firmwareInitVector to decrypt the firmware.
+     */
+    uint8_t firmwareCipherKey[ARM_UC_AES256_KEY_SIZE];
+
+    /* AES Initialization vector. This is a random number used to protect the
+       encryption algorithm from attack. It must be unique for every firmware.
+     */
+    uint8_t firmwareInitVector[ARM_UC_AES_BLOCK_SIZE];
+
+    /* Size of the firmware signature. Must be 0 if no signature is supplied. */
+    uint32_t firmwareSignatureSize;
+
+    /* Hash based message authentication code for the metadata header. Uses per
+       device secret as key. Should use same hash algorithm as firmware hash.
+       The headerHMAC field and firmwareSignature field are not part of the hash.
+    */
+    uint8_t headerHMAC[ARM_UC_SHA512_SIZE];
+
+    /* Optional firmware signature. Hashing algorithm should be the same as the
+       one used for the firmware hash. The firmwareSignatureSize must be set.
+    */
+    uint8_t firmwareSignature[0];
+} arm_uc_external_header_t;
+
+arm_uc_error_t arm_uc_parse_internal_header_v2(const uint8_t* input,
+                                               arm_uc_firmware_details_t* output);
+
+arm_uc_error_t arm_uc_create_internal_header_v2(const arm_uc_firmware_details_t* input,
+                                                arm_uc_buffer_t* output);
+
+arm_uc_error_t arm_uc_parse_external_header_v2(const uint8_t* input,
+                                               arm_uc_firmware_details_t* output);
+
+arm_uc_error_t arm_uc_create_external_header_v2(const arm_uc_firmware_details_t* input,
+                                                arm_uc_buffer_t* output);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ARM_UC_METADATA_HEADER_V2_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_public.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,64 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_COMMON_PUBLIC_H
+#define ARM_UPDATE_COMMON_PUBLIC_H
+
+#include <stdint.h>
+
+#ifndef ARM_UPDATE_CLIENT_VERSION
+#define ARM_UPDATE_CLIENT_VERSION "Update Client 1.1"
+#endif
+
+#ifndef ARM_UPDATE_CLIENT_VERSION_VALUE
+#define ARM_UPDATE_CLIENT_VERSION_VALUE 101001UL
+#endif
+
+/**
+ * Public error codes for the Update Client.
+ */
+enum {
+    ARM_UC_WARNING,
+    ARM_UC_WARNING_CERTIFICATE_NOT_FOUND,
+    ARM_UC_WARNING_IDENTITY_NOT_FOUND,
+    ARM_UC_WARNING_VENDOR_MISMATCH,
+    ARM_UC_WARNING_CLASS_MISMATCH,
+    ARM_UC_WARNING_DEVICE_MISMATCH,
+    ARM_UC_WARNING_CERTIFICATE_INVALID,
+    ARM_UC_WARNING_SIGNATURE_INVALID,
+    ARM_UC_WARNING_URI_NOT_FOUND,
+    ARM_UC_WARNING_ROLLBACK_PROTECTION,
+    ARM_UC_WARNING_UNKNOWN,
+    ARM_UC_ERROR,
+    ARM_UC_ERROR_WRITE_TO_STORAGE,
+    ARM_UC_ERROR_INVALID_HASH,
+    ARM_UC_FATAL,
+    ARM_UC_ERROR_CONNECTION,
+    ARM_UC_UNKNOWN
+};
+
+/**
+ * Public update requests
+ */
+typedef enum {
+    ARM_UCCC_REQUEST_INVALID,
+    ARM_UCCC_REQUEST_DOWNLOAD,
+    ARM_UCCC_REQUEST_INSTALL,
+} arm_uc_request_t;
+
+#endif // ARM_UPDATE_COMMON_PUBLIC_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_scheduler.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,262 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_SCHEDULER_H
+#define ARM_UPDATE_SCHEDULER_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/** 
+ * @file arm_uc_scheduler.h
+ * @brief A simple, atomic event queue for embedded systems
+ * 
+ * @details This is a simple scheduler useful for collecting events from
+ * different threads and interrupt context so they can be executed from the
+ * same thread/context.
+ *
+ * This can reduce the calldepth, ensure functions are executed from the same
+ * thread, and provide a method for breaking out of interrupt context.
+ *
+ * Callbacks are executed FIFO.
+ *
+ * The notification handler should be used for processing the queue whenever it
+ * is non-empty.
+ * 
+ * This event queue uses an underlying atomic queue implementation
+ * to provide atomicity guaranties without Critical Section primitives on 
+ * Cortex-M3 or later platforms. Linux and Cortex-M0 require a Critical Section
+ * due to the lack of exclusive access primitives. See the atomic-queue
+ * documentation for more detail on atomic access.
+ * 
+ * An atomic queue has been used for three reasons:
+ * 1. This allows the queue to be used in contexts where some RTOS primitives
+ *    (mutexes) cannot be used, such as interrupt context.
+ * 2. On many platforms, critical sections are very expensive, while atomics
+ *    are not. Thus, there is a significant performance benefit to using atomic
+ *    primitives wherever possible.
+ * 3. Atomic operations have the least effect on all other execution contexts
+ *    on the device. Critical sections have performance and responsiveness side
+ *    effects. Mutexes can disrupt the execution of other threads. Atomics do 
+ *    not affect the execution of other contexts and are immune to priority
+ *    inversion
+ * 
+ * In short, the atomic queue is the most cooperative way of building an event
+ * queue.
+ * 
+ * This queue does, however have three major drawbacks:
+ * 1. There is no way to directly cancel a callback. This is because the atomic
+ *    queue has no way to remove an element from the middle of the queue. It
+ *    can only be removed from the head of the queue.
+ * 2. There is no way to prioritize one callback over another in the same 
+ *    queue. This is because there is no way to insert a callback into the
+ *    middle of the queue. It can only be added at the end.
+ * 3. The queue is entirely dependent on correct memory ownership, but it
+ *    allocates no memory. The queue must own the callbacks while they are in
+ *    the queue and any manipulation of that storage could break the behaviour
+ *    of the queue.
+ *    
+ * To compensate for 1., a callback author can provide a cancellation flag for 
+ * their callback that is checked on entry, but this may not know if it was
+ * successful. The implementation of callback cancellation is beyond the scope
+ * of this document.
+ * 
+ * To compensate for 2., a prioritized event queue could be constructed from
+ * two or more atomic queues. Since an event queue only takes a single pointer
+ * of dedicated storage, this is can be used with a small number of priorities.
+ * The implementation of a prioritized event queue is beyond the scope of this
+ * document.
+ * 
+ * In typical (non-atomic) structures, the solution for 3. is to allocate a
+ * new callback storage block from the heap on each call. This would ensure
+ * that the queue owns the block. However, this is not possible from an
+ * interrupt context. Therefore, the queue uses a pool allocator instead.
+ * However, pool allocators can run out of elements very easily. To ensure
+ * that a particular callback can be scheduled, it is possible to give the
+ * callback a statically allocated block instead. However, this introduces a
+ * new failure mode: what happens if the block is already in use?
+ *
+ * To compensate for this failure mode, a per-element lock is provided in every
+ * atomic queue element. The lock must be taken before ANY content of the
+ * element is modified, including setting the callback and parameter. The lock
+ * must only be released after the contents of the element have been copied
+ * out.
+ * 
+ * Because both statically allocated blocks and pool allocated blocks are
+ * available, the user of the event queue is presented with a choice: Use a
+ * statically allocated callback element, or use a pool allocated callback
+ * element. Each option is better for different use-cases. When it is only
+ * semantically possible for one callback from a given block of code to be in
+ * flight at a time, it is more reliable for the callback to be statically
+ * allocated. When it's possible for more than one callback from the same block
+ * of code to be in flight at a time, then the pool allocator is a better
+ * choice. Notwithstanding this distinction, if the scheduler fails to acquire
+ * a lock on a statically allocated element, it will allocate a pool element
+ * instead.
+ *
+ * To reduce API complexity, the callback queue mechanism works as below:
+ * 
+ * When a callback is posted, the scheduler attempts to acquire the lock.
+ * If either the callback storage is NULL or the lock cannot be acquired, the
+ * scheduler pool-allocates a callback. If that fails, the scheduler uses a
+ * dedicated error callback to notify the system that pool allocation has
+ * failed, since this is a critical error.
+ * 
+ * This event queue is composed of two major parts:
+ * * The mechanism to post a callback (ARM_UC_PostCallback)
+ * * The mechanism to process a callback
+ * 
+ * When posting a callback, the scheduler first takes the lock on the supplied
+ * callback structure, or pool-allocates a new one and then takes the lock. The
+ * supplied event handler and event parameter are then placed into the supplied
+ * (or pool-allocated) callback structure. The callback structure is then
+ * placed in the event queue for later execution. If the queue was empty prior
+ * to queuing this element, then the notification handler is invoked.
+ * 
+ * **NOTE:** this means that the notification handler MUST be safe to execute
+ * in IRQ context.
+ * 
+ * When the queue is processed, callbacks are extracted in FIFO order. The
+ * scheduler can be run in one of two modes:
+ * * Consume the whole queue (ARM_UC_ProcessQueue)
+ * * Consume single event (ARM_UC_ProcessSingleCallback)
+ * 
+ * Both of these operations execute the same process:
+ * 1. An element is dequeued from the atomic-queue
+ * 2. The contents of the element are extracted
+ * 3. The element is unlocked
+ * 4. If the element was pool-allocated, it is freed
+ * 5. The callback is executed with the supplied parameter
+ * 
+ * Finally, ARM_UC_ProcessQueue goes back to 1, while 
+ * ARM_UC_ProcessSingleCallback returns true if there are still callbacks in
+ * the queue, false otherwise.
+ * 
+ * Callback Pool:
+ * The callback pool is configured using a system define: 
+ *     ARM_UC_SCHEDULER_STORAGE_POOL_SIZE
+ * To set the size of the pool, override this define in your build system. To
+ * disable the pool, set this define to 0.
+ * 
+ * To assist with callback pool debugging, an API is provided to calculate the
+ * high watermark of the pool: ARM_UC_SchedulerGetHighWatermark(). This can be
+ * compared to ARM_UC_SCHEDULER_STORAGE_POOL_SIZE to determine how many
+ * elements were left at maximum usage.
+ */
+
+/**
+ * Use custom struct for the lockfree queue.
+ * Struct contains function pointer callback and uint32_t parameter.
+ */
+#define ATOMIC_QUEUE_CUSTOM_ELEMENT
+
+struct lockfree_queue_element {
+    struct lockfree_queue_element * volatile next;
+    uintptr_t lock;
+    void (*callback)(uint32_t);
+    uint32_t parameter;
+};
+
+#include "atomic-queue/atomic-queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct lockfree_queue_element arm_uc_callback_t;
+
+/**
+ * @brief Add function to be executed to the queue.
+ * @details The caller is responsible for managing the memory for each element
+ *          in the queue, i.e., allocating enough struct lockfree_queue_element
+ *          to hold the number of outstanding callbacks in the queue.
+ *
+ * @param storage Pointer to struct lockfree_queue_element.
+ * @param callback Function pointer to function being scheduled to run later.
+ * @param parameter uint32_t value to be passed as parameter to the callback function.
+ * @return True when the callback was successfully scheduled.
+ */
+bool ARM_UC_PostCallback(arm_uc_callback_t* storage, void (*callback)(uint32_t), uint32_t parameter);
+
+/**
+ * @brief Calling this function processes all callbacks in the queue.
+ */
+void ARM_UC_ProcessQueue(void);
+
+/**
+ * @brief Calling this function processes a single callback in the queue.
+ * @details The return value indicates whether there are more callbacks
+ *          in the queue that needs handling.
+ * @return True when there are more callbacks in the queue, false otherwise.
+ */
+bool ARM_UC_ProcessSingleCallback(void);
+
+/**
+ * @brief Register callback function for when callbacks are added to an empty queue.
+ * @details This function is called at least once (maybe more) when callbacks are
+ *          added to an empty queue. Useful for scheduling when the queue needs
+ *          to be processed.
+ * @param handler Function pointer to function to be called when elements are
+ *        added to an empty queue.
+ */
+void ARM_UC_AddNotificationHandler(void (*handler)(void));
+
+/**
+ * @brief Initialize the scheduler.
+ * @details This function primarily initializes the pool allocator for
+ * callbacks. It should be called prior to using the scheduler at all.
+ */
+void ARM_UC_SchedulerInit(void);
+
+/**
+ * @brief Set the handler for scheduler errors.
+ * @details This will be called in normal scheduler context when the pool runs
+ * out of available callbacks.
+ * 
+ * @param[in] handler The function to call (thread context) when there is a
+ *                    scheduler error.
+ */
+void ARM_UC_SetSchedulerErrorHandler(void(*handler)(uint32_t));
+
+/**
+ * @brief Get the maximum usage of the callback pool.
+ * @details Uses the high watermark of the callback pool to indicate the 
+ * worst-case callback usage.
+ * 
+ * @return the maximum number of callbacks that have been allocated from the
+ * pool at one time.
+ */
+uint32_t ARM_UC_SchedulerGetHighWatermark(void);
+
+/**
+ * @brief Get the current number of queued callbacks
+ * @details This is a function for running tests. The value returned by this
+ * function cannot be relied upon in any system that is not exclusively
+ * single-threaded, since any parallel thread or any interrupt could modify the
+ * count.
+ * 
+ * @return The number of callbacks currently queued in the scheduler.
+ */
+int32_t ARM_UC_SchedulerGetQueuedCount(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ARM_UPDATE_SCHEDULER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_trace.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,164 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_TRACE_H
+#define ARM_UPDATE_TRACE_H
+
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <string.h>
+
+/*
+    Available update client trace flags:
+    ARM_UC_ALL_TRACE_ENABLE
+    ARM_UC_HUB_TRACE_ENABLE
+    ARM_UC_COMMON_TRACE_ENABLE
+    ARM_UC_FIRMWARE_MANAGER_TRACE_ENABLE
+    ARM_UC_CONTROL_CENTER_TRACE_ENABLE
+    ARM_UC_MANIFEST_MANAGER_TRACE_ENABLE
+    ARM_UC_SOURCE_MANAGER_TRACE_ENABLE
+    ARM_UC_PAAL_TRACE_ENABLE
+*/
+
+/* if the global trace flag is enabled, enable trace for all hub modules */
+#if defined(MBED_CONF_MBED_TRACE_ENABLE) && MBED_CONF_MBED_TRACE_ENABLE == 1
+#include "mbed-trace/mbed_trace.h"
+#undef ARM_UC_ALL_TRACE_ENABLE
+#define ARM_UC_ALL_TRACE_ENABLE 1
+#endif // if MBED_CONF_MBED_TRACE_ENABLE
+
+#if defined(ARM_UC_ALL_TRACE_ENABLE) && ARM_UC_ALL_TRACE_ENABLE == 1
+#undef ARM_UC_HUB_TRACE_ENABLE
+#define ARM_UC_HUB_TRACE_ENABLE 1
+#undef ARM_UC_FIRMWARE_MANAGER_TRACE_ENABLE
+#define ARM_UC_FIRMWARE_MANAGER_TRACE_ENABLE 1
+#undef ARM_UC_MANIFEST_MANAGER_TRACE_ENABLE
+#define ARM_UC_MANIFEST_MANAGER_TRACE_ENABLE 1
+#undef ARM_UC_SOURCE_MANAGER_TRACE_ENABLE
+#define ARM_UC_SOURCE_MANAGER_TRACE_ENABLE 1
+#undef ARM_UC_CONTROL_CENTER_TRACE_ENABLE
+#define ARM_UC_CONTROL_CENTER_TRACE_ENABLE 1
+#undef ARM_UC_COMMON_TRACE_ENABLE
+#define ARM_UC_COMMON_TRACE_ENABLE 1
+#undef ARM_UC_PAAL_TRACE_ENABLE
+#define ARM_UC_PAAL_TRACE_ENABLE 1
+#endif // if ARM_UC_ALL_TRACE_ENABLE
+
+#if ARM_UC_HUB_TRACE_ENABLE
+#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+#if MBED_CONF_MBED_TRACE_ENABLE
+#define UC_HUB_TRACE(fmt, ...) mbed_tracef(TRACE_LEVEL_DEBUG, "HUB ", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_HUB_ERR_MSG(fmt, ...) mbed_tracef(TRACE_LEVEL_ERROR, "HUB ", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#else
+#define UC_HUB_TRACE(fmt, ...) printf("[TRACE][HUB]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_HUB_ERR_MSG(fmt, ...) printf("[ERROR][HUB]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#endif // if MBED_CONF_MBED_TRACE_ENABLE
+#else
+#define UC_HUB_TRACE(...)
+#define UC_HUB_ERR_MSG(...)
+#endif // if ARM_UC_FIRMWARE_MANAGER_TRACE_ENABLE
+
+#if ARM_UC_FIRMWARE_MANAGER_TRACE_ENABLE
+#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+#if MBED_CONF_MBED_TRACE_ENABLE
+#define UC_FIRM_TRACE(fmt, ...) mbed_tracef(TRACE_LEVEL_DEBUG, "FIRM", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_FIRM_ERR_MSG(fmt, ...) mbed_tracef(TRACE_LEVEL_ERROR, "FIRM", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#else
+#define UC_FIRM_TRACE(fmt, ...) printf("[TRACE][FIRM]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_FIRM_ERR_MSG(fmt, ...) printf("[ERROR][FIRM]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#endif // if MBED_CONF_MBED_TRACE_ENABLE
+#else
+#define UC_FIRM_TRACE(fmt, ...)
+#define UC_FIRM_ERR_MSG(fmt, ...)
+#endif // if ARM_UC_FIRMWARE_MANAGER_TRACE_ENABLE
+
+#if ARM_UC_MANIFEST_MANAGER_TRACE_ENABLE
+#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+#if MBED_CONF_MBED_TRACE_ENABLE
+#define UC_MMGR_TRACE(fmt, ...) mbed_tracef(TRACE_LEVEL_DEBUG, "MMGR", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_MMGR_ERR_MSG(fmt, ...) mbed_tracef(TRACE_LEVEL_ERROR, "MMGR", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#else
+#define UC_MMGR_TRACE(fmt, ...) printf("[TRACE][MMGR]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_MMGR_ERR_MSG(fmt, ...) printf("[ERROR][MMGR]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#endif // if MBED_CONF_MBED_TRACE_ENABLE
+#else
+#define UC_MMGR_TRACE(fmt, ...)
+#define UC_MMGR_ERR_MSG(fmt, ...)
+#endif // if ARM_UC_MANIFEST_MANAGER_TRACE_ENABLE
+
+#if ARM_UC_SOURCE_MANAGER_TRACE_ENABLE
+#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+#if MBED_CONF_MBED_TRACE_ENABLE
+#define UC_SRCE_TRACE(fmt, ...) mbed_tracef(TRACE_LEVEL_DEBUG, "SRCE", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_SRCE_ERR_MSG(fmt, ...) mbed_tracef(TRACE_LEVEL_ERROR, "SRCE", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#else
+#define UC_SRCE_TRACE(fmt, ...) printf("[TRACE][SRCE]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_SRCE_ERR_MSG(fmt, ...) printf("[ERROR][SRCE]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#endif // if MBED_CONF_MBED_TRACE_ENABLE
+#else
+#define UC_SRCE_TRACE(fmt, ...)
+#define UC_SRCE_ERR_MSG(fmt, ...)
+#endif // if ARM_UC_SOURCE_MANAGER_TRACE_ENABLE
+
+#if ARM_UC_CONTROL_CENTER_TRACE_ENABLE
+#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+#if MBED_CONF_MBED_TRACE_ENABLE
+#define UC_CONT_TRACE(fmt, ...) mbed_tracef(TRACE_LEVEL_DEBUG, "CTRL", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_CONT_ERR_MSG(fmt, ...) mbed_tracef(TRACE_LEVEL_ERROR, "CTRL", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#else
+#define UC_CONT_TRACE(fmt, ...) printf("[TRACE][CTRL]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_CONT_ERR_MSG(fmt, ...) printf("[ERROR][CTRL]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#endif // if MBED_CONF_MBED_TRACE_ENABLE
+#else
+#define UC_CONT_TRACE(fmt, ...)
+#define UC_CONT_ERR_MSG(fmt, ...)
+#endif // if ARM_UC_FIRMWARE_MANAGER_TRACE_ENABLE
+
+#if ARM_UC_COMMON_TRACE_ENABLE
+#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+#if MBED_CONF_MBED_TRACE_ENABLE
+#define UC_COMM_TRACE(fmt, ...) mbed_tracef(TRACE_LEVEL_DEBUG, "COMM", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_COMM_ERR_MSG(fmt, ...) mbed_tracef(TRACE_LEVEL_ERROR, "COMM", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#else
+#define UC_COMM_TRACE(fmt, ...) printf("[TRACE][COMM]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_COMM_ERR_MSG(fmt, ...) printf("[ERROR][COMM]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#endif // if MBED_CONF_MBED_TRACE_ENABLE
+#else
+#define UC_COMM_TRACE(fmt, ...)
+#define UC_COMM_ERR_MSG(fmt, ...)
+#endif // if ARM_UC_COMMON_TRACE_ENABLE
+
+#if ARM_UC_PAAL_TRACE_ENABLE
+#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+#if MBED_CONF_MBED_TRACE_ENABLE
+#define UC_PAAL_TRACE(fmt, ...) mbed_tracef(TRACE_LEVEL_DEBUG, "PAAL", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_PAAL_ERR_MSG(fmt, ...) mbed_tracef(TRACE_LEVEL_ERROR, "PAAL", "%s:%d: " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__)
+#else
+#define UC_PAAL_TRACE(fmt, ...) printf("[TRACE][PAAL]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#define UC_PAAL_ERR_MSG(fmt, ...) printf("[ERROR][PAAL]" "%s:%d: " fmt "\r\n", __FILENAME__, __LINE__, ##__VA_ARGS__)
+#endif // if MBED_CONF_MBED_TRACE_ENABLE
+#else
+#define UC_PAAL_TRACE(fmt, ...)
+#define UC_PAAL_ERR_MSG(fmt, ...)
+#endif // if ARM_UC_COMMON_TRACE_ENABLE
+
+#endif // ARM_UPDATE_TRACE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_types.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,94 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_COMMON_TYPES_H
+#define ARM_UPDATE_COMMON_TYPES_H
+
+#include <stdint.h>
+
+typedef struct
+{
+    uint32_t size_max; // maximum size of the buffer
+    uint32_t size;     // index of the first empty byte in the buffer
+    uint8_t* ptr;      // pointer to buffer's memory
+} arm_uc_buffer_t;
+
+typedef enum {
+    URI_SCHEME_NONE,
+    URI_SCHEME_HTTP,
+} arm_uc_uri_scheme_t;
+
+typedef struct
+{
+    uint32_t            size_max; // maximum size of the buffer
+    uint32_t            size;     // index of the first empty byte in the buffer
+    uint8_t*            ptr;      // pointer to buffer's memory
+    arm_uc_uri_scheme_t scheme;     // URI type
+    uint16_t            port;     // connection port
+    char*               host;     // \0 terminated string with host name
+    char*               path;     // \0 terminated string with resource path
+} arm_uc_uri_t;
+
+#define ARM_UC_GUID_SIZE       (128/8)
+#define ARM_UC_SHA256_SIZE     (256/8)
+#define ARM_UC_SHA512_SIZE     (512/8)
+#define ARM_UC_AES256_KEY_SIZE (256/8)
+#define ARM_UC_AES_BLOCK_SIZE  (128/8)
+#define ARM_UC_ROT_SIZE        (128/8)
+#define ARM_UC_DEVICE_KEY_SIZE (256/8)
+
+#define ARM_UC_DEVICE_HMAC_KEY "StorageEnc256HMACSHA256SIGNATURE"
+#define ARM_UC_DEVICE_HMAC_KEY_SIZE (sizeof(ARM_UC_DEVICE_HMAC_KEY) - 1)
+
+/**
+ * @brief GUID type
+ */
+typedef uint8_t arm_uc_guid_t[ARM_UC_GUID_SIZE];
+
+/**
+ * @brief SHA256 hash
+ */
+typedef uint8_t arm_uc_hash_t[ARM_UC_SHA256_SIZE];
+
+/**
+ * @brief Firmware details struct.
+ * @details Struct for passing information between the Update client and the
+ *          PAAL implementation describing the firmware image.
+ */
+typedef struct _arm_uc_firmware_details_t
+{
+    uint64_t version;
+    uint64_t size;
+    arm_uc_hash_t hash;
+    arm_uc_guid_t campaign;
+    uint32_t signatureSize;
+    uint8_t signature[0];
+} arm_uc_firmware_details_t;
+
+/**
+ * @brief Installer details struct.
+ * @details Struct for reading the installer information.
+ */
+typedef struct _arm_uc_installer_details_t
+{
+    arm_uc_hash_t arm_hash;
+    arm_uc_hash_t oem_hash;
+    uint32_t layout;
+} arm_uc_installer_details_t;
+
+#endif // ARM_UPDATE_COMMON_TYPES_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/common/update-client-common/arm_uc_utilities.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,200 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_COMMON_UTILITIES_H
+#define ARM_UPDATE_COMMON_UTILITIES_H
+
+#include "update-client-common/arm_uc_types.h"
+#include "update-client-common/arm_uc_error.h"
+#include <string.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ARM_UC_util_min(A,B)\
+    ((A) < (B) ? (A) : (B))
+
+/* lookup table for printing hexadecimal characters. */
+extern const uint8_t arm_uc_hex_table[16];
+
+/**
+ * @brief Parse a uri string to populate a arm_uc_uri_t struct
+ * @detail Format of uri scheme:[//]host[:port]/path
+ *         [] means optional, path will always start with a '/'
+ *
+ * @param str Pointer to string containing URI.
+ * @param size String length.
+ * @param uri The arm_uc_uri_t struct to be populated
+ */
+arm_uc_error_t arm_uc_str2uri(const uint8_t* str, uint32_t size, arm_uc_uri_t* uri);
+
+/**
+ * @brief Find substring inside string.
+ * @details The size of both string and substring is explicitly passed so no
+ *          assumptions are made about NULL termination.
+ *
+ * @param big_buffer Pointer to the string to be searched.
+ * @param big_length Length of the string to be searched.
+ * @param little_buffer Pointer to the substring being searched for.
+ * @param little_length Length of the substring being searched for.
+ * @return Index to where the substring was found inside the string. If the
+ *         string doesn't contain the subtring, UINT32_MAX is returned.
+ */
+uint32_t arm_uc_strnstrn(const uint8_t* big_buffer,
+                         uint32_t big_length,
+                         const uint8_t* little_buffer,
+                         uint32_t little_length);
+
+/**
+ * @brief Find string length.
+ * @details Custom implementation of strnlen which is a GNU extension.
+ *          Returns either the string length or max_length.
+ *
+ * @param buffer Pointer to string.
+ * @param max_length Maximum buffer length.
+ *
+ * @return String length or max_length.
+ */
+uint32_t arm_uc_strnlen(const uint8_t* buffer, uint32_t max_length);
+
+/**
+ * @brief Convert string to unsigned 32 bit integer.
+ * @details Function tries to parse string as an unsigned 32 bit integer
+ *          and return the value. The function will set the third parameter
+ *          to true if the parsing was successful.
+ *
+ * @param buffer Pointer to string.
+ * @param max_length Maximum buffer length.
+ * @param success Pointer to boolean indicating whether the parsing was successful.
+ * @return Parsed value. Only valid if success it true.
+ */
+uint32_t arm_uc_str2uint32(const uint8_t* buffer,
+                           uint32_t max_length,
+                           bool* success);
+
+/**
+ * @brief Calculate CRC 32
+ *
+ * @param buffer Input array.
+ * @param length Length of array in bytes.
+ *
+ * @return 32 bit CRC.
+ */
+uint32_t arm_uc_crc32(const uint8_t* buffer, uint32_t length);
+
+/**
+ * @brief Parse 4 byte array into uint32_t
+ *
+ * @param input 4 byte array.
+ * @return uint32_t
+ */
+uint32_t arm_uc_parse_uint32(const uint8_t* input);
+
+/**
+ * @brief Parse 8 byte array into uint64_t
+ *
+ * @param input 8 byte array.
+ * @return uint64_t
+ */
+uint64_t arm_uc_parse_uint64(const uint8_t* input);
+
+/**
+ * @brief Write uint32_t to array.
+ *
+ * @param buffer Pointer to buffer.
+ * @param value Value to be written.
+ */
+void arm_uc_write_uint32(uint8_t* buffer, uint32_t value);
+
+/**
+ * @brief Write uint64_t to array.
+ *
+ * @param buffer Pointer to buffer.
+ * @param value Value to be written.
+ */
+void arm_uc_write_uint64(uint8_t* buffer, uint64_t value);
+
+/**
+ * @brief Do a shallow copy of a buffer.
+ * @details Copies each field of a buffer from `src` to `dest`. This creates another reference to the buffer that
+ *          backs `src` and drops any reference to a buffer that backs `dest`.
+ *
+ * @param[out] dest Pointer to a buffer structure that will receive a reference to the buffer that backs `src`
+ * @param[in] src Pointer to a buffer to copy into dest
+ */
+static inline void ARM_UC_buffer_shallow_copy(arm_uc_buffer_t* dest, arm_uc_buffer_t* src) {
+    dest->size_max = src->size_max;
+    dest->size     = src->size;
+    dest->ptr      = src->ptr;
+}
+
+/**
+ * @brief Do a deep copy of a buffer.
+ * @details Copies the content of `src->ptr` to `dest->ptr`
+ * If the space used in the source memory, referenced by the source buffer, is less than the maximum space available in
+ * the destination memory, referenced by the destination buffer, copies the source into the destination.
+ *
+ * @param[out] dest Pointer to a buffer structure that references destination memory
+ * @param[in] src Pointer to a buffer that references the data to copy into the destination memory
+ * @retval MFST_ERR_SIZE when the source size is larger than the destination's maximum size
+ * @retval MFST_ERR_NULL_PTR when any expected pointer is NULL
+ * @retval MFST_ERR_NONE on success
+ */
+static inline arm_uc_error_t ARM_UC_buffer_deep_copy(arm_uc_buffer_t* dest, arm_uc_buffer_t* src)
+{
+    ARM_UC_INIT_ERROR(retval, MFST_ERR_NULL_PTR);
+
+    /* NULL pointer check */
+    if (dest &&
+        dest->ptr &&
+        src &&
+        src->ptr)
+    {
+        /* destination buffer is large enough */
+        if (src->size <= dest->size_max)
+        {
+            /* copy content and set new size */
+            memcpy(dest->ptr, src->ptr, src->size);
+            dest->size = src->size;
+
+            ARM_UC_CLEAR_ERROR(retval);
+        }
+        else
+        {
+            ARM_UC_SET_ERROR(retval, MFST_ERR_SIZE);
+        }
+    }
+    else
+    {
+        ARM_UC_SET_ERROR(retval, MFST_ERR_NULL_PTR);
+    }
+
+    return retval;
+}
+
+uint32_t ARM_UC_BinCompareCT(const arm_uc_buffer_t* a, const arm_uc_buffer_t* b);
+uint8_t * ARM_UC_Base64Enc(uint8_t *buf, const uint32_t size, const arm_uc_buffer_t* bin);
+void ARM_UC_Base64Dec(arm_uc_buffer_t* bin, const uint32_t size, const uint8_t* buf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ARM_UPDATE_COMMON_UTILITIES_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/source/arm_uc_certificate.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,92 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-control-center/arm_uc_certificate.h"
+#include "update-client-common/arm_uc_config.h"
+
+#if ARM_UC_USE_KCM
+extern const struct arm_uc_certificate_api arm_uc_certificate_kcm_api;
+static const struct arm_uc_certificate_api* arm_uc_registered_certificate_api =
+    &arm_uc_certificate_kcm_api;
+#elif ARM_UC_USE_CFSTORE
+extern const struct arm_uc_certificate_api arm_uc_certificate_cfstore_api;
+static const struct arm_uc_certificate_api* arm_uc_registered_certificate_api =
+    &arm_uc_certificate_cfstore_api;
+#else
+#error No configuration store set
+#endif
+
+/**
+ * @brief Add certificate.
+ * @details [long description]
+ *
+ * @param certificate Pointer to certiface being added.
+ * @param certificate_size Certificate length.
+ * @param fingerprint Pointer to the fingerprint of the certificate being added.
+ * @param fingerprint_size Fingerprint length.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_Certificate_Add(const uint8_t* certificate,
+                                      uint16_t certificate_size,
+                                      const uint8_t* fingerprint,
+                                      uint16_t fingerprint_size,
+                                      void (*callback)(arm_uc_error_t, const arm_uc_buffer_t*))
+{
+    //cert Name: base64(fingerprint)
+    const arm_uc_buffer_t fingerprintBuffer = {
+        .size = fingerprint_size,
+        .size_max = fingerprint_size,
+        .ptr = (uint8_t *)fingerprint /* Const Cast safe because target is in a const struct */
+    };
+
+    const arm_uc_buffer_t certBuffer = {
+        .size = certificate_size,
+        .size_max = certificate_size,
+        .ptr = (uint8_t *)certificate /* Const Cast safe because target is in a const struct */
+    };
+
+    const struct arm_uc_certificate_api* api = arm_uc_registered_certificate_api;
+
+    if (api == NULL || api->store == NULL)
+    {
+        return (arm_uc_error_t){ ARM_UC_CM_ERR_INVALID_PARAMETER};
+    }
+
+    arm_uc_error_t err = api->store(&certBuffer, &fingerprintBuffer, callback);
+
+    if (err.error != 0)
+    {
+        return err;
+    }
+
+    return (arm_uc_error_t){ARM_UC_CM_ERR_NONE};
+}
+
+arm_uc_error_t ARM_UC_certificateFetch(arm_uc_buffer_t* certificate,
+    const arm_uc_buffer_t* fingerprint,
+    const arm_uc_buffer_t* DERCertificateList,
+    void (*callback)(arm_uc_error_t, const arm_uc_buffer_t*, const arm_uc_buffer_t*))
+{
+    if (arm_uc_registered_certificate_api == NULL ||
+        arm_uc_registered_certificate_api->fetch == NULL)
+    {
+        return (arm_uc_error_t){ARM_UC_CM_ERR_INVALID_PARAMETER};
+    }
+
+    return arm_uc_registered_certificate_api->fetch(certificate, fingerprint, DERCertificateList, callback);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/source/arm_uc_certificate_cfstore_api.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,108 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// -----------------------------------------------------------------------------
+
+#include "update-client-control-center/arm_uc_certificate.h"
+#include "update-client-common/arm_uc_config.h"
+
+#ifndef ARM_UC_USE_CFSTORE
+#define ARM_UC_USE_CFSTORE 0
+#endif
+
+#if ARM_UC_USE_CFSTORE
+
+#include <string.h>
+
+static const uint8_t* arm_uc_certificate = NULL;
+static uint16_t arm_uc_certificate_size = 0;
+static const uint8_t* arm_uc_fingerprint = NULL;
+static uint16_t arm_uc_fingerprint_size = 0;
+
+static arm_uc_error_t arm_uc_cfstore_cert_storer(const arm_uc_buffer_t* cert,
+                                                 const arm_uc_buffer_t* fingerprint,
+                                                 void (*callback)(arm_uc_error_t, const arm_uc_buffer_t*))
+{
+    if (cert == NULL ||
+        cert->ptr == NULL ||
+        fingerprint == NULL ||
+        fingerprint->ptr == NULL)
+    {
+        return (arm_uc_error_t){ARM_UC_CM_ERR_INVALID_PARAMETER};
+    }
+    if (cert->size == 0 || fingerprint->size == 0)
+    {
+        return (arm_uc_error_t){ARM_UC_CM_ERR_INVALID_PARAMETER};
+    }
+
+    arm_uc_error_t err = (arm_uc_error_t){ARM_UC_CM_ERR_NONE};
+
+         arm_uc_certificate = cert->ptr;
+    arm_uc_certificate_size = cert->size;
+         arm_uc_fingerprint = fingerprint->ptr;
+    arm_uc_fingerprint_size = fingerprint->size;
+
+    if (err.code == ARM_UC_CM_ERR_NONE && callback)
+    {
+        callback(err, fingerprint);
+    }
+
+    return err;
+}
+
+static arm_uc_error_t arm_uc_cfstore_cert_fetcher(arm_uc_buffer_t* certificate,
+    const arm_uc_buffer_t* fingerprint,
+    const arm_uc_buffer_t* DERCertificateList,
+    void (*callback)(arm_uc_error_t, const arm_uc_buffer_t*, const arm_uc_buffer_t*))
+{
+    arm_uc_error_t err = {ARM_UC_CM_ERR_INVALID_PARAMETER};
+
+    if (fingerprint->size != arm_uc_fingerprint_size)
+    {
+        err.code = ARM_UC_CM_ERR_NOT_FOUND;
+    }
+    else if (fingerprint       != NULL &&
+             fingerprint->ptr  != NULL &&
+             fingerprint->size == arm_uc_fingerprint_size &&
+             certificate       != NULL)
+    {
+        if (0 == memcmp(fingerprint->ptr, arm_uc_fingerprint, arm_uc_fingerprint_size))
+        {
+            err.code              = ARM_UC_CM_ERR_NONE;
+            certificate->ptr      = (uint8_t*) arm_uc_certificate;
+            certificate->size     = arm_uc_certificate_size;
+            certificate->size_max = arm_uc_certificate_size;
+        }
+        else
+        {
+            err.code = ARM_UC_CM_ERR_NOT_FOUND;
+        }
+    }
+
+    if (err.error == ERR_NONE && callback)
+    {
+        callback(err, certificate, fingerprint);
+    }
+
+    return err;
+}
+
+const struct arm_uc_certificate_api arm_uc_certificate_cfstore_api = {
+    .fetch = arm_uc_cfstore_cert_fetcher,
+    .store = arm_uc_cfstore_cert_storer,
+};
+
+#endif // ARM_UC_USE_KCM
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/source/arm_uc_certificate_kcm_api.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,197 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-control-center/arm_uc_certificate.h"
+#include "update-client-common/arm_uc_config.h"
+#include "update-client-common/arm_uc_crypto.h"
+
+#ifndef ARM_UC_USE_KCM
+#define ARM_UC_USE_KCM 0
+#endif
+
+#if ARM_UC_USE_KCM
+
+#include "key-config-manager/key_config_manager.h"
+
+static arm_uc_error_t kerr2ucerr(int kerr)
+{
+    arm_uc_error_t err;
+    switch(kerr)
+    {
+        case KCM_STATUS_SUCCESS:
+            err.code = ARM_UC_CM_ERR_NONE;
+            break;
+        case KCM_STATUS_INVALID_PARAMETER:
+            err.code = ARM_UC_CM_ERR_INVALID_PARAMETER;
+            break;
+        case KCM_STATUS_ITEM_NOT_FOUND:
+        case KCM_STATUS_ESFS_ERROR:
+            err.code = ARM_UC_CM_ERR_NOT_FOUND;
+            break;
+        case KCM_CRYPTO_STATUS_PARSING_DER_CERT:
+            err.code = ARM_UC_CM_ERR_INVALID_CERT;
+            break;
+        case KCM_STATUS_OUT_OF_MEMORY:
+        case KCM_STATUS_INSUFFICIENT_BUFFER:
+        default:
+            err.modulecc[0] = 'K';
+            err.modulecc[1] = 'C';
+            err.error       = kerr;
+            break;
+    }
+    return err;
+}
+
+static arm_uc_error_t arm_uc_kcm_cert_fetcher(arm_uc_buffer_t* certificate,
+    const arm_uc_buffer_t* fingerprint,
+    const arm_uc_buffer_t* DERCertificateList,
+    void (*callback)(arm_uc_error_t, const arm_uc_buffer_t*, const arm_uc_buffer_t*))
+{
+    uint8_t certName[MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE] = MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT;
+    // uint8_t certName[MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE] = MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX;
+    // uint8_t* b64hash = &certName[sizeof(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX)-1];
+    // uint8_t defaultInUse = 0;
+
+    UC_CONT_TRACE("Attempting to fetch certificate from: %s", certName);
+    // Format the certificate name into the certName buffer
+    // ARM_UC_Base64Enc(b64hash, sizeof(b64hash), fingerprint);
+
+    // The arm_uc_buffer_t's size variable is 32bit, but kcm_item_get_data() needs
+    // a pointer to size_t, so we need to use a temp variable for it or we would get
+    // a corrupted arm_uc_buffer_t structure.
+    size_t cert_data_size = 0;
+
+    // Look up the certificate by fingerprint
+    kcm_status_e kerr = kcm_item_get_data(certName,
+                                          strlen((char*)certName),
+                                          KCM_CERTIFICATE_ITEM,
+                                          certificate->ptr,
+                                          certificate->size_max,
+                                          &cert_data_size);
+
+    // Check if the certificate was found.
+    // if (kerr == KCM_STATUS_ITEM_NOT_FOUND || kerr == KCM_STATUS_ESFS_ERROR)
+    // {
+    //     printf("fingerprinted certificate not found. Checking for default...\n");
+    //     // If not, try the default location.
+    //     kerr = kcm_item_get_data(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT,
+    //                              sizeof(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT) - 1,
+    //                              KCM_CERTIFICATE_ITEM,
+    //                              certificate->ptr,
+    //                              certificate->size_max,
+    //                              &cert_data_size);
+    //     defaultInUse = 1;
+    // }
+    // Translate the KCM error to an update client error
+    arm_uc_error_t err = kerr2ucerr(kerr);
+    arm_uc_error_t errFinish = {ARM_UC_CM_ERR_INVALID_PARAMETER};
+
+    // Prepare to calculate the fingerprint of the certificate.
+    arm_uc_mdHandle_t h = { 0 };
+    uint8_t fingerprintLocal[MBED_CLOUD_SHA256_BYTES];
+    arm_uc_buffer_t fingerprintLocalBuffer = {
+        .size_max = sizeof(fingerprintLocal),
+        .size = 0,
+        .ptr = fingerprintLocal};
+
+    // Check for overflow before continuing. This is actually unnecessary
+    // belts and suspenders type of code, as the max value given to kcm_item_get_data()
+    // is at most UINT32_MAX, but the Coverity might point this as a error.
+    if (cert_data_size <= UINT32_MAX)
+    {
+        certificate->size = (uint32_t)cert_data_size;
+    }
+    else
+    {
+        err.code = ARM_UC_CM_ERR_INVALID_CERT;
+    }
+
+    // Calculate the fingerprint of the certificate
+    if (err.error == ERR_NONE)
+    {
+        err = ARM_UC_cryptoHashSetup(&h, ARM_UC_CU_SHA256);
+    }
+    if (err.error == ERR_NONE)
+    {
+        err = ARM_UC_cryptoHashUpdate(&h, certificate);
+
+        // The cryptoHashFinish needs to be called no matter if the update succeeded or not as
+        // it will do memory freeing. But in order to have valid result, the update & finish
+        // must both have succeeded.
+        errFinish = ARM_UC_cryptoHashFinish(&h, &fingerprintLocalBuffer);
+
+        // Compare the calculated fingerprint to the requested fingerprint.
+        if ((err.error == ERR_NONE) && (errFinish.error == ERR_NONE))
+        {
+            uint32_t rc = ARM_UC_BinCompareCT(fingerprint, &fingerprintLocalBuffer);
+            if (rc)
+            {
+                err.code = ARM_UC_CM_ERR_NOT_FOUND;
+            }
+            else
+            {
+                UC_CONT_TRACE("Certificate lookup fingerprint matched.");
+                err.code = ARM_UC_CM_ERR_NONE;
+            }
+
+            if (callback && (err.error == ERR_NONE))
+            {
+                callback(err, certificate, fingerprint);
+            }
+        }
+    }
+
+    return err;
+}
+
+static arm_uc_error_t arm_uc_kcm_cert_storer(
+    const arm_uc_buffer_t* cert,
+    const arm_uc_buffer_t* fingerprint,
+    void(*callback)(arm_uc_error_t, const arm_uc_buffer_t*))
+{
+    // uint8_t certName[MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE] = MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX;
+    // uint8_t* b64hash = &certName[sizeof(MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_PREFIX)-1];
+    uint8_t certName[MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_NAME_SIZE] = MBED_CLOUD_CLIENT_UPDATE_CERTIFICATE_DEFAULT;
+
+    UC_CONT_TRACE("Storing certificate to: %s\n", certName);
+    // ARM_UC_Base64Enc(b64hash, sizeof(b64hash), fingerprint);
+
+    kcm_status_e kerr = kcm_item_store(certName,
+                                       strlen((char*) certName),
+                                       KCM_CERTIFICATE_ITEM,
+                                       true,
+                                       cert->ptr,
+                                       cert->size,
+                                       NULL);
+
+    arm_uc_error_t err = kerr2ucerr(kerr);
+
+    if (callback && (err.code == ARM_UC_CM_ERR_NONE))
+    {
+        callback(err, fingerprint);
+    }
+
+    return err;
+}
+
+const struct arm_uc_certificate_api arm_uc_certificate_kcm_api = {
+    .fetch = arm_uc_kcm_cert_fetcher,
+    .store = arm_uc_kcm_cert_storer
+};
+
+#endif // ARM_UC_USE_KCM
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/source/arm_uc_control_center.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,419 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-control-center/arm_uc_control_center.h"
+
+#include <stdbool.h>
+
+/* event handler */
+static void (*arm_uccc_event_handler)(uint32_t) = NULL;
+static arm_uc_callback_t arm_uccc_authorize_callback = { 0 };
+static arm_uc_callback_t arm_uccc_monitor_callback = { 0 };
+
+/* authorization callback */
+static void (*arm_uc_authority_callback)(int32_t) = NULL;
+static bool arm_uc_download_token_armed = false;
+static bool arm_uc_install_token_armed = false;
+
+/* force authorization */
+static arm_uc_callback_t arm_uccc_override_callback = { 0 };
+
+static void arm_uccc_override_task(uint32_t unused);
+
+/* progress callback */
+static void (*arm_uc_progress_callback)(uint32_t, uint32_t) = NULL;
+
+/* function pointer structs */
+static const ARM_UPDATE_MONITOR* arm_uc_monitor_struct = NULL;
+
+static void ARM_UC_ControlCenter_Notification_Handler(void)
+{
+    if (arm_uccc_event_handler)
+    {
+        ARM_UC_PostCallback(&arm_uccc_monitor_callback,
+                            arm_uccc_event_handler,
+                            ARM_UCCC_EVENT_MONITOR_SEND_DONE);
+    }
+}
+
+/**
+ * @brief Initialize Control Center.
+ *
+ * @param callback Event handler to signal authorizations.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_Initialize(void (*callback)(uint32_t))
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_Initialize: %p", callback);
+
+    arm_uccc_event_handler = callback;
+
+    return (arm_uc_error_t){ ERR_NONE };
+}
+
+/**
+ * @brief Add monitor struct for sending status and results remotely.
+ *
+ * @param monitor Pointer to an ARM_UPDATE_MONITOR struct.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_AddMonitor(const ARM_UPDATE_MONITOR* monitor)
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_AddMonitor: %p", monitor);
+
+    arm_uc_error_t result = (arm_uc_error_t){ ERR_INVALID_PARAMETER };
+
+    arm_uc_monitor_struct = monitor;
+
+    if (arm_uc_monitor_struct)
+    {
+        result = arm_uc_monitor_struct->Initialize(ARM_UC_ControlCenter_Notification_Handler);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set callback for receiving download progress.
+ * @details User application call for setting callback handler.
+ *          The callback function takes the progreess in percent as argument.
+ *
+ * @param callback Function pointer to the progress function.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_SetProgressHandler(void (*callback)(uint32_t progress, uint32_t total))
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_SetProgressHandler: %p", callback);
+
+    arm_uc_progress_callback = callback;
+
+    return (arm_uc_error_t){ ERR_NONE };
+}
+
+/**
+ * @brief Set callback function for authorizing requests.
+ * @details The callback function takes an enum request and an authorization
+ *          function pointer. To authorize the given request, the caller
+ *          invokes the authorization function.
+ *
+ * @param callback Function pointer to the authorization function.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_SetAuthorityHandler(void (*callback)(int32_t))
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_SetAuthorityHandler: %p", callback);
+
+    arm_uc_authority_callback = callback;
+
+    return (arm_uc_error_t){ ERR_NONE };
+}
+
+/**
+ * @brief Request authorization from Control Center.
+ *
+ * @param type Request type.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_GetAuthorization(arm_uc_request_t request)
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_GetAuthorization: %d", (int) request);
+
+    arm_uc_error_t result = (arm_uc_error_t){ ERR_INVALID_PARAMETER };
+
+    switch (request)
+    {
+        case ARM_UCCC_REQUEST_DOWNLOAD:
+            /* Arm callback token */
+            arm_uc_download_token_armed = true;
+
+            if (arm_uc_authority_callback)
+            {
+                arm_uc_authority_callback(ARM_UCCC_REQUEST_DOWNLOAD);
+            }
+            else
+            {
+                ARM_UC_ControlCenter_Authorize(ARM_UCCC_REQUEST_DOWNLOAD);
+            }
+            result.code = ERR_NONE;
+            break;
+
+        case ARM_UCCC_REQUEST_INSTALL:
+            /* Arm callback token */
+            arm_uc_install_token_armed = true;
+
+            if (arm_uc_authority_callback)
+            {
+                arm_uc_authority_callback(ARM_UCCC_REQUEST_INSTALL);
+            }
+            else
+            {
+                ARM_UC_ControlCenter_Authorize(ARM_UCCC_REQUEST_INSTALL);
+            }
+            result.code = ERR_NONE;
+            break;
+        default:
+            break;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Authorize request.
+ *
+ * @param request Request type. Must match the type in callback function.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_Authorize(arm_uc_request_t request)
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_Authorize: %d", (int) request);
+
+    arm_uc_error_t result = (arm_uc_error_t){ ERR_INVALID_PARAMETER };
+
+    switch (request)
+    {
+        case ARM_UCCC_REQUEST_DOWNLOAD:
+            if (arm_uccc_event_handler && arm_uc_download_token_armed)
+            {
+                arm_uc_download_token_armed = false;
+
+                ARM_UC_PostCallback(&arm_uccc_authorize_callback,
+                                    arm_uccc_event_handler,
+                                    ARM_UCCC_EVENT_AUTHORIZE_DOWNLOAD);
+
+                result.code = ERR_NONE;
+            }
+            break;
+
+        case ARM_UCCC_REQUEST_INSTALL:
+            if (arm_uccc_event_handler && arm_uc_install_token_armed)
+            {
+                arm_uc_install_token_armed = false;
+
+                ARM_UC_PostCallback(&arm_uccc_authorize_callback,
+                                    arm_uccc_event_handler,
+                                    ARM_UCCC_EVENT_AUTHORIZE_INSTALL);
+
+                result.code = ERR_NONE;
+            }
+            break;
+
+        default:
+            break;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Override update authorization handler.
+ * @details Force download and update to progress regardless of authorization
+ *          handler. This function is used for unblocking an update in a buggy
+ *          application.
+ */
+void ARM_UC_ControlCenter_OverrideAuthorization(void)
+{
+    ARM_UC_PostCallback(&arm_uccc_override_callback,
+                        arm_uccc_override_task,
+                        0);
+}
+
+static void arm_uccc_override_task(uint32_t unused)
+{
+    (void) unused;
+
+    UC_CONT_TRACE("arm_uccc_override_task");
+
+    if (arm_uc_download_token_armed)
+    {
+        arm_uc_download_token_armed = false;
+
+        /* force authorization */
+        if (arm_uccc_event_handler)
+        {
+            arm_uccc_event_handler(ARM_UCCC_EVENT_AUTHORIZE_DOWNLOAD);
+        }
+    }
+    else if (arm_uc_install_token_armed)
+    {
+        arm_uc_install_token_armed = false;
+
+        /* force authorization */
+        if (arm_uccc_event_handler)
+        {
+            arm_uccc_event_handler(ARM_UCCC_EVENT_AUTHORIZE_INSTALL);
+        }
+    }
+
+    /* disable authorization function */
+    arm_uc_authority_callback = NULL;
+}
+
+/**
+ * @brief Report download progress.
+ * @details Update Client call for informing the Control Center about the
+ *          current download progress. The Control Center will send this to the
+ *          appication handler and the monitor if either/both are attached.
+ *
+ * @param progrss Bytes already downloaded.
+ * @param total Total amount of bytes in download.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportProgress(uint32_t progress, uint32_t total)
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_ReportProgress: %" PRIu32 " / %" PRIu32, progress, total);
+
+    /* only forward request if callback is set. */
+    if (arm_uc_progress_callback)
+    {
+        arm_uc_progress_callback(progress, total);
+    }
+
+    return (arm_uc_error_t){ ERR_NONE };
+}
+
+/**
+ * @brief Send Update Client state.
+ * @param state Update Client state.
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportState(arm_uc_monitor_state_t state)
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_ReportState: %d", (int) state);
+
+    arm_uc_error_t result = (arm_uc_error_t){ ERR_INVALID_PARAMETER };
+
+    if (arm_uc_monitor_struct)
+    {
+        arm_uc_monitor_struct->SendState(state);
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set update result.
+ * @param result Update result.
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportUpdateResult(arm_uc_monitor_result_t updateResult)
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_ReportUpdateResult: %d", (int) updateResult);
+
+    arm_uc_error_t result = (arm_uc_error_t){ ERR_INVALID_PARAMETER };
+
+    if (arm_uc_monitor_struct)
+    {
+        arm_uc_monitor_struct->SendUpdateResult(updateResult);
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set current firmware name.
+ * @details Update Client call for informing the Control Center about the
+ *          current firmware name. The Control Center will send this to the
+ *          monitor. The firmware name is the SHA256 hash.
+ *
+ * @param name Pointer to buffer struct. Hash is stored as byte array.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportName(arm_uc_buffer_t* name)
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_ReportName: %p", name);
+
+    arm_uc_error_t result = (arm_uc_error_t){ ERR_INVALID_PARAMETER };
+
+    if (arm_uc_monitor_struct)
+    {
+        arm_uc_monitor_struct->SendName(name);
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set current firmware version.
+ * @details The firmware version is the SHA256 hash.
+ *
+ * @param version Pointer to buffer struct. Hash is stored as byte array.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportVersion(uint64_t version)
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_ReportVersion: %llu", version);
+
+    arm_uc_error_t result = (arm_uc_error_t){ ERR_INVALID_PARAMETER };
+
+    if (arm_uc_monitor_struct)
+    {
+        arm_uc_monitor_struct->SendVersion(version);
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Send bootloader hash to monitor.
+ * @details The bootloader hash is a hash of the bootloader. This is
+ *          used for tracking the version of the bootloader used.
+ *
+ * @param name Pointer to buffer struct. Hash is stored as byte array.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportBootloaderHash(arm_uc_buffer_t* hash)
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_ReportBootloaderHash");
+
+    arm_uc_error_t result = (arm_uc_error_t){ ERR_INVALID_PARAMETER };
+
+    if (arm_uc_monitor_struct && arm_uc_monitor_struct->SetBootloaderHash)
+    {
+        result = arm_uc_monitor_struct->SetBootloaderHash(hash);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Send the OEM bootloader hash to monitor.
+ * @details If the end-user has modified the bootloader the hash of the
+ *          modified bootloader can be set here.
+ *
+ * @param name Pointer to buffer struct. Hash is stored as byte array.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportOEMBootloaderHash(arm_uc_buffer_t* hash)
+{
+    UC_CONT_TRACE("ARM_UC_ControlCenter_ReportOEMBootloaderHash");
+
+    arm_uc_error_t result = (arm_uc_error_t){ ERR_INVALID_PARAMETER };
+
+    if (arm_uc_monitor_struct && arm_uc_monitor_struct->SetOEMBootloaderHash)
+    {
+        result = arm_uc_monitor_struct->SetOEMBootloaderHash(hash);
+    }
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/source/arm_uc_pre_shared_key.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,74 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-control-center/arm_uc_pre_shared_key.h"
+
+/* Pointer to the pre-shared-key. Module only supports 1 key at a time. */
+static const uint8_t* arm_uc_psk_key = NULL;
+static uint16_t arm_uc_psk_size = 0;
+
+/**
+ * @brief Register event handler.
+ *
+ * @param callback Event handler to signal result.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_PreSharedKey_Initialize(void (*callback)(uint32_t))
+{
+    return (arm_uc_error_t){ ERR_NONE};
+}
+
+/**
+ * @brief Set pointer to pre-shared-key with the given size.
+ *
+ * @param key Pointer to pre-shared-key.
+ * @param bits Key size in bits.
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_PreSharedKey_SetKey(const uint8_t* key, uint16_t bits)
+{
+    arm_uc_psk_key = key;
+    arm_uc_psk_size = bits;
+
+    return (arm_uc_error_t){ ERR_NONE};
+}
+
+/**
+ * @brief Get pointer to pre-shared-key with the given size.
+ *
+ * @param key Pointer-pointer to the shared key.
+ * @param bits Key size in bits.
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_PreSharedKey_GetKey(const uint8_t** key, uint16_t bits)
+{
+    arm_uc_error_t retval = (arm_uc_error_t){ ERR_INVALID_PARAMETER };
+
+    if (key && (bits == arm_uc_psk_size))
+    {
+        /* set return value */
+        retval = (arm_uc_error_t){ ERR_NONE };
+
+        /* assign PSK pointer */
+        *key = arm_uc_psk_key;
+    }
+
+    return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/update-client-control-center/arm_uc_certificate.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,82 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_CERTIFICATES_H
+#define ARM_UPDATE_CERTIFICATES_H
+
+#include "update-client-common/arm_uc_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Add certificate.
+ * @details [long description]
+ *
+ * @param certificate Pointer to certiface being added.
+ * @param certificate_length Certificate length.
+ * @param fingerprint Pointer to the fingerprint of the certificate being added.
+ * @param fingerprint_length Fingerprint length.
+ * @return Error code.
+ */
+ arm_uc_error_t ARM_UC_Certificate_Add(const uint8_t* certificate,
+                                       uint16_t certificate_size,
+                                       const uint8_t* fingerprint,
+                                       uint16_t fingerprint_size,
+                                       void (*callback)(arm_uc_error_t, const arm_uc_buffer_t*));
+
+typedef arm_uc_error_t (* arm_uc_certificateStorer)(const arm_uc_buffer_t* certificate,
+                                                    const arm_uc_buffer_t* fingerprint,
+                                                    void (*callback)(arm_uc_error_t, const arm_uc_buffer_t*));
+
+/**
+ * @brief Fetch a certificate by fingerprint
+ * @details This API is registered with the hub by the application. The application must handle any required certificate
+ * chain validation. The API for parsing a certificate chain will be provided by the manifest manager, but the API
+ * is TBD, so the DERCertificateList should be ignored for now.
+ *
+ * @param[out] certificates A pointer to the buffer to populate with the certificate. The buffer's ptr should be updated
+ *                          to point to the certificate.
+ * @param[in] fingerprint The fingerprint of the certificate
+ * @param[in] DERCertificateList The encoded list of certificate fingerprint/URL pairs that define the chain of
+ *                               certificates used to verify the requested certificate (The requested certificate will
+ *                               always be the first in the list)
+ * @param[in] callback The function to call when the certificate is available
+ */
+typedef arm_uc_error_t (*arm_uc_certificateFetcher)(arm_uc_buffer_t* certificate,
+    const arm_uc_buffer_t* fingerprint,
+    const arm_uc_buffer_t* DERCertificateList,
+    void (*callback)(arm_uc_error_t, const arm_uc_buffer_t*, const arm_uc_buffer_t*));
+
+
+struct arm_uc_certificate_api {
+    arm_uc_certificateFetcher fetch;
+    arm_uc_certificateStorer  store;
+};
+
+arm_uc_error_t ARM_UC_certificateFetch(arm_uc_buffer_t* certificate,
+    const arm_uc_buffer_t* fingerprint,
+    const arm_uc_buffer_t* DERCertificateList,
+    void (*callback)(arm_uc_error_t, const arm_uc_buffer_t*, const arm_uc_buffer_t*));
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ARM_UPDATE_CERTIFICATES_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/update-client-control-center/arm_uc_control_center.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,228 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_CONTROL_CENTER_H
+#define ARM_UPDATE_CONTROL_CENTER_H
+
+#include "update-client-monitor/arm_uc_monitor.h"
+#include "update-client-common/arm_uc_common.h"
+
+#include <stdint.h>
+
+typedef enum {
+    ARM_UCCC_EVENT_AUTHORIZE_DOWNLOAD,
+    ARM_UCCC_EVENT_AUTHORIZE_INSTALL,
+    ARM_UCCC_EVENT_MONITOR_SEND_DONE,
+} arm_uc_contro_center_event_t;
+
+/**
+ * @brief Initialize Control Center.
+ *
+ * @param callback Event handler to signal authorizations.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_Initialize(void (*callback)(uint32_t));
+
+/**
+ * @brief Add monitor struct for sending status and results remotely.
+ * @details Update Client call for adding remote monitor.
+ *
+ * @param monitor Pointer to an ARM_UPDATE_MONITOR struct.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_AddMonitor(const ARM_UPDATE_MONITOR* monitor);
+
+/**
+ * @brief Set callback for receiving download progress.
+ * @details User application call for setting callback handler.
+ *          The callback function takes the progreess in percent as argument.
+ *
+ * @param callback Function pointer to the progress function.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_SetProgressHandler(void (*callback)(uint32_t progress, uint32_t total));
+
+/**
+ * @brief Set callback function for authorizing requests.
+ * @details User application call for setting callback handler.
+ *          The callback function takes an enum request and an authorization
+ *          function pointer. To authorize the given request, the caller
+ *          invokes the authorization function.
+ *
+ * @param callback Function pointer to the authorization function.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_SetAuthorityHandler(void (*callback)(int32_t));
+
+/**
+ * @brief Request authorization from Control Center.
+ * @details Update Client call for asking user application for permission.
+ *
+ * @param type Request type.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_GetAuthorization(arm_uc_request_t request);
+
+/**
+ * @brief Authorize request.
+ * @details User application call for authorizing request.
+ *
+ * @param request Request type. Must match the type in callback function.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_Authorize(arm_uc_request_t request);
+
+/**
+ * @brief Override update authorization handler.
+ * @details Force download and update to progress regardless of authorization
+ *          handler. This function is used for unblocking an update in a buggy
+ *          application.
+ */
+void ARM_UC_ControlCenter_OverrideAuthorization(void);
+
+/**
+ * @brief Report download progress.
+ * @details Update Client call for informing the Control Center about the
+ *          current download progress. The Control Center will send this to the
+ *          appication handler and the monitor if either/both are attached.
+ *
+ * @param progress Bytes already downloaded.
+ * @param total Total bytes in download.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportProgress(uint32_t progress, uint32_t total);
+
+/**
+ * @brief Send Update Client state.
+ * @details Update Client call for informing the Control Center about the
+ *          current state. The Control Center will send this to the monitor.
+ *
+ *          From the OMA LWM2M Technical Specification:
+ *
+ *          Indicates current state with respect to this firmware update.
+ *          This value is set by the LWM2M Client.
+ *          0: Idle (before downloading or after successful updating)
+ *          1: Downloading (The data sequence is on the way)
+ *          2: Downloaded
+ *          3: Updating
+ *
+ *          If writing the firmware package to Package Resource is done,
+ *          or, if the device has downloaded the firmware package from the
+ *          Package URI the state changes to Downloaded.
+ *
+ *          If writing an empty string to Package Resource is done or
+ *          writing an empty string to Package URI is done, the state
+ *          changes to Idle.
+ *
+ *          When in Downloaded state, and the executable Resource Update is
+ *          triggered, the state changes to Updating.
+ *          If the Update Resource failed, the state returns at Downloaded.
+ *          If performing the Update Resource was successful, the state
+ *          changes from Updating to Idle.
+ *
+ * @param state Valid states: ARM_UC_MONITOR_STATE_IDLE
+ *                            ARM_UC_MONITOR_STATE_DOWNLOADING
+ *                            ARM_UC_MONITOR_STATE_DOWNLOADED
+ *                            ARM_UC_MONITOR_STATE_UPDATING
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportState(arm_uc_monitor_state_t state);
+
+/**
+ * @brief Set update result.
+ * @details Update Client call for informing the Control Center about the
+ *          latest update result. The Control Center will send this to the monitor.
+ *
+ *          From the OMA LWM2M Technical Specification:
+ *
+ *          Contains the result of downloading or updating the firmware
+ *          0: Initial value. Once the updating process is initiated
+ *             (Download /Update), this Resource MUST be reset to Initial
+ *             value.
+ *          1: Firmware updated successfully,
+ *          2: Not enough storage for the new firmware package.
+ *          3. Out of memory during downloading process.
+ *          4: Connection lost during downloading process.
+ *          5: CRC check failure for new downloaded package.
+ *          6: Unsupported package type.
+ *          7: Invalid URI
+ *          8: Firmware update failed
+ *
+ *          This Resource MAY be reported by sending Observe operation.
+ *
+ * @param result Valid results: ARM_UC_MONITOR_RESULT_INITIAL
+ *                              ARM_UC_MONITOR_RESULT_SUCCESS
+ *                              ARM_UC_MONITOR_RESULT_ERROR_STORAGE
+ *                              ARM_UC_MONITOR_RESULT_ERROR_MEMORY
+ *                              ARM_UC_MONITOR_RESULT_ERROR_CONNECTION
+ *                              ARM_UC_MONITOR_RESULT_ERROR_CRC
+ *                              ARM_UC_MONITOR_RESULT_ERROR_TYPE
+ *                              ARM_UC_MONITOR_RESULT_ERROR_URI
+ *                              ARM_UC_MONITOR_RESULT_ERROR_UPDATE
+ *                              ARM_UC_MONITOR_RESULT_ERROR_HASH
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportUpdateResult(arm_uc_monitor_result_t updateResult);
+
+/**
+ * @brief Set current firmware name.
+ * @details Update Client call for informing the Control Center about the
+ *          current firmware name. The Control Center will send this to the
+ *          monitor. The firmware name is the SHA256 hash.
+ *
+ * @param name Pointer to buffer struct. Hash is stored as byte array.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportName(arm_uc_buffer_t* name);
+
+/**
+ * @brief Set current firmware version.
+ * @details Update Client call for informing the Control Center about the
+ *          current firmware version. The Control Center will send this to the
+ *          monitor. The firmware version is the manifest timestamp that
+ *          authorized the installation.
+ *
+ * @param version Timestamp, 64 bit unsigned integer.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportVersion(uint64_t version);
+
+/**
+ * @brief Send bootloader hash to monitor.
+ * @details The bootloader hash is a hash of the bootloader. This is
+ *          used for tracking the version of the bootloader used.
+ *
+ * @param name Pointer to buffer struct. Hash is stored as byte array.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportBootloaderHash(arm_uc_buffer_t* hash);
+
+/**
+ * @brief Send the OEM bootloader hash to monitor.
+ * @details If the end-user has modified the bootloader the hash of the
+ *          modified bootloader can be set here.
+ *
+ * @param name Pointer to buffer struct. Hash is stored as byte array.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_ControlCenter_ReportOEMBootloaderHash(arm_uc_buffer_t* hash);
+
+#endif // __ARM_UPDATE_CONTROL_CENTER_H__
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/control-center/update-client-control-center/arm_uc_pre_shared_key.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,72 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PRE_SHARED_KEY_H
+#define ARM_UC_PRE_SHARED_KEY_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "update-client-common/arm_uc_common.h"
+
+#include <stdint.h>
+
+typedef enum {
+    ARM_UC_PSK_GET_DONE,
+    ARM_UC_PSK_GET_ERROR
+} arm_uc_psk_event_t;
+
+/**
+ * @brief Register event handler.
+ *
+ * @param callback Event handler to signal result.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_PreSharedKey_Initialize(void (*callback)(uint32_t));
+
+/**
+ * @brief Set pointer to pre-shared-key with the given size.
+ *
+ * @param key Pointer to pre-shared-key.
+ * @param bits Key size in bits.
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_PreSharedKey_SetKey(const uint8_t* key, uint16_t bits);
+
+/**
+ * @brief Get pointer to pre-shared-key with the given size.
+ * @details This call will generate an event upon completion because the key
+ *          pointing to might have to be loaded from asynchronous storage.
+ *
+ *          If the event is ARM_UC_PSK_GET_DONE, key will point to a valid
+ *          pre-shared-key, which memory is handled internally.
+ *
+ * @param key Pointer-pointer to the shared key.
+ * @param bits Key size in bits.
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_PreSharedKey_GetKey(const uint8_t** key, uint16_t bits);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ARM_UC_PRE_SHARED_KEY_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/device-identity/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+TESTS/tests/sanity/*
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/device-identity/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/device-identity/pal4life-device-identity/pal_device_identity.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,154 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef PAL4LIFE_DEVICE_IDENTITY_H
+#define PAL4LIFE_DEVICE_IDENTITY_H
+
+#include "update-client-common/arm_uc_common.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Function for setting the vendor GUID.
+ * @details The GUID is copied.
+ * @param vendor_guid Pointer to a arm_uc_guid_t GUID.
+ * @return Error code.
+ */
+arm_uc_error_t pal_setVendorGuid(const arm_uc_guid_t* vendor_guid);
+
+/**
+ * @brief Function for getting a pointer to the vendor GUID.
+ * @param vendor_guid Pointer to a arm_uc_guid_t pointer.
+ * @return Error code.
+ */
+arm_uc_error_t pal_getVendorGuid(arm_uc_guid_t* vendor_guid);
+
+/**
+ * @brief Function for setting the device class GUID.
+ * @details The GUID is copied.
+ * @param class_guid Pointer to a arm_uc_guid_t GUID.
+ * @return Error code.
+ */
+arm_uc_error_t pal_setClassGuid(const arm_uc_guid_t* class_guid);
+
+/**
+ * @brief Function for getting a pointer to the device class GUID.
+ * @param class_guid Pointer to a arm_uc_guid_t pointer.
+ * @return Error code.
+ */
+arm_uc_error_t pal_getClassGuid(arm_uc_guid_t* class_guid);
+
+/**
+ * @brief Function for setting the device GUID.
+ * @details The GUID is copied.
+ * @param device_guid Pointer to a arm_uc_guid_t GUID.
+ * @return Error code.
+ */
+arm_uc_error_t pal_setDeviceGuid(const arm_uc_guid_t* device_guid);
+
+/**
+ * @brief Function for getting a pointer to the device GUID.
+ * @param device_guid Pointer to a arm_uc_guid_t pointer.
+ * @return Error code.
+ */
+arm_uc_error_t pal_getDeviceGuid(arm_uc_guid_t* device_guid);
+
+/**
+ * @brief Check whether the three GUIDs provided are valid on the device.
+ * @details
+ * @param vendor_guid Buffer pointer to the Vendor GUID.
+ * @param class_guid  Buffer pointer to the device class GUID.
+ * @param device_guid Buffer pointer to the device GUID.
+ * @return Error code.
+ */
+arm_uc_error_t pal_deviceIdentityCheck(const arm_uc_buffer_t* vendor_guid,
+                                       const arm_uc_buffer_t* class_guid,
+                                       const arm_uc_buffer_t* device_guid);
+
+/**
+ * @brief Structure definition holding API function pointers.
+ */
+typedef struct _ARM_PAL_DEVICE_IDENTITY {
+    /**
+     * @brief Function for setting the vendor GUID.
+     * @details The GUID is copied.
+     * @param vendor_guid Pointer to a arm_uc_guid_t GUID.
+     * @return Error code.
+     */
+    arm_uc_error_t (*SetVendorGuid)(const arm_uc_guid_t* vendor_guid);
+
+    /**
+     * @brief Function for getting a pointer to the vendor GUID.
+     * @param vendor_guid Pointer to a arm_uc_guid_t pointer.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetVendorGuid)(arm_uc_guid_t* vendor_guid);
+
+    /**
+     * @brief Function for setting the device class GUID.
+     * @details The GUID is copied.
+     * @param class_guid Pointer to a arm_uc_guid_t GUID.
+     * @return Error code.
+     */
+    arm_uc_error_t (*SetClassGuid)(const arm_uc_guid_t* class_guid);
+
+    /**
+     * @brief Function for getting a pointer to the device class GUID.
+     * @param class_guid Pointer to a arm_uc_guid_t pointer.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetClassGuid)(arm_uc_guid_t* class_guid);
+
+    /**
+     * @brief Function for setting the device GUID.
+     * @details The GUID is copied.
+     * @param device_guid Pointer to a arm_uc_guid_t GUID.
+     * @return Error code.
+     */
+    arm_uc_error_t (*SetDeviceGuid)(const arm_uc_guid_t* device_guid);
+
+    /**
+     * @brief Function for getting a pointer to the device GUID.
+     * @param device_guid Pointer to a arm_uc_guid_t pointer.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetDeviceGuid)(arm_uc_guid_t* device_guid);
+
+    /**
+     * @brief Check whether the three GUIDs provided are valid on the device.
+     * @details
+     * @param vendor_guid Buffer pointer to the Vendor GUID.
+     * @param class_guid  Buffer pointer to the device class GUID.
+     * @param device_guid Buffer pointer to the device GUID.
+     * @return Error code.
+     */
+    arm_uc_error_t (*DeviceIdentityCheck)(const arm_uc_buffer_t* vendor_guid,
+                                          const arm_uc_buffer_t* class_guid,
+                                          const arm_uc_buffer_t* device_guid);
+} ARM_PAL_DEVICE_IDENTITY;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // PAL4LIFE_DEVICE_IDENTITY_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/device-identity/source/arm_uc_device_identity.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,161 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "pal4life-device-identity/pal_device_identity.h"
+#include "update-client-common/arm_uc_config.h"
+
+#if ARM_UC_USE_KCM
+extern const ARM_PAL_DEVICE_IDENTITY arm_uc_device_identity_kcm;
+static const ARM_PAL_DEVICE_IDENTITY* arm_uc_device_identity =
+    &arm_uc_device_identity_kcm;
+#elif ARM_UC_USE_CFSTORE
+extern const ARM_PAL_DEVICE_IDENTITY arm_uc_device_identity_cfstore;
+static const ARM_PAL_DEVICE_IDENTITY* arm_uc_device_identity =
+    &arm_uc_device_identity_cfstore;
+#else
+#error No configuration store set
+#endif
+
+/**
+ * @brief Function for setting the vendor GUID.
+ * @details The GUID is copied.
+ * @param vendor_guid Pointer to a arm_uc_guid_t GUID.
+ * @return Error code.
+ */
+arm_uc_error_t pal_setVendorGuid(const arm_uc_guid_t* vendor_guid)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (arm_uc_device_identity)
+    {
+        result = arm_uc_device_identity->SetVendorGuid(vendor_guid);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Function for getting a pointer to the vendor GUID.
+ * @param vendor_guid Pointer to a arm_uc_guid_t pointer.
+ * @return Error code.
+ */
+arm_uc_error_t pal_getVendorGuid(arm_uc_guid_t* vendor_guid)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (arm_uc_device_identity)
+    {
+        result = arm_uc_device_identity->GetVendorGuid(vendor_guid);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Function for setting the device class GUID.
+ * @details The GUID is copied.
+ * @param class_guid Pointer to a arm_uc_guid_t GUID.
+ * @return Error code.
+ */
+arm_uc_error_t pal_setClassGuid(const arm_uc_guid_t* class_guid)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (arm_uc_device_identity)
+    {
+        result = arm_uc_device_identity->SetClassGuid(class_guid);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Function for getting a pointer to the device class GUID.
+ * @param class_guid Pointer to a arm_uc_guid_t pointer.
+ * @return Error code.
+ */
+arm_uc_error_t pal_getClassGuid(arm_uc_guid_t* class_guid)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (arm_uc_device_identity)
+    {
+        result = arm_uc_device_identity->GetClassGuid(class_guid);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Function for setting the device GUID.
+ * @details The GUID is copied.
+ * @param device_guid Pointer to a arm_uc_guid_t GUID.
+ * @return Error code.
+ */
+arm_uc_error_t pal_setDeviceGuid(const arm_uc_guid_t* device_guid)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (arm_uc_device_identity)
+    {
+        result = arm_uc_device_identity->SetDeviceGuid(device_guid);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Function for getting a pointer to the device GUID.
+ * @param device_guid Pointer to a arm_uc_guid_t pointer.
+ * @return Error code.
+ */
+arm_uc_error_t pal_getDeviceGuid(arm_uc_guid_t* device_guid)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (arm_uc_device_identity)
+    {
+        result = arm_uc_device_identity->GetDeviceGuid(device_guid);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Check whether the three GUIDs provided are valid on the device.
+ * @details
+ * @param vendor_guid Buffer pointer to the Vendor GUID.
+ * @param class_guid  Buffer pointer to the device class GUID.
+ * @param device_guid Buffer pointer to the device GUID.
+ * @return Error code.
+ */
+arm_uc_error_t pal_deviceIdentityCheck(const arm_uc_buffer_t* vendor_guid,
+                                       const arm_uc_buffer_t* class_guid,
+                                       const arm_uc_buffer_t* device_guid)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (arm_uc_device_identity)
+    {
+        result = arm_uc_device_identity->DeviceIdentityCheck(vendor_guid,
+                                                       class_guid,
+                                                       device_guid);
+    }
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/device-identity/source/arm_uc_device_identity_cfstore.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,286 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "pal4life-device-identity/pal_device_identity.h"
+#include "update-client-common/arm_uc_config.h"
+
+#ifndef ARM_UC_USE_CFSTORE
+#define ARM_UC_USE_CFSTORE 0
+#endif
+
+#if ARM_UC_USE_CFSTORE
+
+#include <string.h>
+
+static arm_uc_guid_t arm_uc_vendor_guid = {0};
+static int arm_uc_vendor_guid_set = 0;
+static arm_uc_guid_t arm_uc_class_guid = {0};
+static int arm_uc_class_guid_set = 0;
+static arm_uc_guid_t arm_uc_device_guid = {0};
+static int arm_uc_device_guid_set = 0;
+
+/**
+ * @brief Function for setting the vendor GUID.
+ * @details The GUID is copied.
+ * @param guid Pointer to a arm_uc_guid_t GUID.
+ * @return Error code.
+ */
+arm_uc_error_t pal_cfstore_setVendorGuid(const arm_uc_guid_t* vendor_guid)
+{
+    arm_uc_error_t result = { .code = ERR_NONE };
+
+    if (vendor_guid)
+    {
+        memcpy(&arm_uc_vendor_guid, vendor_guid, sizeof(arm_uc_guid_t));
+        arm_uc_vendor_guid_set = 1;
+    }
+    else
+    {
+        memset(&arm_uc_vendor_guid, 0, sizeof(arm_uc_guid_t));
+        arm_uc_vendor_guid_set = 0;
+    }
+    return result;
+}
+
+/**
+ * @brief Function for getting a pointer to the vendor GUID.
+ * @param guid Pointer to a arm_uc_guid_t.
+ * @return Error code.
+ */
+arm_uc_error_t pal_cfstore_getVendorGuid(arm_uc_guid_t* vendor_guid)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (vendor_guid && arm_uc_vendor_guid_set)
+    {
+        result.code = ERR_NONE;
+        memcpy(vendor_guid, &arm_uc_vendor_guid, sizeof(arm_uc_guid_t));
+    }
+
+    return result;
+}
+
+/**
+ * @brief Function for setting the device class GUID.
+ * @details The GUID is copied/
+ * @param guid Pointer to a arm_uc_guid_t GUID.
+ * @return Error code.
+ */
+arm_uc_error_t pal_cfstore_setClassGuid(const arm_uc_guid_t* class_guid)
+{
+    arm_uc_error_t result = { .code = ERR_NONE };
+
+    if (class_guid)
+    {
+        memcpy(&arm_uc_class_guid, class_guid, sizeof(arm_uc_guid_t));
+        arm_uc_class_guid_set = 1;
+    }
+    else
+    {
+        memset(&arm_uc_class_guid, 0, sizeof(arm_uc_guid_t));
+        arm_uc_class_guid_set = 0;
+    }
+    return result;
+}
+
+/**
+ * @brief Function for getting a pointer to the device class GUID.
+ * @param guid Pointer to a arm_uc_guid_t.
+ * @return Error code.
+ */
+arm_uc_error_t pal_cfstore_getClassGuid(arm_uc_guid_t* class_guid)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (class_guid && arm_uc_class_guid_set)
+    {
+        result.code = ERR_NONE;
+        memcpy(class_guid, &arm_uc_class_guid, sizeof(arm_uc_guid_t));
+    }
+
+    return result;
+}
+
+/**
+ * @brief Function for setting the device GUID.
+ * @details The GUID is copied.
+ * @param guid Pointer to a arm_uc_guid_t GUID.
+ * @return Error code.
+ */
+arm_uc_error_t pal_cfstore_setDeviceGuid(const arm_uc_guid_t* device_guid)
+{
+    arm_uc_error_t result = { .code = ERR_NONE };
+
+    if (device_guid)
+    {
+        memcpy(&arm_uc_device_guid, device_guid, sizeof(arm_uc_guid_t));
+        arm_uc_device_guid_set = 1;
+    }
+    else
+    {
+        memset(&arm_uc_device_guid, 0, sizeof(arm_uc_guid_t));
+        arm_uc_device_guid_set = 0;
+    }
+    return result;
+}
+
+/**
+ * @brief Function for getting a pointer to the device GUID.
+ * @param guid Pointer to a arm_uc_guid_t.
+ * @return Error code.
+ */
+arm_uc_error_t pal_cfstore_getDeviceGuid(arm_uc_guid_t* device_guid)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (device_guid && arm_uc_device_guid_set)
+    {
+        result.code = ERR_NONE;
+        memcpy(device_guid, &arm_uc_device_guid, sizeof(arm_uc_guid_t));
+    }
+
+    return result;
+}
+
+static bool pal_cfstore_internal_compare(const arm_uc_guid_t* guid,
+                                         const arm_uc_buffer_t* buffer)
+{
+    // count how many bytes match
+    uint8_t index = 0;
+
+    if (guid && buffer)
+    {
+        for ( ; (index < sizeof(arm_uc_guid_t)) && (index < buffer->size); index++)
+        {
+            if (((const uint8_t*) guid)[index] != buffer->ptr[index])
+            {
+                break;
+            }
+        }
+    }
+
+    // return true if all bytes matched
+    return (index == sizeof(arm_uc_guid_t));
+}
+
+/**
+ * @brief Check whether the three GUIDs provided are valid on the device.
+ * @details
+ * @param vendor_buffer Buffer pointer to the Vendor GUID.
+ * @param class_buffer  Buffer pointer to the device class GUID.
+ * @param device_buffer Buffer pointer to the device GUID.
+ * @param isValid     Pointer to the boolean return value.
+ * @return Error code.
+ */
+arm_uc_error_t pal_cfstore_deviceIdentityCheck(const arm_uc_buffer_t* vendor_buffer,
+                                               const arm_uc_buffer_t* class_buffer,
+                                               const arm_uc_buffer_t* device_buffer)
+{
+    arm_uc_error_t result = { .code = MFST_ERR_NULL_PTR };
+
+    uint8_t parameters_set = 0;
+    uint8_t parameters_ok = 0;
+
+    /* check device - device is optional */
+    if (arm_uc_device_guid_set)
+    {
+        if (device_buffer && device_buffer->ptr)
+        {
+            bool is_same = pal_cfstore_internal_compare(&arm_uc_device_guid,
+                                                        device_buffer);
+
+            if (is_same)
+            {
+                parameters_ok++;
+            }
+            else
+            {
+                result.code = MFST_ERR_GUID_DEVICE;
+            }
+
+            parameters_set++;
+        }
+    }
+
+    /* check class - class is optional */
+    if (arm_uc_class_guid_set)
+    {
+        if (class_buffer && class_buffer->ptr)
+        {
+            bool is_same = pal_cfstore_internal_compare(&arm_uc_class_guid,
+                                                        class_buffer);
+
+            if (is_same)
+            {
+                parameters_ok++;
+            }
+            else
+            {
+                result.code = MFST_ERR_GUID_DEVCLASS;
+            }
+
+            parameters_set++;
+        }
+    }
+
+    /* check vendor - vendor is mandatory and has mask 0x10. */
+    if (arm_uc_vendor_guid_set)
+    {
+        if (vendor_buffer && vendor_buffer->ptr)
+        {
+            bool is_same = pal_cfstore_internal_compare(&arm_uc_vendor_guid,
+                                                        vendor_buffer);
+
+            if (is_same)
+            {
+                parameters_ok += 0x10;
+            }
+            else
+            {
+                result.code = MFST_ERR_GUID_VENDOR;
+            }
+
+            parameters_set += 0x10;
+        }
+    }
+
+    /* Device ID checks out when:
+        - vendor match and neither class nor device is passed
+        - vendor and class match and no device is passed
+        - vendor and device match and no class is passed
+        - vendor and class and device match
+    */
+    if ((parameters_set >= 0x10) && (parameters_set == parameters_ok))
+    {
+        result.code = MFST_ERR_NONE;
+    }
+
+    return result;
+}
+
+const ARM_PAL_DEVICE_IDENTITY arm_uc_device_identity_cfstore = {
+    .SetVendorGuid          = pal_cfstore_setVendorGuid,
+    .GetVendorGuid          = pal_cfstore_getVendorGuid,
+    .SetClassGuid           = pal_cfstore_setClassGuid,
+    .GetClassGuid           = pal_cfstore_getClassGuid,
+    .SetDeviceGuid          = pal_cfstore_setDeviceGuid,
+    .GetDeviceGuid          = pal_cfstore_getDeviceGuid,
+    .DeviceIdentityCheck    = pal_cfstore_deviceIdentityCheck
+};
+
+#endif // ARM_UC_USE_CFSTORE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/device-identity/source/arm_uc_device_identity_kcm.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,341 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "pal4life-device-identity/pal_device_identity.h"
+#include "update-client-common/arm_uc_config.h"
+#include <stdint.h>
+
+#ifndef ARM_UC_USE_KCM
+#define ARM_UC_USE_KCM 0
+#endif
+
+#if ARM_UC_USE_KCM
+
+#include "key-config-manager/key_config_manager.h"
+
+#define SIZE_OF_GUID (sizeof(arm_uc_guid_t))
+// Hex encoded GUIDs with up to 4 hyphens.
+#define SIZE_OF_TEXT_GUID ((SIZE_OF_GUID) * 2 + 4)
+
+/* these defines are copied from:
+   mbed-cloud-client/source/include/CloudClientStorage.h
+*/
+#define KEY_DEVICE_MANUFACTURER_DEPRECATED      "mbed.Manufacturer"
+#define KEY_DEVICE_MODELNUMBER_DEPRECATED       "mbed.ModelNumber"
+#define KEY_ENDPOINT_NAME                       "mbed.EndpointName"
+#define KEY_VENDOR_ID                           "mbed.VendorId"
+#define KEY_CLASS_ID                            "mbed.ClassId"
+
+static arm_uc_error_t pal_kcm_internal_set_guid(const arm_uc_guid_t* guid,
+                                                const char* key,
+                                                size_t key_length)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (guid && key)
+    {
+        kcm_status_e kcm_status = kcm_item_store((const uint8_t*) key,
+                                                 key_length,
+                                                 KCM_CONFIG_ITEM,
+                                                 true,
+                                                 (const uint8_t*) guid,
+                                                 SIZE_OF_GUID,
+                                                 NULL);
+
+        if (kcm_status == KCM_STATUS_SUCCESS)
+        {
+            result.code = ERR_NONE;
+        }
+    }
+
+    return result;
+}
+
+static arm_uc_error_t pal_kcm_internal_get_guid(arm_uc_guid_t* guid,
+                                                const char* key,
+                                                size_t key_length)
+{
+    arm_uc_error_t result = { .module = TWO_CC('D', 'I'), .error = ERR_INVALID_PARAMETER };
+
+    if (guid && key)
+    {
+        uint8_t buffer[SIZE_OF_GUID] = { 0 };
+        size_t value_length = 0;
+        memset(guid, 0, SIZE_OF_GUID);
+
+        kcm_status_e kcm_status = kcm_item_get_data((const uint8_t*) key,
+                                        key_length,
+                                        KCM_CONFIG_ITEM,
+                                        buffer,
+                                        SIZE_OF_GUID,
+                                        &value_length);
+        if (kcm_status == KCM_STATUS_ITEM_NOT_FOUND)
+        {
+            result.code = ARM_UC_DI_ERR_NOT_FOUND;
+        }
+
+        if (kcm_status == KCM_STATUS_SUCCESS)
+        {
+            result.code = ERR_NONE;
+            memcpy(guid, buffer, SIZE_OF_GUID);
+        }
+    }
+
+    return result;
+}
+
+static bool pal_kcm_internal_compare(const arm_uc_guid_t* guid,
+                                     const arm_uc_buffer_t* buffer)
+{
+    // count how many bytes match
+    uint8_t index = 0;
+
+    if (guid && buffer)
+    {
+        for ( ; (index < sizeof(arm_uc_guid_t)) && (index < buffer->size); index++)
+        {
+            // printf("%02X %02X\r\n", ((uint8_t*) guid)[index], buffer->ptr[index]);
+
+            if (((uint8_t*) guid)[index] != buffer->ptr[index])
+            {
+                break;
+            }
+        }
+    }
+
+    // return true if all bytes matched
+    return (index == sizeof(arm_uc_guid_t));
+}
+
+/**
+ * @brief Function for setting the vendor GUID.
+ * @details The GUID is copied.
+ * @param guid Pointer to a arm_uc_guid_t GUID.
+ * @param copy Boolean value indicating whether the value should be copied or
+ *             referenced.
+ * @return Error code.
+ */
+arm_uc_error_t pal_kcm_setVendorGuid(const arm_uc_guid_t* guid)
+{
+    return pal_kcm_internal_set_guid(guid,
+                                     KEY_VENDOR_ID,
+                                     sizeof(KEY_VENDOR_ID) - 1);
+}
+
+/**
+ * @brief Function for getting a pointer to the vendor GUID.
+ * @param guid Pointer to a arm_uc_guid_t pointer.
+ * @return Error code.
+ */
+arm_uc_error_t pal_kcm_getVendorGuid(arm_uc_guid_t* guid)
+{
+    arm_uc_error_t err = pal_kcm_internal_get_guid(guid,
+                                    KEY_VENDOR_ID,
+                                    sizeof(KEY_VENDOR_ID) - 1);
+    if (err.code == ARM_UC_DI_ERR_NOT_FOUND)
+    {
+        err = pal_kcm_internal_get_guid(guid,
+                                    KEY_DEVICE_MANUFACTURER_DEPRECATED,
+                                    sizeof(KEY_DEVICE_MANUFACTURER_DEPRECATED) - 1);
+    }
+    return err;
+}
+
+/**
+ * @brief Function for setting the device class GUID.
+ * @details The GUID is copied.
+ * @param guid Pointer to a arm_uc_guid_t GUID.
+ * @param copy Boolean value indicating whether the value should be copied or
+ *             referenced.
+ * @return Error code.
+ */
+arm_uc_error_t pal_kcm_setClassGuid(const arm_uc_guid_t* guid)
+{
+    return pal_kcm_internal_set_guid(guid,
+                                     KEY_CLASS_ID,
+                                     sizeof(KEY_CLASS_ID) - 1);
+}
+
+/**
+ * @brief Function for getting a pointer to the device class GUID.
+ * @param guid Pointer to a arm_uc_guid_t pointer.
+ * @return Error code.
+ */
+arm_uc_error_t pal_kcm_getClassGuid(arm_uc_guid_t* guid)
+{
+    arm_uc_error_t err = pal_kcm_internal_get_guid(guid,
+                                    KEY_CLASS_ID,
+                                    sizeof(KEY_CLASS_ID) - 1);
+    if (err.code == ARM_UC_DI_ERR_NOT_FOUND)
+    {
+        err = pal_kcm_internal_get_guid(guid,
+                                    KEY_DEVICE_MODELNUMBER_DEPRECATED,
+                                    sizeof(KEY_DEVICE_MODELNUMBER_DEPRECATED) - 1);
+    }
+    return err;
+}
+
+/**
+ * @brief Function for setting the device GUID.
+ * @details The GUID is copied.
+ * @param guid Pointer to a arm_uc_guid_t GUID.
+ * @param copy Boolean value indicating whether the value should be copied or
+ *             referenced.
+ * @return Error code.
+ */
+arm_uc_error_t pal_kcm_setDeviceGuid(const arm_uc_guid_t* guid)
+{
+    return pal_kcm_internal_set_guid(guid,
+                                     KEY_ENDPOINT_NAME,
+                                     sizeof(KEY_ENDPOINT_NAME) - 1);
+}
+
+/**
+ * @brief Function for getting a pointer to the device GUID.
+ * @param guid Pointer to a arm_uc_guid_t pointer.
+ * @return Error code.
+ */
+arm_uc_error_t pal_kcm_getDeviceGuid(arm_uc_guid_t* guid)
+{
+    return pal_kcm_internal_get_guid(guid,
+                                     KEY_ENDPOINT_NAME,
+                                     sizeof(KEY_ENDPOINT_NAME) - 1);
+}
+
+
+/**
+ * @brief Check whether the three GUIDs provided are valid on the device.
+ * @details
+ * @param vendor_buffer Buffer pointer to the Vendor GUID.
+ * @param class_buffer  Buffer pointer to the device class GUID.
+ * @param device_buffer Buffer pointer to the device GUID.
+ * @param isValid     Pointer to the boolean return value.
+ * @return Error code.
+ */
+arm_uc_error_t pal_kcm_deviceIdentityCheck(const arm_uc_buffer_t* vendor_buffer,
+                                           const arm_uc_buffer_t* class_buffer,
+                                           const arm_uc_buffer_t* device_buffer)
+{
+    arm_uc_error_t result = { .code = MFST_ERR_NULL_PTR };
+
+    uint8_t parameters_set = 0;
+    uint8_t parameters_ok = 0;
+
+    /* check device - device is optional */
+    if (device_buffer &&
+        device_buffer->ptr &&
+        (device_buffer->size > 0))
+    {
+        parameters_set++;
+
+        arm_uc_guid_t guid = { 0 };
+
+        arm_uc_error_t retval = pal_kcm_getDeviceGuid(&guid);
+
+        if (retval.code == ERR_NONE)
+        {
+            bool is_same = pal_kcm_internal_compare(&guid, device_buffer);
+
+            if (is_same)
+            {
+                parameters_ok++;
+            }
+            else
+            {
+                result.code = MFST_ERR_GUID_DEVICE;
+            }
+        }
+    }
+
+    /* check class - class is optional */
+    if (class_buffer &&
+        class_buffer->ptr &&
+        (class_buffer->size > 0))
+    {
+        parameters_set++;
+
+        arm_uc_guid_t guid = { 0 };
+
+        arm_uc_error_t retval = pal_kcm_getClassGuid(&guid);
+
+        if (retval.code == ERR_NONE)
+        {
+            bool is_same = pal_kcm_internal_compare(&guid, class_buffer);
+
+            if (is_same)
+            {
+                parameters_ok++;
+            }
+            else
+            {
+                result.code = MFST_ERR_GUID_DEVCLASS;
+            }
+        }
+    }
+
+    /* check vendor - vendor is mandatory and has mask 0x10. */
+    if (vendor_buffer &&
+        vendor_buffer->ptr &&
+        (vendor_buffer->size > 0))
+    {
+        parameters_set += 0x10;
+
+        arm_uc_guid_t guid = { 0 };
+
+        arm_uc_error_t retval = pal_kcm_getVendorGuid(&guid);
+
+        if (retval.code == ERR_NONE)
+        {
+            bool is_same = pal_kcm_internal_compare(&guid, vendor_buffer);
+
+            if (is_same)
+            {
+                parameters_ok += 0x10;
+            }
+            else
+            {
+                result.code = MFST_ERR_GUID_VENDOR;
+            }
+        }
+    }
+
+    /* Device ID checks out when:
+        - vendor match and neither class nor device is passed
+        - vendor and class match and no device is passed
+        - vendor and device match and no class is passed
+        - vendor and class and device match
+    */
+    if ((parameters_set >= 0x10) && (parameters_set == parameters_ok))
+    {
+        result.code = MFST_ERR_NONE;
+    }
+
+    return result;
+}
+
+const ARM_PAL_DEVICE_IDENTITY arm_uc_device_identity_kcm = {
+    .SetVendorGuid          = pal_kcm_setVendorGuid,
+    .GetVendorGuid          = pal_kcm_getVendorGuid,
+    .SetClassGuid           = pal_kcm_setClassGuid,
+    .GetClassGuid           = pal_kcm_getClassGuid,
+    .SetDeviceGuid          = pal_kcm_setDeviceGuid,
+    .GetDeviceGuid          = pal_kcm_getDeviceGuid,
+    .DeviceIdentityCheck    = pal_kcm_deviceIdentityCheck
+};
+
+#endif // ARM_UC_USE_KCM
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/firmware-manager/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+*/test/*
+test/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/firmware-manager/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/firmware-manager/source/arm_uc_firmware_manager.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,624 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-firmware-manager/arm_uc_firmware_manager.h"
+#include "update-client-common/arm_uc_common.h"
+
+#include "update-client-paal/arm_uc_paal_update.h"
+
+#include <stdio.h>
+#include <stdbool.h>
+
+static ARM_UCFM_SignalEvent_t ucfm_handler = NULL;
+
+static ARM_UCFM_Setup_t* package_configuration = NULL;
+static uint32_t package_offset = 0;
+static bool ready_to_receive = false;
+
+static arm_uc_callback_t arm_uc_event_handler_callback = { 0 };
+
+static arm_uc_mdHandle_t mdHandle = { 0 };
+static arm_uc_cipherHandle_t cipherHandle = { 0 };
+static arm_uc_buffer_t* front_buffer = NULL;
+static arm_uc_buffer_t* back_buffer = NULL;
+
+#define UCFM_DEBUG_OUTPUT 0
+
+
+static void arm_uc_signal_ucfm_handler(uint32_t event);
+
+/******************************************************************************/
+/* Debug output functions for writing formatted output                        */
+/******************************************************************************/
+
+#if UCFM_DEBUG_OUTPUT
+
+static void debug_output_decryption(const uint8_t* encrypted,
+                                    arm_uc_buffer_t* decrypted)
+{
+    for (size_t index = 0; index < UCFM_MAX_BLOCK_SIZE; index++)
+    {
+        if (index < decrypted->size)
+        {
+            uint8_t symbol = encrypted[index];
+
+            printf("%02X", symbol);
+        }
+        else
+        {
+            printf("  ");
+        }
+    }
+
+    printf("\t:\t");
+
+    for (size_t index = 0; index < UCFM_MAX_BLOCK_SIZE; index++)
+    {
+        if (index < decrypted->size)
+        {
+            uint8_t symbol = encrypted[index];
+
+            if ((symbol > 32) && (symbol < 127))
+            {
+                printf("%c", symbol);
+            }
+            else
+            {
+                printf(" ");
+            }
+        }
+        else
+        {
+            printf(" ");
+        }
+    }
+
+    printf("\t:\t");
+
+    for (size_t index = 0; index < decrypted->size_max; index++)
+    {
+        if (index < decrypted->size)
+        {
+            uint8_t symbol = decrypted->ptr[index];
+
+            if ((symbol > 32) && (symbol < 127))
+            {
+                printf("%c", symbol);
+            }
+            else
+            {
+                printf(" ");
+            }
+        }
+        else
+        {
+            printf(" ");
+        }
+    }
+
+    printf("\r\n");
+}
+
+static void debug_output_validation(arm_uc_buffer_t* hash,
+                                    arm_uc_buffer_t* output_buffer)
+{
+    printf("\r\n");
+    printf("expected hash  : ");
+    for (size_t index = 0; index < hash->size; index++)
+    {
+        printf("%02X", hash->ptr[index]);
+    }
+    printf("\r\n");
+
+    printf("calculated hash: ");
+    for (size_t index = 0; index < output_buffer->size; index++)
+    {
+        printf("%02X", output_buffer->ptr[index]);
+    }
+    printf("\r\n");
+    printf("\r\n");
+}
+
+#endif
+
+/******************************************************************************/
+
+/* Hash calculation is performed using the output buffer. This function fills
+   the output buffer with data from the PAL.
+*/
+static void arm_uc_internal_process_hash(void)
+{
+    bool double_buffering = (front_buffer != back_buffer);
+    bool needs_more_data = (package_offset < package_configuration->package_size);
+    arm_uc_error_t status = { .code = ERR_NONE };
+    uint32_t error_event = UCFM_EVENT_FINALIZE_ERROR;
+
+    if (double_buffering && needs_more_data)
+    {
+#if UCFM_DEBUG_OUTPUT
+        printf("double buffering: %p %" PRIX32 "\r\n", back_buffer, back_buffer->size_max);
+#endif
+
+        /* if using double buffering, initiate a new data read as soon as possible */
+        /* Indicate read size */
+        uint32_t bytes_remaining = package_configuration->package_size - package_offset;
+        back_buffer->size = (bytes_remaining > back_buffer->size_max)?
+                                back_buffer->size_max : bytes_remaining;
+
+        /* initiate read from PAL */
+        status = ARM_UCP_Read(package_configuration->package_id,
+                              package_offset,
+                              back_buffer);
+    }
+
+    if (status.error == ERR_NONE)
+    {
+        /* process data in front buffer */
+        ARM_UC_cryptoHashUpdate(&mdHandle, front_buffer);
+
+        if (needs_more_data)
+        {
+            /* if we're actually using two buffers, the read operation was initiated earlier,
+             * otherwise it needs to be initiated now, after we're done hashing the only
+             * buffer that we're using
+             */
+            if (!double_buffering)
+            {
+#if UCFM_DEBUG_OUTPUT
+                printf("single buffering: %p\r\n", front_buffer);
+#endif
+                /* Indicate read size */
+                uint32_t bytes_remaining = package_configuration->package_size - package_offset;
+                back_buffer->size = (bytes_remaining > back_buffer->size_max)?
+                                        back_buffer->size_max : bytes_remaining;
+
+                /* initiate read from PAL */
+                status = ARM_UCP_Read(package_configuration->package_id,
+                                      package_offset,
+                                      back_buffer);
+            }
+        }
+        else
+        {
+            /* invert status code so that it has to be set explicitly for success */
+            status.code = ERR_INVALID_PARAMETER;
+
+            /* finalize hash calculation */
+            uint8_t hash_output_ptr[2 * UCFM_MAX_BLOCK_SIZE];
+            arm_uc_buffer_t hash_buffer = {
+                .size_max = sizeof(hash_output_ptr),
+                .size = 0,
+                .ptr = hash_output_ptr
+            };
+
+            ARM_UC_cryptoHashFinish(&mdHandle, &hash_buffer);
+
+            /* size check before memcmp call */
+            if (hash_buffer.size == package_configuration->hash->size)
+            {
+                int diff = memcmp(hash_buffer.ptr,
+                                  package_configuration->hash->ptr,
+                                  package_configuration->hash->size);
+
+#if UCFM_DEBUG_OUTPUT
+                debug_output_validation(package_configuration->hash,
+                                        &hash_buffer);
+#endif
+
+                /* hash matches */
+                if (diff == 0)
+                {
+                    UC_FIRM_TRACE("UCFM_EVENT_FINALIZE_DONE");
+
+                    arm_uc_signal_ucfm_handler(UCFM_EVENT_FINALIZE_DONE);
+                    status.code = ERR_NONE;
+                }
+                else
+                {
+                    /* use specific event for "invalid hash" */
+                    UC_FIRM_ERR_MSG("Invalid image hash");
+
+                    error_event = UCFM_EVENT_FINALIZE_INVALID_HASH_ERROR;
+                }
+            }
+        }
+
+        /* Front buffer is processed, back buffer might be reading more data.
+           Swap buffer so that data will be ready in front buffer
+        */
+        arm_uc_buffer_t* temp = front_buffer;
+        front_buffer = back_buffer;
+        back_buffer = temp;
+    }
+
+    /* signal error if status is not clean */
+    if (status.error != ERR_NONE)
+    {
+        UC_FIRM_TRACE("UCFM_EVENT_FINALIZE_ERROR");
+        arm_uc_signal_ucfm_handler(error_event);
+    }
+}
+
+/******************************************************************************/
+
+/* Function for decoupling PAL callbacks using the internal task queue. */
+/* Write commit done */
+static void event_handler_finalize(void)
+{
+    UC_FIRM_TRACE("event_handler_finalize");
+
+    /* setup mandatory hash */
+    arm_uc_mdType_t mdtype = ARM_UC_CU_SHA256;
+    arm_uc_error_t result = ARM_UC_cryptoHashSetup(&mdHandle, mdtype);
+
+    if (result.error == ERR_NONE)
+    {
+        /* initiate hash calculation */
+        package_offset = 0;
+
+        /* indicate number of bytes needed */
+        front_buffer->size = (package_configuration->package_size < front_buffer->size_max)?
+                              package_configuration->package_size : front_buffer->size_max;
+
+        /* initiate read from PAL */
+        result = ARM_UCP_Read(package_configuration->package_id,
+                              package_offset,
+                              front_buffer);
+    }
+
+    if (result.error != ERR_NONE)
+    {
+        UC_FIRM_ERR_MSG("ARM_UC_cryptoHashSetup failed");
+        arm_uc_signal_ucfm_handler(UCFM_EVENT_FINALIZE_ERROR);
+    }
+}
+
+/* Function for decoupling PAL callbacks using the internal task queue. */
+static void event_handler_read(void)
+{
+#if UCFM_DEBUG_OUTPUT
+    printf("event_handler_read: %" PRIX32 "\r\n", front_buffer->size);
+#endif
+
+    /* check that read succeeded in reading data into buffer */
+    if (front_buffer->size > 0)
+    {
+        /* check if read over shot */
+        if ((package_offset + front_buffer->size) >
+            package_configuration->package_size)
+        {
+            /* trim buffer */
+            front_buffer->size = package_configuration->package_size - package_offset;
+        }
+
+        /* update offset and continue reading data from PAL */
+        package_offset += front_buffer->size;
+        arm_uc_internal_process_hash();
+    }
+    else
+    {
+        /* error - no data processed */
+        UC_FIRM_TRACE("UCFM_EVENT_FINALIZE_ERROR");
+        arm_uc_signal_ucfm_handler(UCFM_EVENT_FINALIZE_ERROR);
+    }
+}
+
+static void arm_uc_signal_ucfm_handler(uint32_t event)
+{
+    if (ucfm_handler)
+    {
+        ucfm_handler(event);
+    }
+}
+
+static void arm_uc_internal_event_handler(uint32_t event)
+{
+    switch (event)
+    {
+        case ARM_UC_PAAL_EVENT_FINALIZE_DONE:
+            event_handler_finalize();
+            break;
+        case ARM_UC_PAAL_EVENT_READ_DONE:
+            event_handler_read();
+            break;
+        default:
+            /* pass all other events directly */
+            arm_uc_signal_ucfm_handler(event);
+            break;
+    }
+}
+
+static void ARM_UCFM_PALEventHandler(uint32_t event)
+{
+    /* decouple event handler from callback */
+    ARM_UC_PostCallback(&arm_uc_event_handler_callback,
+                        arm_uc_internal_event_handler, event);
+}
+
+/******************************************************************************/
+static arm_uc_error_t ARM_UCFM_Initialize(ARM_UCFM_SignalEvent_t handler)
+{
+    UC_FIRM_TRACE("ARM_UCFM_Initialize");
+
+    arm_uc_error_t result = (arm_uc_error_t){ FIRM_ERR_INVALID_PARAMETER };
+
+    if (handler)
+    {
+        result = ARM_UCP_Initialize(ARM_UCFM_PALEventHandler);
+
+        if (result.error == ERR_NONE)
+        {
+            ucfm_handler = handler;
+        }
+    }
+
+    return result;
+}
+
+static arm_uc_error_t ARM_UCFM_Prepare(ARM_UCFM_Setup_t* configuration,
+                                       const arm_uc_firmware_details_t* details,
+                                       arm_uc_buffer_t* buffer)
+{
+    UC_FIRM_TRACE("ARM_UCFM_Setup");
+
+    arm_uc_error_t result = (arm_uc_error_t){ FIRM_ERR_NONE };
+
+    /* sanity checks */
+    if (!ucfm_handler)
+    {
+        UC_FIRM_ERR_MSG("Event handler not set. Should call Initialise before calling Setup");
+        result =  (arm_uc_error_t){ FIRM_ERR_UNINITIALIZED };
+    }
+    /* check configuration is defined and contains key and iv. */
+    else if ((!(configuration &&
+              ((configuration->mode == UCFM_MODE_NONE_SHA_256) ||
+               (configuration->key && configuration->iv)))) ||
+             !buffer ||
+             !buffer->ptr)
+    {
+        result =  (arm_uc_error_t){ FIRM_ERR_INVALID_PARAMETER };
+    }
+
+    /* allocate space using PAL */
+    if (result.error == ERR_NONE)
+    {
+        result = ARM_UCP_Prepare(configuration->package_id,
+                                 details,
+                                 buffer);
+
+        if (result.error != ERR_NONE)
+        {
+            UC_FIRM_ERR_MSG("ARM_UCP_Prepare failed");
+        }
+    }
+
+    /* setup encryption if requested by mode */
+    if ((result.error == ERR_NONE) &&
+        (configuration->mode != UCFM_MODE_NONE_SHA_256))
+    {
+        /* A previously aborted firmware write will have left the cipherHandler
+           in an inconsistent state. If the IV is not NULL, clear the context
+           using the call to finish and set the struct to zero.
+        */
+        if (cipherHandle.aes_iv != NULL)
+        {
+            ARM_UC_cryptoDecryptFinish(&cipherHandle, buffer);
+            memset(&cipherHandle, 0, sizeof(arm_uc_cipherHandle_t));
+        }
+
+        /* setup cipherHanlde with decryption keys */
+        uint32_t bits = (configuration->mode == UCFM_MODE_AES_CTR_128_SHA_256) ? 128 : 256;
+        result = ARM_UC_cryptoDecryptSetup(&cipherHandle,
+                                           configuration->key,
+                                           configuration->iv,
+                                           bits);
+
+        if (result.error != ERR_NONE)
+        {
+            UC_FIRM_ERR_MSG("ARM_UC_cryptoDecryptSetup failed in %" PRIu32 " bit mode", bits);
+        }
+    }
+
+    /* Initialise the internal state */
+    if (result.error == ERR_NONE)
+    {
+        package_configuration = configuration;
+        package_offset = 0;
+        ready_to_receive = true;
+    }
+
+    return result;
+}
+
+static arm_uc_error_t ARM_UCFM_Write(const arm_uc_buffer_t* fragment)
+{
+    UC_FIRM_TRACE("ARM_UCFM_Write");
+
+    arm_uc_error_t result = (arm_uc_error_t){ FIRM_ERR_NONE };
+
+    if (!fragment || fragment->size_max == 0 || fragment->size > fragment->size_max || !fragment->ptr)
+    {
+        result = (arm_uc_error_t){ FIRM_ERR_INVALID_PARAMETER };
+    }
+    else if (!ready_to_receive)
+    {
+        result = (arm_uc_error_t){ FIRM_ERR_UNINITIALIZED };
+    }
+    else
+    {
+        /* decrypt fragment before writing to PAL */
+        if (package_configuration->mode != UCFM_MODE_NONE_SHA_256)
+        {
+            /* temporary buffer for decrypting in place */
+            uint8_t decrypt_output_ptr[2 * UCFM_MAX_BLOCK_SIZE];
+            arm_uc_buffer_t decrypt_buffer = {
+                .size_max = sizeof(decrypt_output_ptr),
+                .size = 0,
+                .ptr = decrypt_output_ptr
+            };
+
+            uint32_t fragment_offset = 0;
+            while (fragment_offset < fragment->size)
+            {
+                /* default to max length */
+                uint32_t length_update = decrypt_buffer.size_max;
+
+                /* adjust size to not overshoot */
+                if (fragment_offset + length_update > fragment->size)
+                {
+                    length_update = fragment->size - fragment_offset;
+                }
+
+                /* decrypt part of the fragment using the offset */
+                ARM_UC_cryptoDecryptUpdate(&cipherHandle,
+                                           &fragment->ptr[fragment_offset],
+                                           length_update,
+                                           &decrypt_buffer);
+
+#if UCFM_DEBUG_OUTPUT
+                debug_output_decryption(&fragment->ptr[fragment_offset],
+                                        &decrypt_buffer);
+#endif
+
+                /* overwrite the encrypted data with the decrypted data */
+                memcpy(&fragment->ptr[fragment_offset],
+                       decrypt_buffer.ptr,
+                       length_update);
+
+                /* update offset */
+                fragment_offset += length_update;
+            }
+        }
+
+        /* store fragment using PAL */
+        result = ARM_UCP_Write(package_configuration->package_id,
+                               package_offset,
+                               fragment);
+
+        if (result.error == ERR_NONE)
+        {
+            package_offset += fragment->size;
+        }
+    }
+
+    return result;
+}
+
+static arm_uc_error_t ARM_UCFM_Finalize(arm_uc_buffer_t* front, arm_uc_buffer_t* back)
+{
+    UC_FIRM_TRACE("ARM_UCFM_Finish");
+
+    arm_uc_error_t result = (arm_uc_error_t){ FIRM_ERR_NONE };
+
+    if (!ready_to_receive)
+    {
+        result = (arm_uc_error_t){ FIRM_ERR_UNINITIALIZED };
+    }
+    else if ((front == NULL) ||
+             (front != NULL && ((front->size_max % ARM_UC_SHA256_SIZE) != 0)) ||
+             (back != NULL && ((back->size_max % ARM_UC_SHA256_SIZE) != 0)))
+    {
+        result = (arm_uc_error_t){ FIRM_ERR_INVALID_PARAMETER };
+    }
+    else
+    {
+        /* flush decryption buffer, discard data */
+        ARM_UC_cryptoDecryptFinish(&cipherHandle, front);
+        memset(&cipherHandle, 0, sizeof(arm_uc_cipherHandle_t));
+
+        /* save buffers, checking if the buffers actually exist */
+        front_buffer = front;
+        back_buffer = (back == NULL) ? front_buffer : back;
+
+        /* flush to PAL */
+        result = ARM_UCP_Finalize(package_configuration->package_id);
+
+        /* disable module until next setup call is received */
+        ready_to_receive = false;
+    }
+
+    return result;
+}
+
+static arm_uc_error_t ARM_UCFM_Activate(uint32_t location)
+{
+    UC_FIRM_TRACE("ARM_UCFM_Activate");
+
+    arm_uc_error_t result = { .code = FIRM_ERR_ACTIVATE };
+
+    if (ucfm_handler)
+    {
+        result = ARM_UCP_Activate(location);
+    }
+
+    return result;
+}
+
+static arm_uc_error_t ARM_UCFM_GetActiveFirmwareDetails(arm_uc_firmware_details_t* details)
+{
+    UC_FIRM_TRACE("ARM_UCFM_GetActiveFirmwareDetails");
+
+    arm_uc_error_t result = { .code = FIRM_ERR_INVALID_PARAMETER };
+
+    if (ucfm_handler && details)
+    {
+        result = ARM_UCP_GetActiveFirmwareDetails(details);
+    }
+
+    return result;
+}
+
+static arm_uc_error_t ARM_UCFM_GetFirmwareDetails(uint32_t location,
+                                                  arm_uc_firmware_details_t* details)
+{
+    UC_FIRM_TRACE("ARM_UCFM_GetFirmwareDetails");
+
+    arm_uc_error_t result = { .code = FIRM_ERR_INVALID_PARAMETER };
+
+    if (ucfm_handler && details)
+    {
+        result = ARM_UCP_GetFirmwareDetails(location, details);
+    }
+
+    return result;
+}
+
+static arm_uc_error_t ARM_UCFM_GetInstallerDetails(arm_uc_installer_details_t* details)
+{
+    UC_FIRM_TRACE("ARM_UCFM_GetInstallerDetails");
+
+    arm_uc_error_t result = { .code = FIRM_ERR_INVALID_PARAMETER };
+
+    if (ucfm_handler && details)
+    {
+        result = ARM_UCP_GetInstallerDetails(details);
+    }
+
+    return result;
+}
+
+ARM_UC_FIRMWARE_MANAGER_t ARM_UC_FirmwareManager = {
+    .Initialize               = ARM_UCFM_Initialize,
+    .Prepare                  = ARM_UCFM_Prepare,
+    .Write                    = ARM_UCFM_Write,
+    .Finalize                 = ARM_UCFM_Finalize,
+    .Activate                 = ARM_UCFM_Activate,
+    .GetActiveFirmwareDetails = ARM_UCFM_GetActiveFirmwareDetails,
+    .GetFirmwareDetails       = ARM_UCFM_GetFirmwareDetails,
+    .GetInstallerDetails      = ARM_UCFM_GetInstallerDetails
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/firmware-manager/update-client-firmware-manager/arm_uc_firmware_manager.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,158 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_FIRMWARE_MANAGER_H
+#define ARM_UC_FIRMWARE_MANAGER_H
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+#include "update-client-common/arm_uc_common.h"
+
+typedef void (*ARM_UCFM_SignalEvent_t)(uint32_t event);
+
+#define UCFM_MAX_BLOCK_SIZE 16
+
+typedef enum {
+    UCFM_EVENT_INITIALIZE_DONE                   = ARM_UC_PAAL_EVENT_INITIALIZE_DONE,
+    UCFM_EVENT_PREPARE_DONE                      = ARM_UC_PAAL_EVENT_PREPARE_DONE,
+    UCFM_EVENT_WRITE_DONE                        = ARM_UC_PAAL_EVENT_WRITE_DONE,
+    UCFM_EVENT_FINALIZE_DONE                     = ARM_UC_PAAL_EVENT_FINALIZE_DONE,
+    UCFM_EVENT_ACTIVATE_DONE                     = ARM_UC_PAAL_EVENT_ACTIVATE_DONE,
+    UCFM_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE  = ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE,
+    UCFM_EVENT_GET_FIRMWARE_DETAILS_DONE         = ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE,
+    UCFM_EVENT_GET_INSTALLER_DETAILS_DONE        = ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE,
+    UCFM_EVENT_INITIALIZE_ERROR                  = ARM_UC_PAAL_EVENT_INITIALIZE_ERROR,
+    UCFM_EVENT_PREPARE_ERROR                     = ARM_UC_PAAL_EVENT_PREPARE_ERROR,
+    UCFM_EVENT_WRITE_ERROR                       = ARM_UC_PAAL_EVENT_WRITE_ERROR,
+    UCFM_EVENT_FINALIZE_ERROR                    = ARM_UC_PAAL_EVENT_FINALIZE_ERROR,
+    UCFM_EVENT_ACTIVATE_ERROR                    = ARM_UC_PAAL_EVENT_ACTIVATE_ERROR,
+    UCFM_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_ERROR = ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_ERROR,
+    UCFM_EVENT_GET_FIRMWARE_DETAILS_ERROR        = ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_ERROR,
+    UCFM_EVENT_GET_INSTALLER_DETAILS_ERROR       = ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_ERROR,
+    UCFM_EVENT_FINALIZE_INVALID_HASH_ERROR
+} ARM_UCFM_Event_t;
+
+typedef enum {
+    UCFM_MODE_UNINIT,
+    UCFM_MODE_NONE_SHA_256,
+    UCFM_MODE_AES_CTR_128_SHA_256,
+    UCFM_MODE_AES_CTR_256_SHA_256
+} ARM_UCFM_mode_t;
+
+typedef struct _ARM_UCFM_Setup {
+    ARM_UCFM_mode_t mode;
+    arm_uc_buffer_t* key;
+    arm_uc_buffer_t* iv;
+    arm_uc_buffer_t* hash;
+    uint32_t package_id;
+    uint32_t package_size;
+} ARM_UCFM_Setup_t;
+
+typedef struct _ARM_UC_FIRMWARE_MANAGER {
+    /**
+     * @brief Initialization function.
+     * @param handler Function pointer to the event handler.
+     * @return Error code.
+     */
+    arm_uc_error_t (*Initialize)(ARM_UCFM_SignalEvent_t handler);
+
+    /**
+     * @brief Setup new package to be processed.
+     * @details Generates UCFM_EVENT_PREPARE_DONE event if call is accepted.
+     * @param configuration Struct containing configuration data.
+     * @param buffer Scratch pad for temporary storage.
+     * @return Error code.
+     */
+    arm_uc_error_t (*Prepare)(ARM_UCFM_Setup_t* configuration,
+                              const arm_uc_firmware_details_t* details,
+                              arm_uc_buffer_t* buffer);
+
+    /**
+     * @brief Function for adding a package fragment.
+     * @details Generates either UCFM_EVENT_WRITE_DONE or UCFM_EVENT_WRITE_ERROR.
+     * @details Fragments are processed based on the mode set in the configure
+     *          struct. This can include decryption, validation, and storage.
+     * @param input Buffer struct.
+     * @return Error code.
+     */
+    arm_uc_error_t (*Write)(const arm_uc_buffer_t* input);
+
+    /**
+     * @brief Function for finalizing the current package.
+     * @details Flushes all write buffers and initiates the hash validation.
+     *          Generates UCFM_EVENT_FINALIZE_DONE, UCFM_EVENT_FINALIZE_ERROR
+     *          or UCFM_EVENT_FINALIZE_INVALID_HASH_ERROR.
+     *          To speed up hash computation, this function accepts two buffer
+     *          arguments ('front' and 'back):
+     *          - if both 'front' and 'back' are NULL, a small internal buffer is
+     *            used. Note that this can have an adverse impact on performance.
+     *          - if only 'front' isn't NULL, 'front' will be used instead of the
+     *            internal buffer. If 'front' is a large buffer, a performance
+     *            improvement is likely to be observed.
+     *          - if both 'front' and 'back' are not NULL, the code will initiate
+     *            a read in the back buffer, hash the data in the front buffer,
+     *            then swap the buffers. This configuration should provide the
+     *            best performance (but also uses the most memory).
+     *          It is an error to call this function with 'front' equal to NULL
+     *          and a non-null value for 'back'.
+     *          NOTE: the buffer size must be a multiple of ARM_UC_SHA256_SIZE.
+     * @return Error code.
+     */
+    arm_uc_error_t (*Finalize)(arm_uc_buffer_t* front, arm_uc_buffer_t* back);
+
+    /**
+     * @brief Function for activating or installing the current package.
+     * @details Activates or installs the current package.
+     *          In the future this function might take the image ID as
+     *          paramter.
+     * @param location ID of slot to be activated.
+     * @return Error code.
+     */
+    arm_uc_error_t (*Activate)(uint32_t location);
+
+    /**
+     * @brief Get the firmware details for the currently active image.
+     *
+     * @param details Pointer to firmware details struct.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetActiveFirmwareDetails)(arm_uc_firmware_details_t* details);
+
+    /**
+     * @brief Get the firmware details for the specified location.
+     *
+     * @param location Location ID to get details for.
+     * @param details Pointer to firmware details struct.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetFirmwareDetails)(uint32_t location,
+                                         arm_uc_firmware_details_t* details);
+
+    /**
+     * @brief Get the installer details.
+     * @details Installer is responsible for applying the firmware image.
+     *
+     * @param details Pointer to installer details struct.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetInstallerDetails)(arm_uc_installer_details_t* details);
+
+} ARM_UC_FIRMWARE_MANAGER_t;
+
+extern ARM_UC_FIRMWARE_MANAGER_t ARM_UC_FirmwareManager;
+
+#endif // ARM_UC_FIRMWARE_MANAGER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,165 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/DeviceMetadataResource.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,247 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-lwm2m/DeviceMetadataResource.h"
+
+#include "update-client-common/arm_uc_common.h"
+#include "pal4life-device-identity/pal_device_identity.h"
+
+#include <stdio.h>
+
+#define ARM_UCS_LWM2M_INTERNAL_ERROR (-1)
+#define ARM_UCS_LWM2M_INTERNAL_SUCCESS (0)
+
+namespace DeviceMetadataResource {
+    /* LWM2M Firmware Update Object */
+    static M2MObject* deviceMetadataObject;
+
+    /* LWM2M Firmware Update Object resources */
+    static M2MResource* protocolSupportedResource = NULL; // /10255/0/0
+    static M2MResource* bootloaderHashResource    = NULL; // /10255/0/1
+    static M2MResource* OEMBootloaderHashResource = NULL; // /10255/0/2
+    static M2MResource* vendorIdResource          = NULL; // /10255/0/3
+    static M2MResource* classIdResource           = NULL; // /10255/0/4
+    static M2MResource* deviceIdResource          = NULL; // /10255/0/5
+}
+
+
+/**
+ * @brief Initialize LWM2M Device Metadata Object
+ * @details Sets up LWM2M object with accompanying resources.
+ */
+void DeviceMetadataResource::Initialize(void)
+{
+    static bool initialized = false;
+
+    if (!initialized)
+    {
+        initialized = true;
+
+        /* The LWM2M Firmware Update Object is at /10255 */
+        deviceMetadataObject = M2MInterfaceFactory::create_object("10255");
+
+        if (deviceMetadataObject)
+        {
+            /* Set object operating mode to GET_ALLOWED */
+            deviceMetadataObject->set_operation(M2MBase::GET_ALLOWED);
+            /* Create first (and only) instance /10255/0 */
+            M2MObjectInstance* deviceMetadataInstance = deviceMetadataObject->create_object_instance();
+
+            if (deviceMetadataInstance)
+            {
+                /* Default values are non-standard, but the standard has no
+                   values for indicating that the device is initializing.
+                */
+                int64_t defaultVersion   = 1;
+                const uint8_t invalid_value[]    = "INVALID";
+                const uint8_t invalid_value_size = sizeof(invalid_value) - 1;
+
+                ARM_UC_INIT_ERROR(err, ERR_INVALID_PARAMETER);
+                arm_uc_guid_t guid    = { 0 };
+                uint8_t* value        = NULL;
+                uint32_t value_length = 0;
+
+                /* Set instance operating mode to GET_ALLOWED */
+                deviceMetadataInstance->set_operation(M2MBase::GET_ALLOWED);
+
+                /* Create Update resource /10255/0/0 */
+                protocolSupportedResource = deviceMetadataInstance->create_dynamic_resource(
+                                                    "0",
+                                                    "ProtocolSupported",
+                                                    M2MResourceInstance::INTEGER,
+                                                    true);
+                if (protocolSupportedResource)
+                {
+                    protocolSupportedResource->set_operation(M2MBase::GET_ALLOWED);
+                    protocolSupportedResource->set_value(defaultVersion);
+                }
+
+                /* Create Update resource /10255/0/1 */
+                bootloaderHashResource = deviceMetadataInstance->create_static_resource(
+                                                    "1",
+                                                    "BootloaderHash",
+                                                    M2MResourceInstance::OPAQUE,
+                                                    (uint8_t *) invalid_value,
+                                                    invalid_value_size);
+                if (bootloaderHashResource)
+                {
+                    bootloaderHashResource->set_operation(M2MBase::GET_ALLOWED);
+                }
+
+                /* Create Update resource /10255/0/2 */
+                OEMBootloaderHashResource = deviceMetadataInstance->create_static_resource(
+                                                    "2",
+                                                    "OEMBootloaderHash",
+                                                    M2MResourceInstance::OPAQUE,
+                                                    (uint8_t *) invalid_value,
+                                                    invalid_value_size);
+                if (OEMBootloaderHashResource)
+                {
+                    OEMBootloaderHashResource->set_operation(M2MBase::GET_ALLOWED);
+                }
+
+                /* get vendor ID */
+                err = pal_getVendorGuid(&guid);
+                if (err.error == ERR_NONE)
+                {
+                    value = (uint8_t *) &guid;
+                    value_length = sizeof(arm_uc_guid_t);
+                }
+                else
+                {
+                    value = (uint8_t *) invalid_value;
+                    value_length = invalid_value_size;
+                }
+
+                /* Create Update resource /10255/0/3 */
+                vendorIdResource = deviceMetadataInstance->create_dynamic_resource(
+                                                    "3",
+                                                    "Vendor",
+                                                    M2MResourceInstance::OPAQUE,
+                                                    true);
+
+                if (vendorIdResource)
+                {
+                    vendorIdResource->set_operation(M2MBase::GET_ALLOWED);
+                    vendorIdResource->set_value(value, value_length);
+                }
+
+                /* get class ID */
+                err = pal_getClassGuid(&guid);
+                if (err.error == ERR_NONE)
+                {
+                    value = (uint8_t *) &guid;
+                    value_length = sizeof(arm_uc_guid_t);
+                }
+                else
+                {
+                    value = (uint8_t *) invalid_value;
+                    value_length = invalid_value_size;
+                }
+
+                /* Create Update resource /10255/0/4 */
+                classIdResource = deviceMetadataInstance->create_dynamic_resource(
+                                                    "4",
+                                                    "Class",
+                                                    M2MResourceInstance::OPAQUE,
+                                                    true);
+
+                if (classIdResource)
+                {
+                    classIdResource->set_operation(M2MBase::GET_ALLOWED);
+                    classIdResource->set_value(value, value_length);
+                }
+
+                /* get device ID */
+                err = pal_getDeviceGuid(&guid);
+                if (err.error == ERR_NONE)
+                {
+                    value = (uint8_t *) &guid;
+                    value_length = sizeof(arm_uc_guid_t);
+                }
+                else
+                {
+                    value = (uint8_t *) invalid_value;
+                    value_length = invalid_value_size;
+                }
+
+                /* Create Update resource /10255/0/5 */
+                deviceIdResource = deviceMetadataInstance->create_static_resource(
+                                                    "5",
+                                                    "DeviceId",
+                                                    M2MResourceInstance::OPAQUE,
+                                                    value,
+                                                    value_length);
+                if (deviceIdResource)
+                {
+                    deviceIdResource->set_operation(M2MBase::GET_ALLOWED);
+                }
+            }
+        }
+    }
+}
+
+int32_t DeviceMetadataResource::setBootloaderHash(arm_uc_buffer_t* hash)
+{
+    UC_SRCE_TRACE("DeviceMetadataResource::setBootloaderHash ptr %p size %u", hash, hash->size);
+
+    int32_t result = ARM_UCS_LWM2M_INTERNAL_ERROR;
+
+    if (bootloaderHashResource && hash && hash->size > 0)
+    {
+        bool rt = bootloaderHashResource->set_value(hash->ptr, hash->size);
+        if (rt == true)
+        {
+            result = ARM_UCS_LWM2M_INTERNAL_SUCCESS;
+        }
+    }
+
+    return result;
+}
+
+int32_t DeviceMetadataResource::setOEMBootloaderHash(arm_uc_buffer_t* hash)
+{
+    UC_SRCE_TRACE("DeviceMetadataResource::setOEMBootloaderHash ptr %p size %u", hash, hash->size);
+
+    int32_t result = ARM_UCS_LWM2M_INTERNAL_ERROR;
+
+    if (OEMBootloaderHashResource && hash && hash->size > 0)
+    {
+        bool rt = OEMBootloaderHashResource->set_value(hash->ptr, hash->size);
+        if (rt == true)
+        {
+            result = ARM_UCS_LWM2M_INTERNAL_SUCCESS;
+        }
+    }
+
+    return result;
+}
+
+M2MObject* DeviceMetadataResource::getObject()
+{
+    Initialize();
+
+    return deviceMetadataObject;
+}
+
+void DeviceMetadataResource::Uninitialize()
+{
+    UC_SRCE_TRACE("DeviceMetadataResource::Uninitialize");
+    delete deviceMetadataObject;
+    deviceMetadataObject = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/FirmwareUpdateResource.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,448 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-lwm2m/FirmwareUpdateResource.h"
+
+#include "update-client-common/arm_uc_common.h"
+#include "source/update_client_hub_state_machine.h"
+#include "source/update_client_hub_error_handler.h"
+
+#include <stdio.h>
+
+#define ARM_UCS_LWM2M_INTERNAL_ERROR (-1)
+#define ARM_UCS_LWM2M_INTERNAL_SUCCESS (0)
+
+namespace FirmwareUpdateResource {
+
+    /* send delayed response */
+    enum {
+        ResourcePackage,
+        ResourcePackageURI,
+        ResourceUpdate
+    };
+
+    static void packageCallback(void* _parameters);
+    static void packageURICallback(void* _parameters);
+    static void updateCallback(void*);
+    static void notificationCallback(const M2MBase& object, NotificationDeliveryStatus delivery_status, void* client_args);
+    static void sendDelayedResponseTask(uint32_t parameter);
+
+    /* LWM2M Firmware Update Object */
+    static M2MObject* updateObject;
+
+    /* LWM2M Firmware Update Object resources */
+    static M2MResource* resourcePackage = NULL;
+    static M2MResource* resourcePackageURI = NULL;
+    static M2MResource* resourceUpdate = NULL;
+    static M2MResource* resourceState = NULL;
+    static M2MResource* resourceResult = NULL;
+    static M2MResource* resourceName = NULL;
+    static M2MResource* resourceVersion = NULL;
+
+    /* function pointers to callback functions */
+    static void (*externalPackageCallback)(const uint8_t* buffer, uint16_t length) = NULL;
+    static void (*externalPackageURICallback)(const uint8_t* buffer, uint16_t length) = NULL;
+    static void (*externalUpdateCallback)(void) = NULL;
+    static void (*externalNotificationCallback)(void) = NULL;
+
+    /* Callback structs for delayed response.
+     *
+     * There needs to be one per callback type to avoid collisions between different operations.
+     */
+    static arm_uc_callback_t callbackNodePackage = { NULL, 0, NULL, 0 };
+    static arm_uc_callback_t callbackNodePackageURI = { NULL, 0, NULL, 0 };
+    static arm_uc_callback_t callbackNodeResourceUpdate = { NULL, 0, NULL, 0 };
+}
+
+/**
+ * @brief Initialize LWM2M Firmware Update Object
+ * @details Sets up LWM2M object with accompanying resources.
+ */
+void FirmwareUpdateResource::Initialize(void)
+{
+    static bool initialized = false;
+
+    if (!initialized)
+    {
+        initialized = true;
+
+        /* The LWM2M Firmware Update Object is at /5 */
+        updateObject = M2MInterfaceFactory::create_object("5");
+
+        if (updateObject)
+        {
+            /* Create first (and only) instance /5/0 */
+            M2MObjectInstance* updateInstance = updateObject->create_object_instance();
+
+            if (updateInstance)
+            {
+                /* Set observable so the Portal can read it */
+                updateInstance->set_observable(true);
+
+                /* Default values are non-standard, but the standard has no
+                   values for indicating that the device is initializing.
+                   To address this, Service ignores -1 and/or 255 values coming through,
+                   so for our purposes this is the correct form of initialization.
+                */
+                uint8_t defaultValue[] = {"-1"};
+                uint8_t defaultVersion[] = {"-1"};
+
+                /* Create Package resource /5/0/0 */
+                resourcePackage = updateInstance->create_dynamic_resource(
+                                    "0", "Package", M2MResourceInstance::OPAQUE, false);
+                if (resourcePackage)
+                {
+                    /* This should be PUT according to the standard but
+                       Connector client doesn't support callbacks for PUT.
+                    */
+                    resourcePackage->set_operation(M2MBase::POST_ALLOWED);
+                    resourcePackage->set_execute_function(packageCallback);
+
+                    /* The delayed response if for processing heavier loads */
+                    resourcePackage->set_delayed_response(true);
+                }
+
+                /* Create Package URI resource /5/0/1 */
+                resourcePackageURI = updateInstance->create_dynamic_resource(
+                                    "1", "PackageURI", M2MResourceInstance::STRING, false);
+                if (resourcePackageURI)
+                {
+                    resourcePackageURI->set_operation(M2MBase::POST_ALLOWED);
+                    resourcePackageURI->set_execute_function(packageURICallback);
+                    resourcePackageURI->set_delayed_response(true);
+                }
+
+                /* Create Update resource /5/0/2 */
+                resourceUpdate = updateInstance->create_dynamic_resource(
+                                    "2", "Update", M2MResourceInstance::BOOLEAN, false);
+                if (resourceUpdate)
+                {
+                    resourceUpdate->set_operation(M2MBase::POST_ALLOWED);
+                    resourceUpdate->set_execute_function(updateCallback);
+                    resourceUpdate->set_delayed_response(true);
+                }
+
+                /* Create State resource /5/0/3 */
+                resourceState = updateInstance->create_dynamic_resource(
+                                    "3", "State", M2MResourceInstance::INTEGER, true);
+                if (resourceState)
+                {
+                    resourceState->set_operation(M2MBase::GET_ALLOWED);
+                    resourceState->set_notification_delivery_status_cb(notificationCallback, NULL);
+                    resourceState->set_value(defaultValue, sizeof(defaultValue) - 1);
+                }
+
+                /* Create Update Result resource /5/0/5 */
+                resourceResult = updateInstance->create_dynamic_resource(
+                                    "5", "UpdateResult", M2MResourceInstance::INTEGER, true);
+                if (resourceResult)
+                {
+                    resourceResult->set_operation(M2MBase::GET_ALLOWED);
+                    resourceResult->set_notification_delivery_status_cb(notificationCallback, NULL);
+                    resourceResult->set_value(defaultValue, sizeof(defaultValue) - 1);
+                }
+
+                /* Create PkgName resource /5/0/6 */
+                resourceName = updateInstance->create_dynamic_resource(
+                                    "6", "PkgName", M2MResourceInstance::STRING, true);
+                if (resourceName)
+                {
+                    resourceName->set_operation(M2MBase::GET_ALLOWED);
+                    resourceName->set_value(defaultVersion, sizeof(defaultVersion) - 1);
+                }
+
+                /* Create PkgVersion resource /5/0/7 */
+                resourceVersion = updateInstance->create_dynamic_resource(
+                                    "7", "PkgVersion", M2MResourceInstance::STRING, true);
+                if (resourceVersion)
+                {
+                    resourceVersion->set_operation(M2MBase::GET_ALLOWED);
+                    resourceVersion->set_value(defaultVersion, sizeof(defaultVersion) - 1);
+                }
+            }
+        }
+    }
+}
+
+M2MObject* FirmwareUpdateResource::getObject()
+{
+    Initialize();
+
+    return updateObject;
+}
+
+void FirmwareUpdateResource::packageCallback(void* _parameters)
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::packageCallback");
+
+    if (_parameters && externalPackageCallback)
+    {
+        /* recast parameter */
+        M2MResource::M2MExecuteParameter* parameters =
+            static_cast<M2MResource::M2MExecuteParameter*>(_parameters);
+
+        /* read payload */
+        const uint8_t* buffer = parameters->get_argument_value();
+        uint16_t length = parameters->get_argument_value_length();
+
+        /* invoke external callback function */
+        externalPackageCallback(buffer, length);
+
+        /* schedule delayed response */
+        ARM_UC_PostCallback(&callbackNodePackage,
+                            FirmwareUpdateResource::sendDelayedResponseTask,
+                            FirmwareUpdateResource::ResourcePackage);
+    }
+}
+
+void FirmwareUpdateResource::packageURICallback(void* _parameters)
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::packageURICallback");
+
+    if (_parameters && externalPackageURICallback)
+    {
+        /* recast parameter */
+        M2MResource::M2MExecuteParameter* parameters =
+            static_cast<M2MResource::M2MExecuteParameter*>(_parameters);
+
+        /* read payload */
+        const uint8_t* buffer = parameters->get_argument_value();
+        uint16_t length = parameters->get_argument_value_length();
+
+        /* invoke external callback function */
+        externalPackageURICallback(buffer, length);
+
+        /* schedule delayed response */
+        ARM_UC_PostCallback(&callbackNodePackageURI,
+                            FirmwareUpdateResource::sendDelayedResponseTask,
+                            FirmwareUpdateResource::ResourcePackageURI);
+    }
+}
+
+void FirmwareUpdateResource::updateCallback(void* _parameters)
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::updateCallback");
+
+    (void) _parameters;
+
+    if (externalUpdateCallback)
+    {
+        /* invoke external callback function */
+        externalUpdateCallback();
+
+        /* schedule delayed response */
+        ARM_UC_PostCallback(&callbackNodeResourceUpdate,
+                            FirmwareUpdateResource::sendDelayedResponseTask,
+                            FirmwareUpdateResource::ResourceUpdate);
+    }
+}
+
+void FirmwareUpdateResource::notificationCallback(const M2MBase& base,
+                                                  const NotificationDeliveryStatus delivery_status,
+                                                  void *client_args)
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::notificationCallback status: %d", delivery_status);
+
+    if (delivery_status == NOTIFICATION_STATUS_DELIVERED) {
+        // Notification has been ACKed by server, complete to callback
+        UC_SRCE_TRACE("FirmwareUpdateResource::notificationCallback DELIVERED");
+
+        if (externalNotificationCallback) {
+            externalNotificationCallback();
+        }
+
+    }
+    else if (delivery_status == NOTIFICATION_STATUS_BUILD_ERROR ||
+             delivery_status == NOTIFICATION_STATUS_RESEND_QUEUE_FULL ||
+             delivery_status == NOTIFICATION_STATUS_SEND_FAILED ||
+             delivery_status == NOTIFICATION_STATUS_UNSUBSCRIBED) {
+        // Error case, notification not reaching service
+        // We are sending out error because we cannot rely connection is
+        // anymore up and the service and client are not in sync anymore.
+        // Also sending new notifications after this might lock event
+        // machine because comms cannot service us anymore.
+        UC_SRCE_ERR_MSG("Received Notification delivery status: %d - ERROR!", delivery_status);
+        ARM_UC_HUB_ErrorHandler(HUB_ERR_CONNECTION, ARM_UC_HUB_getState());
+
+    }
+    else {
+        // NOTIFICATION_STATUS_INIT
+        // NOTIFICATION_STATUS_SENT
+        // NOTIFICATION_STATUS_SUBSCRIBED
+        UC_SRCE_TRACE("FirmwareUpdateResource::notificationCallback Status ignored, waiting delivery...");
+    }
+}
+
+void FirmwareUpdateResource::sendDelayedResponseTask(uint32_t parameter)
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::sendDelayedResponseTask");
+
+    switch (parameter)
+    {
+        case FirmwareUpdateResource::ResourcePackage:
+            UC_SRCE_TRACE("resourcePackage->send_delayed_post_response");
+            resourcePackage->send_delayed_post_response();
+            break;
+        case FirmwareUpdateResource::ResourcePackageURI:
+            UC_SRCE_TRACE("resourcePackageURI->send_delayed_post_response");
+            resourcePackageURI->send_delayed_post_response();
+            break;
+        case FirmwareUpdateResource::ResourceUpdate:
+            UC_SRCE_TRACE("resourceUpdate->send_delayed_post_response");
+            resourceUpdate->send_delayed_post_response();
+            break;
+        default:
+            UC_SRCE_ERR_MSG("unsupported resource");
+            break;
+    }
+}
+
+/*****************************************************************************/
+/* Update Client Source                                                      */
+/*****************************************************************************/
+
+/* Add callback for resource /5/0/0, Package */
+int32_t FirmwareUpdateResource::addPackageCallback(void (*cb)(const uint8_t* buffer, uint16_t length))
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::addPackageCallback: %p", cb);
+
+    externalPackageCallback = cb;
+
+    return ARM_UCS_LWM2M_INTERNAL_SUCCESS;
+}
+
+/* Add callback for resource /5/0/1, Package URI */
+int32_t FirmwareUpdateResource::addPackageURICallback(void (*cb)(const uint8_t* buffer, uint16_t length))
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::addPackageURICallback: %p", cb);
+
+    externalPackageURICallback = cb;
+
+    return ARM_UCS_LWM2M_INTERNAL_SUCCESS;
+}
+
+/* Add callback for resource /5/0/2, Update */
+int32_t FirmwareUpdateResource::addUpdateCallback(void (*cb)(void))
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::addUpdateCallback: %p", cb);
+
+    externalUpdateCallback = cb;
+
+    return ARM_UCS_LWM2M_INTERNAL_SUCCESS;
+}
+
+/* Add callback for when send{State, UpdateResult} is done */
+int32_t FirmwareUpdateResource::addNotificationCallback(void (*cb)(void))
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::addNotificationCallback: %p", cb);
+
+    externalNotificationCallback = cb;
+
+    return ARM_UCS_LWM2M_INTERNAL_SUCCESS;
+}
+
+/*****************************************************************************/
+/* Update Client Status                                                      */
+/*****************************************************************************/
+
+/* Send state for resource /5/0/3, State */
+int32_t FirmwareUpdateResource::sendState(arm_ucs_lwm2m_state_t state)
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::sendState");
+
+    int32_t result = ARM_UCS_LWM2M_INTERNAL_ERROR;
+
+    if (state <= ARM_UCS_LWM2M_STATE_LAST)
+    {
+        /* valid states: 0-3 */
+        uint8_t value[2];
+        snprintf((char*)value, 2, "%d", state);
+        resourceState->set_value(value, 1);
+
+        result = ARM_UCS_LWM2M_INTERNAL_SUCCESS;
+    }
+
+    return result;
+}
+
+/* Send result for resource /5/0/5, Update Result */
+int32_t FirmwareUpdateResource::sendUpdateResult(arm_ucs_lwm2m_result_t updateResult)
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::sendUpdateResult");
+
+    int32_t result = ARM_UCS_LWM2M_INTERNAL_ERROR;
+
+    if (updateResult <= ARM_UCS_LWM2M_RESULT_LAST)
+    {
+        /* valid results: 0-8 */
+        uint8_t value[2];
+        snprintf((char*)value, 2, "%d", updateResult);
+        resourceResult->set_value(value, 1);
+
+        result = ARM_UCS_LWM2M_INTERNAL_SUCCESS;
+    }
+
+    return result;
+}
+
+/* Send name for resource /5/0/6 PkgName */
+int32_t FirmwareUpdateResource::sendPkgName(const uint8_t* name, uint16_t length)
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::sendPkgName");
+
+    int32_t result = ARM_UCS_LWM2M_INTERNAL_ERROR;
+
+    /* the maximum length is defined in the OMA LWM2M standard. */
+    if ((name != NULL) && (length <= 255))
+    {
+        uint8_t value[64] = { 0 };
+        uint8_t index = 0;
+
+        /* convert to printable characters using lookup table */
+        for ( ; (index < 32) && (index < length); index++)
+        {
+            value[2 * index    ] = arm_uc_hex_table[name[index] >> 4];
+            value[2 * index + 1] = arm_uc_hex_table[name[index] & 0x0F];
+        }
+
+        resourceName->set_value(value, 2 * index);
+
+        result = ARM_UCS_LWM2M_INTERNAL_SUCCESS;
+    }
+
+    return result;
+}
+
+/* Send version for resource /5/0/7, PkgVersion */
+int32_t FirmwareUpdateResource::sendPkgVersion(uint64_t version)
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::sendPkgVersion");
+
+    uint8_t value[21] = { 0 };
+    uint8_t length = snprintf((char*) value, 21, "%llu" , version);
+    resourceVersion->set_value(value, length);
+
+    return ARM_UCS_LWM2M_INTERNAL_SUCCESS;
+}
+
+void FirmwareUpdateResource::Uninitialize(void)
+{
+    UC_SRCE_TRACE("FirmwareUpdateResource::Uninitialize"); 
+    delete updateObject;
+    updateObject = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/lwm2m-control.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,41 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-lwm2m/lwm2m-control.h"
+#include "update-client-lwm2m/FirmwareUpdateResource.h"
+
+/**
+ * @brief Set callback function for externally triggering an update.
+ * @details The callback function is called when an external trigger
+ *          is fired. The callback function should force an update.
+ *
+ * @param callback Function pointer.
+ */
+arm_uc_error_t ARM_UC_CONTROL_SetOverrideCallback(void (*callback)(void))
+{
+    ARM_UC_INIT_ERROR(retval, ERR_INVALID_PARAMETER);
+
+    int32_t result = FirmwareUpdateResource::addUpdateCallback(callback);
+
+    if (result == 0)
+    {
+        retval.code = ERR_NONE;
+    }
+
+    return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/lwm2m-monitor.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,324 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-lwm2m-mbed-apis.h"
+#include "update-client-lwm2m/lwm2m-monitor.h"
+#include "update-client-lwm2m/FirmwareUpdateResource.h"
+#include "update-client-lwm2m/DeviceMetadataResource.h"
+
+/**
+ * @brief Get driver version.
+ * @return Driver version.
+ */
+uint32_t ARM_UCS_LWM2M_MONITOR_GetVersion(void)
+{
+    return 0;
+}
+
+/**
+ * @brief Get Source capabilities.
+ * @return Struct containing capabilites. See definition above.
+ */
+ARM_MONITOR_CAPABILITIES ARM_UCS_LWM2M_MONITOR_GetCapabilities(void)
+{
+    ARM_MONITOR_CAPABILITIES result;
+    result.state   = 1;
+    result.result  = 1;
+    result.version = 1;
+
+   return result;
+}
+
+/**
+ * @brief Initialize Monitor.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_Initialize(void (*notification_handler)(void))
+{
+    ARM_UC_INIT_ERROR(retval, SRCE_ERR_NONE);
+
+    FirmwareUpdateResource::Initialize();
+    FirmwareUpdateResource::addNotificationCallback(notification_handler);
+
+    DeviceMetadataResource::Initialize();
+
+    return retval;
+}
+
+/**
+ * @brief Uninitialized Monitor.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_Uninitialize(void)
+{
+    ARM_UC_INIT_ERROR(retval, SRCE_ERR_NONE);
+
+    return retval;
+}
+
+/**
+ * @brief Send Update Client state.
+ * @details From the OMA LWM2M Technical Specification:
+ *
+ *          Indicates current state with respect to this firmware update.
+ *          This value is set by the LWM2M Client.
+ *          0: Idle (before downloading or after successful updating)
+ *          1: Downloading (The data sequence is on the way)
+ *          2: Downloaded
+ *          3: Updating
+ *
+ *          If writing the firmware package to Package Resource is done,
+ *          or, if the device has downloaded the firmware package from the
+ *          Package URI the state changes to Downloaded.
+ *
+ *          If writing an empty string to Package Resource is done or
+ *          writing an empty string to Package URI is done, the state
+ *          changes to Idle.
+ *
+ *          When in Downloaded state, and the executable Resource Update is
+ *          triggered, the state changes to Updating.
+ *          If the Update Resource failed, the state returns at Downloaded.
+ *          If performing the Update Resource was successful, the state
+ *          changes from Updating to Idle.
+ *
+ * @param state Valid states: ARM_UC_MONITOR_STATE_IDLE
+ *                            ARM_UC_MONITOR_STATE_DOWNLOADING
+ *                            ARM_UC_MONITOR_STATE_DOWNLOADED
+ *                            ARM_UC_MONITOR_STATE_UPDATING
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_SendState(arm_uc_monitor_state_t state)
+{
+    ARM_UC_INIT_ERROR(result, ERR_INVALID_PARAMETER);
+
+    int32_t retval = -1;
+
+    switch (state)
+    {
+        case ARM_UC_MONITOR_STATE_IDLE:
+            retval = FirmwareUpdateResource::sendState(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_STATE_IDLE);
+            break;
+        case ARM_UC_MONITOR_STATE_DOWNLOADING:
+            retval = FirmwareUpdateResource::sendState(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_STATE_DOWNLOADING);
+            break;
+        case ARM_UC_MONITOR_STATE_DOWNLOADED:
+            retval = FirmwareUpdateResource::sendState(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_STATE_DOWNLOADED);
+            break;
+        case ARM_UC_MONITOR_STATE_UPDATING:
+            retval = FirmwareUpdateResource::sendState(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_STATE_UPDATING);
+            break;
+        default:
+            break;
+    }
+
+    if (retval == 0)
+    {
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Send update result.
+ * @details From the OMA LWM2M Technical Specification:
+ *
+ *          Contains the result of downloading or updating the firmware
+ *          0: Initial value. Once the updating process is initiated
+ *             (Download /Update), this Resource MUST be reset to Initial
+ *             value.
+ *          1: Firmware updated successfully,
+ *          2: Not enough storage for the new firmware package.
+ *          3. Out of memory during downloading process.
+ *          4: Connection lost during downloading process.
+ *          5: CRC check failure for new downloaded package.
+ *          6: Unsupported package type.
+ *          7: Invalid URI
+ *          8: Firmware update failed
+ *
+ *          This Resource MAY be reported by sending Observe operation.
+ *
+ * @param result Valid results: ARM_UC_MONITOR_RESULT_INITIAL
+ *                              ARM_UC_MONITOR_RESULT_SUCCESS
+ *                              ARM_UC_MONITOR_RESULT_ERROR_STORAGE
+ *                              ARM_UC_MONITOR_RESULT_ERROR_MEMORY
+ *                              ARM_UC_MONITOR_RESULT_ERROR_CONNECTION
+ *                              ARM_UC_MONITOR_RESULT_ERROR_CRC
+ *                              ARM_UC_MONITOR_RESULT_ERROR_TYPE
+ *                              ARM_UC_MONITOR_RESULT_ERROR_URI
+ *                              ARM_UC_MONITOR_RESULT_ERROR_UPDATE
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_SendUpdateResult(arm_uc_monitor_result_t updateResult)
+{
+    ARM_UC_INIT_ERROR(result, ERR_INVALID_PARAMETER);
+
+    int32_t retval = -1;
+
+    switch (updateResult)
+    {
+        case ARM_UC_MONITOR_RESULT_INITIAL:
+            retval = FirmwareUpdateResource::sendUpdateResult(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_RESULT_INITIAL);
+            break;
+        case ARM_UC_MONITOR_RESULT_SUCCESS:
+            retval = FirmwareUpdateResource::sendUpdateResult(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_RESULT_SUCCESS);
+            break;
+        case ARM_UC_MONITOR_RESULT_ERROR_STORAGE:
+            retval = FirmwareUpdateResource::sendUpdateResult(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_RESULT_ERROR_STORAGE);
+            break;
+        case ARM_UC_MONITOR_RESULT_ERROR_MEMORY:
+            retval = FirmwareUpdateResource::sendUpdateResult(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_RESULT_ERROR_MEMORY);
+            break;
+        case ARM_UC_MONITOR_RESULT_ERROR_CONNECTION:
+            retval = FirmwareUpdateResource::sendUpdateResult(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_RESULT_ERROR_CONNECTION);
+            break;
+        case ARM_UC_MONITOR_RESULT_ERROR_CRC:
+            retval = FirmwareUpdateResource::sendUpdateResult(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_RESULT_ERROR_CRC);
+            break;
+        case ARM_UC_MONITOR_RESULT_ERROR_TYPE:
+            retval = FirmwareUpdateResource::sendUpdateResult(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_RESULT_ERROR_TYPE);
+            break;
+        case ARM_UC_MONITOR_RESULT_ERROR_URI:
+            retval = FirmwareUpdateResource::sendUpdateResult(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_RESULT_ERROR_URI);
+            break;
+        case ARM_UC_MONITOR_RESULT_ERROR_UPDATE:
+            retval = FirmwareUpdateResource::sendUpdateResult(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_RESULT_ERROR_UPDATE);
+            break;
+        case ARM_UC_MONITOR_RESULT_ERROR_HASH:
+            retval = FirmwareUpdateResource::sendUpdateResult(
+                FirmwareUpdateResource::ARM_UCS_LWM2M_RESULT_ERROR_HASH);
+            break;
+        default:
+            break;
+    }
+
+    if (retval == 0)
+    {
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Send current firmware name.
+ * @details The firmware name is the SHA256 hash.
+ *
+ * @param name Pointer to buffer struct. Hash is stored as byte array.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_SendName(arm_uc_buffer_t* name)
+{
+    ARM_UC_INIT_ERROR(result, ERR_INVALID_PARAMETER);
+
+    int32_t retval = -1;
+
+    if (name && name->ptr)
+    {
+        retval = FirmwareUpdateResource::sendPkgName(name->ptr, name->size);
+    }
+
+    if (retval == 0)
+    {
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Send current firmware version.
+ * @details The firmware version is the timestamp from the manifest that
+ *          authorized the firmware.
+ *
+ * @param version Timestamp, 64 bit unsigned integer.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_SendVersion(uint64_t version)
+{
+    ARM_UC_INIT_ERROR(result, ERR_INVALID_PARAMETER);
+
+    int32_t retval = FirmwareUpdateResource::sendPkgVersion(version);
+
+    if (retval == 0)
+    {
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set the bootloader hash.
+ * @details The bootloader hash is a hash of the bootloader. This is
+ *          used for tracking the version of the bootloader used.
+ *
+ * @param name Pointer to buffer struct. Hash is stored as byte array.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_SetBootloaderHash(arm_uc_buffer_t* hash)
+{
+    ARM_UC_INIT_ERROR(result, ERR_INVALID_PARAMETER);
+
+    int32_t retval = DeviceMetadataResource::setBootloaderHash(hash);
+
+    if (retval == 0)
+    {
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set the OEM bootloader hash.
+ * @details If the end-user has modified the bootloader the hash of the
+ *          modified bootloader can be set here.
+ *
+ * @param name Pointer to buffer struct. Hash is stored as byte array.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_SetOEMBootloaderHash(arm_uc_buffer_t* hash)
+{
+    ARM_UC_INIT_ERROR(result, ERR_INVALID_PARAMETER);
+
+    int32_t retval = DeviceMetadataResource::setOEMBootloaderHash(hash);
+
+    if (retval == 0)
+    {
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/lwm2m-source.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,392 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-lwm2m-mbed-apis.h"
+#include "update-client-common/arm_uc_common.h"
+#include "update-client-lwm2m/lwm2m-source.h"
+#include "update-client-lwm2m/FirmwareUpdateResource.h"
+#include "update-client-lwm2m/DeviceMetadataResource.h"
+
+
+/* forward declaration */
+static void ARM_UCS_PackageCallback(const uint8_t* buffer, uint16_t length);
+
+/* local copy of the received manifest */
+static uint8_t* arm_ucs_manifest_buffer = NULL;
+static uint16_t arm_ucs_manifest_length = 0;
+
+/* callback function pointer and struct */
+static void (*ARM_UCS_EventHandler)(uint32_t event) = 0;
+static arm_uc_callback_t callbackNodeManifest = { NULL, 0, NULL, 0 };
+static arm_uc_callback_t callbackNodeNotification = { NULL, 0, NULL, 0 };
+
+/**
+ * @brief Get driver version.
+ * @return Driver version.
+ */
+uint32_t ARM_UCS_LWM2M_SOURCE_GetVersion(void)
+{
+    return 0;
+}
+
+/**
+ * @brief Get Source capabilities.
+ * @return Struct containing capabilites. See definition above.
+ */
+ARM_SOURCE_CAPABILITIES ARM_UCS_LWM2M_SOURCE_GetCapabilities(void)
+{
+    ARM_SOURCE_CAPABILITIES result;
+    result.notify = 0;
+    result.manifest_default = 0;
+    result.manifest_url = 0;
+    result.firmware = 0;
+    result.keytable = 0;
+
+    /* the event handler must be set before module can be used */
+    if (ARM_UCS_EventHandler != 0)
+    {
+        result.notify = 1;
+        result.manifest_default = 1;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Initialize Source.
+ * @details Function pointer to event handler is passed as argument.
+ *
+ * @param cb_event Function pointer to event handler. See events above.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_Initialize(ARM_SOURCE_SignalEvent_t cb_event)
+{
+    UC_SRCE_TRACE("ARM_UCS_LWM2M_SOURCE_Initialize: %p", cb_event);
+    ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER);
+
+    if (cb_event != 0)
+    {
+        /* store callback handler */
+        ARM_UCS_EventHandler = cb_event;
+
+        /* Initialize LWM2M Firmware Update Object */
+        FirmwareUpdateResource::Initialize();
+
+        /* Register callback handler */
+        FirmwareUpdateResource::addPackageCallback(ARM_UCS_PackageCallback);
+
+        DeviceMetadataResource::Initialize();
+
+        ARM_UC_SET_ERROR(result, SRCE_ERR_NONE);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Uninitialized Source.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_Uninitialize(void)
+{
+    ARM_UC_INIT_ERROR(retval, SRCE_ERR_NONE);
+    DeviceMetadataResource::Uninitialize();
+    FirmwareUpdateResource::Uninitialize();
+
+    return retval;
+}
+
+/**
+ * @brief Cost estimation for retrieving manifest from the default location.
+ * @details The estimation can vary over time and should not be cached too long.
+ *          0x00000000 - The manifest is already downloaded.
+ *          0xFFFFFFFF - Cannot retrieve manifest from this Source.
+ *
+ * @param cost Pointer to variable for the return value.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestDefaultCost(uint32_t* cost)
+{
+    ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER);
+
+    if (cost != 0)
+    {
+        /* set cost to 0 when manifest is cached */
+        if (arm_ucs_manifest_buffer && arm_ucs_manifest_length)
+        {
+            *cost = 0;
+        }
+        /* set cost to 0xFFFFFFFF when manifest has been read */
+        else
+        {
+            *cost = 0xFFFFFFFF;
+        }
+
+        ARM_UC_SET_ERROR(result, SRCE_ERR_NONE);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Retrieve manifest from the default location.
+ * @details Manifest is stored in supplied buffer.
+ *          Event is generated once manifest is in buffer.
+ *
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestDefault(arm_uc_buffer_t* buffer,
+                                                       uint32_t offset)
+{
+    ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER);
+
+    /* copy manifest from cache into buffer */
+    if ((buffer != NULL) &&
+        (buffer->ptr != NULL) &&
+        (arm_ucs_manifest_buffer != NULL) &&
+        (arm_ucs_manifest_length != 0) &&
+        (offset < arm_ucs_manifest_length))
+    {
+        /* remaining length based on offset request */
+        uint16_t length = arm_ucs_manifest_length - offset;
+
+        /* set actual length based on buffer size */
+        if (length > buffer->size_max)
+        {
+            length = buffer->size_max;
+        }
+
+        /* size check */
+        if (length > 0)
+        {
+            /* copy manifest from local buffer to external buffer */
+            memcpy(buffer->ptr, &arm_ucs_manifest_buffer[offset], length);
+            buffer->size = length;
+
+            /* delete local buffer once the entire manifest has been read */
+            if (offset + length >= arm_ucs_manifest_length)
+            {
+                delete[] arm_ucs_manifest_buffer;
+                arm_ucs_manifest_buffer = NULL;
+                arm_ucs_manifest_length = 0;
+            }
+
+            ARM_UC_SET_ERROR(result, SRCE_ERR_NONE);
+
+            /* signal event handler that manifest has been copied to buffer */
+            if (ARM_UCS_EventHandler)
+            {
+                ARM_UC_PostCallback(&callbackNodeManifest,
+                                    ARM_UCS_EventHandler,
+                                    EVENT_MANIFEST);
+            }
+        }
+    }
+
+    return result;
+}
+
+static void ARM_UCS_PackageCallback(const uint8_t* buffer, uint16_t length)
+{
+    uint32_t event_code = EVENT_ERROR;
+
+    if (arm_ucs_manifest_buffer)
+    {
+        UC_SRCE_ERR_MSG("received new manifest before reading the old one");
+
+        /* delete old buffer to make space for the new one */
+        delete[] arm_ucs_manifest_buffer;
+        arm_ucs_manifest_length = 0;
+    }
+
+    /* allocate a local buffer of the same size as the manifest */
+    arm_ucs_manifest_buffer = new uint8_t[length];
+
+    if (arm_ucs_manifest_buffer)
+    {
+        /* copy manifest from payload to local buffer */
+        memcpy(arm_ucs_manifest_buffer, buffer, length);
+        arm_ucs_manifest_length = length;
+
+        event_code = EVENT_NOTIFICATION;
+    }
+
+    /* signal event handler with result */
+    if (ARM_UCS_EventHandler)
+    {
+        ARM_UC_PostCallback(&callbackNodeNotification,
+                            ARM_UCS_EventHandler,
+                            event_code);
+    }
+}
+
+/*****************************************************************************/
+/* Capabilities not supported by this source                                 */
+/*****************************************************************************/
+
+/**
+ * @brief Cost estimation for retrieving manifest from URL.
+ * @details The estimation can vary over time and should not be cached too long.
+ *          0x00000000 - The manifest is already downloaded.
+ *          0xFFFFFFFF - Cannot retrieve manifest from this Source.
+ *
+ * @param uri URI struct with manifest location.
+ * @param cost Pointer to variable for the return value.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestURLCost(arm_uc_uri_t* uri,
+                                                       uint32_t* cost)
+{
+    (void) uri;
+    (void) cost;
+
+    ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER);
+
+    /* not supported - return default cost regardless of actual uri location */
+    if (cost)
+    {
+        *cost = 0xFFFFFFFF;
+        ARM_UC_SET_ERROR(result, SRCE_ERR_NONE);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Cost estimation for retrieving firmware from URL.
+ * @details The estimation can vary over time and should not be cached too long.
+ *          0x00000000 - The firmware is already downloaded.
+ *          0xFFFFFFFF - Cannot retrieve firmware from this Source.
+ *
+ * @param uri URI struct with firmware location.
+ * @param cost Pointer to variable for the return value.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost(arm_uc_uri_t* uri,
+                                                       uint32_t* cost)
+{
+    (void) uri;
+    (void) cost;
+
+    ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER);
+
+    /* not supported - return default cost regardless of actual uri location */
+    if (cost != 0)
+    {
+        *cost = 0xFFFFFFFF;
+        ARM_UC_SET_ERROR(result, SRCE_ERR_NONE);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Cost estimation for retrieving key table from URL.
+ * @details The estimation can vary over time and should not be cached too long.
+ *          0x00000000 - The firmware is already downloaded.
+ *          0xFFFFFFFF - Cannot retrieve firmware from this Source.
+ *
+ * @param uri URI struct with keytable location.
+ * @param cost Pointer to variable for the return value.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetKeytableURLCost(arm_uc_uri_t* uri,
+                                                       uint32_t* cost)
+{
+    (void) uri;
+    (void) cost;
+
+    ARM_UC_INIT_ERROR(result, SRCE_ERR_INVALID_PARAMETER);
+
+    /* not supported - return default cost regardless of actual uri location */
+    if ((uri != 0) && (cost != 0))
+    {
+        *cost = 0xFFFFFFFF;
+        ARM_UC_SET_ERROR(result, SRCE_ERR_NONE);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Retrieve manifest from URL.
+ * @details Manifest is stored in supplied buffer.
+ *          Event is generated once manifest is in buffer.
+ *
+ * @param uri URI struct with manifest location.
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestURL(arm_uc_uri_t* uri,
+                                                   arm_uc_buffer_t* buffer,
+                                                   uint32_t offset)
+{
+    (void) uri;
+    (void) buffer;
+    (void) offset;
+
+    ARM_UC_INIT_ERROR(retval, SRCE_ERR_INVALID_PARAMETER);
+
+    return retval;
+}
+
+/**
+ * @brief Retrieve firmware fragment.
+ * @details Firmware fragment is stored in supplied buffer.
+ *          Event is generated once fragment is in buffer.
+ *
+ * @param uri URI struct with firmware location.
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ * @param offset Firmware offset to retrieve fragment from.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment(arm_uc_uri_t* uri,
+                                                        arm_uc_buffer_t* buffer,
+                                                        uint32_t offset)
+{
+    (void) uri;
+    (void) buffer;
+    (void) offset;
+
+    ARM_UC_INIT_ERROR(retval, SRCE_ERR_INVALID_PARAMETER);
+
+    return retval;
+}
+
+/**
+ * @brief Retrieve a key table from a URL.
+ * @details Key table is stored in supplied buffer.
+ *          Event is generated once fragment is in buffer.
+ *
+ * @param uri URI struct with keytable location.
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetKeytableURL(arm_uc_uri_t* uri,
+                                                   arm_uc_buffer_t* buffer)
+{
+    (void) uri;
+    (void) buffer;
+
+    ARM_UC_INIT_ERROR(retval, SRCE_ERR_INVALID_PARAMETER);
+
+    return retval;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/update-lwm2m-mbed-apis.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,36 @@
+#include "update-client-lwm2m/lwm2m-monitor.h"
+#include "update-client-lwm2m/lwm2m-source.h"
+#include "update-lwm2m-mbed-apis.h"
+
+
+ARM_UPDATE_MONITOR ARM_UCS_LWM2M_MONITOR =
+{
+    .GetVersion           = ARM_UCS_LWM2M_MONITOR_GetVersion,
+    .GetCapabilities      = ARM_UCS_LWM2M_MONITOR_GetCapabilities,
+    .Initialize           = ARM_UCS_LWM2M_MONITOR_Initialize,
+    .Uninitialize         = ARM_UCS_LWM2M_MONITOR_Uninitialize,
+
+    .SendState            = ARM_UCS_LWM2M_MONITOR_SendState,
+    .SendUpdateResult     = ARM_UCS_LWM2M_MONITOR_SendUpdateResult,
+    .SendName             = ARM_UCS_LWM2M_MONITOR_SendName,
+    .SendVersion          = ARM_UCS_LWM2M_MONITOR_SendVersion,
+
+    .SetBootloaderHash    = ARM_UCS_LWM2M_MONITOR_SetBootloaderHash,
+    .SetOEMBootloaderHash = ARM_UCS_LWM2M_MONITOR_SetOEMBootloaderHash
+};
+
+ARM_UPDATE_SOURCE ARM_UCS_LWM2M_SOURCE =
+{
+    .GetVersion             = ARM_UCS_LWM2M_SOURCE_GetVersion,
+    .GetCapabilities        = ARM_UCS_LWM2M_SOURCE_GetCapabilities,
+    .Initialize             = ARM_UCS_LWM2M_SOURCE_Initialize,
+    .Uninitialize           = ARM_UCS_LWM2M_SOURCE_Uninitialize,
+    .GetManifestDefaultCost = ARM_UCS_LWM2M_SOURCE_GetManifestDefaultCost,
+    .GetManifestURLCost     = ARM_UCS_LWM2M_SOURCE_GetManifestURLCost,
+    .GetFirmwareURLCost     = ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost,
+    .GetKeytableURLCost     = ARM_UCS_LWM2M_SOURCE_GetKeytableURLCost,
+    .GetManifestDefault     = ARM_UCS_LWM2M_SOURCE_GetManifestDefault,
+    .GetManifestURL         = ARM_UCS_LWM2M_SOURCE_GetManifestURL,
+    .GetFirmwareFragment    = ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment,
+    .GetKeytableURL         = ARM_UCS_LWM2M_SOURCE_GetKeytableURL
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/source/update-lwm2m-mbed-apis.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,74 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+/** @file update-lwm2m-mbed-apis.h
+ * @brief This file contains forward declarations for all functions used as
+ * APIS for the update client
+ * 
+ * @detail Because C++ does not support designated initialisers, this file is
+ * used to provide linkage from C++ to C structure initialisers. This pattern is
+ * necessary to ensure that the APIs are not brittle and prone to breakage if
+ * APIs are added or the API structure is changed.
+ */
+
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-monitor/arm_uc_monitor.h"
+#include "update-client-source/arm_uc_source.h"
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+uint32_t ARM_UCS_LWM2M_MONITOR_GetVersion(void);
+ARM_MONITOR_CAPABILITIES ARM_UCS_LWM2M_MONITOR_GetCapabilities(void);
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_Initialize(void (*notification_handler)(void));
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_Uninitialize(void);
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_SendState(arm_uc_monitor_state_t state);
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_SendUpdateResult(arm_uc_monitor_result_t updateResult);
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_SendName(arm_uc_buffer_t* name);
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_SendVersion(uint64_t version);
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_SetBootloaderHash(arm_uc_buffer_t* hash);
+arm_uc_error_t ARM_UCS_LWM2M_MONITOR_SetOEMBootloaderHash(arm_uc_buffer_t* hash);
+
+uint32_t ARM_UCS_LWM2M_SOURCE_GetVersion(void);
+ARM_SOURCE_CAPABILITIES ARM_UCS_LWM2M_SOURCE_GetCapabilities(void);
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_Initialize(ARM_SOURCE_SignalEvent_t cb_event);
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_Uninitialize(void);
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestDefaultCost(uint32_t* cost);
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestDefault(arm_uc_buffer_t* buffer,
+                                                       uint32_t offset);
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestURLCost(arm_uc_uri_t* uri,
+                                                       uint32_t* cost);
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetFirmwareURLCost(arm_uc_uri_t* uri,
+                                                       uint32_t* cost);
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetKeytableURLCost(arm_uc_uri_t* uri,
+                                                       uint32_t* cost);
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetManifestURL(arm_uc_uri_t* uri,
+                                                   arm_uc_buffer_t* buffer,
+                                                   uint32_t offset);
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetFirmwareFragment(arm_uc_uri_t* uri,
+                                                        arm_uc_buffer_t* buffer,
+                                                        uint32_t offset);
+arm_uc_error_t ARM_UCS_LWM2M_SOURCE_GetKeytableURL(arm_uc_uri_t* uri,
+                                                   arm_uc_buffer_t* buffer);                                                                                                                                                                                                                         
+
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/update-client-lwm2m/DeviceMetadataResource.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,42 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __ARM_UCS_DEVICE_METADATA_RESOURCE_H__
+#define __ARM_UCS_DEVICE_METADATA_RESOURCE_H__
+
+#include "update-client-common/arm_uc_common.h"
+
+#include "mbed-client/m2minterfacefactory.h"
+#include "mbed-client/m2mresource.h"
+#include "mbed-client/m2mobject.h"
+
+namespace DeviceMetadataResource {
+
+    void Initialize(void);
+    void Uninitialize(void);
+
+    M2MObject* getObject(void);
+
+    /* set bootloader hash resource /10255/0/1 */
+    int32_t setBootloaderHash(arm_uc_buffer_t* hash);
+
+    /* set OEM bootloader hash resource /10255/0/2 */
+    int32_t setOEMBootloaderHash(arm_uc_buffer_t* hash);
+}
+
+#endif // __ARM_UCS_DEVICE_METADATA_RESOURCE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/update-client-lwm2m/FirmwareUpdateResource.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,82 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __ARM_UCS_FIRMWARE_UPDATE_RESOURCE_H__
+#define __ARM_UCS_FIRMWARE_UPDATE_RESOURCE_H__
+
+#include "mbed-client/m2minterfacefactory.h"
+#include "mbed-client/m2mresource.h"
+#include "mbed-client/m2mobject.h"
+
+namespace FirmwareUpdateResource {
+
+    typedef enum {
+        ARM_UCS_LWM2M_STATE_FIRST       = 0,
+        ARM_UCS_LWM2M_STATE_IDLE        = ARM_UCS_LWM2M_STATE_FIRST,
+        ARM_UCS_LWM2M_STATE_DOWNLOADING = 1,
+        ARM_UCS_LWM2M_STATE_DOWNLOADED  = 2,
+        ARM_UCS_LWM2M_STATE_UPDATING    = 3,
+        ARM_UCS_LWM2M_STATE_LAST        = ARM_UCS_LWM2M_STATE_UPDATING
+    } arm_ucs_lwm2m_state_t;
+
+    typedef enum {
+        ARM_UCS_LWM2M_RESULT_FIRST            = 0,
+        ARM_UCS_LWM2M_RESULT_INITIAL          = ARM_UCS_LWM2M_RESULT_FIRST,
+        ARM_UCS_LWM2M_RESULT_SUCCESS          = 1,
+        ARM_UCS_LWM2M_RESULT_ERROR_STORAGE    = 2,
+        ARM_UCS_LWM2M_RESULT_ERROR_MEMORY     = 3,
+        ARM_UCS_LWM2M_RESULT_ERROR_CONNECTION = 4,
+        ARM_UCS_LWM2M_RESULT_ERROR_CRC        = 5,
+        ARM_UCS_LWM2M_RESULT_ERROR_TYPE       = 6,
+        ARM_UCS_LWM2M_RESULT_ERROR_URI        = 7,
+        ARM_UCS_LWM2M_RESULT_ERROR_UPDATE     = 8,
+        ARM_UCS_LWM2M_RESULT_ERROR_HASH       = 9,
+        ARM_UCS_LWM2M_RESULT_LAST             = ARM_UCS_LWM2M_RESULT_ERROR_HASH
+    } arm_ucs_lwm2m_result_t;
+
+    void Initialize(void);
+    void Uninitialize(void);
+
+    M2MObject* getObject(void);
+
+    /* Add callback for resource /5/0/0, Package */
+    int32_t addPackageCallback(void (*cb)(const uint8_t* buffer, uint16_t length));
+
+    /* Add callback for resource /5/0/1, Package URI */
+    int32_t addPackageURICallback(void (*cb)(const uint8_t* buffer, uint16_t length));
+
+    /* Add callback for resource /5/0/2, Update */
+    int32_t addUpdateCallback(void (*cb)(void));
+
+    /* Add callback for when send{State, UpdateResult} is done */
+    int32_t addNotificationCallback(void (*notification_handler)(void));
+
+    /* Send state for resource /5/0/3, State */
+    int32_t sendState(arm_ucs_lwm2m_state_t state);
+
+    /* Send result for resource /5/0/5, Update Result */
+    int32_t sendUpdateResult(arm_ucs_lwm2m_result_t result);
+
+    /* Send name for resource /5/0/6, PkgName */
+    int32_t sendPkgName(const uint8_t* name, uint16_t length);
+
+    /* Send version for resource /5/0/7, PkgVersion */
+    int32_t sendPkgVersion(uint64_t version);
+}
+
+#endif // __ARM_UCS_FIRMWARE_UPDATE_RESOURCE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/update-client-lwm2m/lwm2m-control.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,41 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_LWM2M_CONTROL_H
+#define ARM_UC_LWM2M_CONTROL_H
+
+#include "update-client-common/arm_uc_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Set callback function for externally triggering an update.
+ * @details The callback function is called when an external trigger
+ *          is fired. The callback function should force an update.
+ *
+ * @param callback Function pointer.
+ */
+arm_uc_error_t ARM_UC_CONTROL_SetOverrideCallback(void (*callback)(void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ARM_UCS_LWM2M_CONTROL_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/update-client-lwm2m/lwm2m-monitor.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,26 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __ARM_UCS_LWM2M_MONITOR_H__
+#define __ARM_UCS_LWM2M_MONITOR_H__
+
+#include "update-client-monitor/arm_uc_monitor.h"
+
+extern ARM_UPDATE_MONITOR ARM_UCS_LWM2M_MONITOR;
+
+#endif // __ARM_UCS_LWM2M_MONITOR_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/lwm2m-mbed/update-client-lwm2m/lwm2m-source.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,26 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __ARM_UCS_LWM2M_SOURCE_H__
+#define __ARM_UCS_LWM2M_SOURCE_H__
+
+#include "update-client-source/arm_uc_source.h"
+
+extern ARM_UPDATE_SOURCE ARM_UCS_LWM2M_SOURCE;
+
+#endif // __ARM_UCS_LWM2M_SOURCE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,2 @@
+test/*
+*/test/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,166 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmCommon.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,35 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-manifest-manager/update-client-manifest-manager-context.h"
+
+#include "arm_uc_mmCommon.h"
+#include "arm_uc_mmConfig.h"
+#include "update-client-manifest-manager/update-client-manifest-types.h"
+
+#include <string.h>
+
+// Initialisation with an enum silences a compiler warning for ARM ("188-D: enumerated type mixed with another type").
+arm_uc_mmPersistentContext_t arm_uc_mmPersistentContext = { ARM_UC_MM_STATE_INVALID };
+const size_t arm_uc_mmDynamicContextSize = sizeof(arm_uc_mmContext_t);
+
+#if ARM_UC_MANIFEST_MANAGER_TRACE_ENABLE
+volatile uint8_t arm_uc_mm_gDebugLevel = 10;
+#else
+volatile uint8_t arm_uc_mm_gDebugLevel = 0;
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmCommon.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,64 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef MANIFEST_MANAGER_COMMON_H
+#define MANIFEST_MANAGER_COMMON_H
+
+#include "update-client-manifest-manager/update-client-manifest-types.h"
+#include "update-client-common/arm_uc_trace.h"
+#include <string.h>
+#include <stdio.h>
+
+enum arm_uc_mmEvent {
+    ARM_UC_MM_EVENT_INVALID = 0,
+    ARM_UC_MM_EVENT_BEGIN,
+};
+
+#define ARM_UC_MM_DEBUG_LOG_LEVEL_NONE 0
+#define ARM_UC_MM_DEBUG_LOG_LEVEL_VALS 9
+#define ARM_UC_MM_DEBUG_LOG_LEVEL_STATES 10
+
+#define ARRAY_SIZE(X)\
+    (sizeof(X)/sizeof((X)[0]))
+
+#define ARM_UC_MM_SET_BUFFER(BUF,ARRAY)\
+    do {\
+        (BUF).ptr = (ARRAY);\
+        (BUF).size = 0;\
+        (BUF).size_max = sizeof(ARRAY);\
+    } while(0)
+
+#define ARM_UC_MFST_SET_ERROR(VAR, ERROR)\
+    do {\
+    VAR.code = ERROR;\
+    if (VAR.error != ERR_NONE) {\
+        arm_uc_mmPersistentContext.errorFile = __FILE__;\
+        arm_uc_mmPersistentContext.errorLine = __LINE__;\
+    }\
+    }while (0)
+
+
+#if ARM_UC_MANIFEST_MANAGER_TRACE_ENABLE
+extern volatile uint8_t arm_uc_mm_gDebugLevel;
+#define ARM_UC_MM_DEBUG_LOG(LEVEL,...) \
+    if(arm_uc_mm_gDebugLevel >= LEVEL) {printf(__VA_ARGS__);}
+#else
+#define ARM_UC_MM_DEBUG_LOG(LEVEL,...)
+#endif
+
+#endif //MANIFEST_MANAGER_COMMON_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmConfig.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,62 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef MANIFEST_MANAGER_CONFIG_H
+#define MANIFEST_MANAGER_CONFIG_H
+
+#include <limits.h>
+
+#define MAX_HASH_BYTES 32
+#define MAX_SYMM_KEY_BYTES 16
+// #define ECC_SIG_BYTES 71
+#define MAX_URI_BYTES 128
+
+#define MANIFEST_SUPPORTED_VERSION 1
+#define MANIFEST_MANAGER_NO_STORAGE 1
+
+#ifndef ARM_UC_MM_ENABLE_TEST_VECTORS
+#define ARM_UC_MM_ENABLE_TEST_VECTORS 0
+#endif
+
+#ifndef ARM_UC_MM_ENABLE_INSERT_TEST_VECTORS
+#define ARM_UC_MM_ENABLE_INSERT_TEST_VECTORS 0
+#endif
+
+#define RFC_4122_BYTES (128/CHAR_BIT)
+#define RFC_4122_WORDS (RFC_4122_BYTES/sizeof(uint32_t))
+
+#define CERT_MAX_STORAGE 1024
+#define CA_PREFIX       "com.arm.mbed.update.mm.ca"
+#define MANIFEST_PREFIX "com.arm.mbed.update.mm.m"
+
+#define MANIFEST_ROLLBACK_PROTECTION 0
+
+#define CFSTORE_HASH_ID_SIZE ((((256 + CHAR_BIT - 1) / CHAR_BIT + 2) / 3) * 4 + 1)
+
+#define MANIFEST_STORAGE_RETENTION_LEVEL ARM_RETENTION_NVM
+// TODO: Enable ACLs for manifest storage
+#define MANIFEST_STORAGE_ACLS_ENABLED 0
+// TODO: Enable lazy flush
+#define MANIFEST_STORAGE_LAZY_FLUSH_ENABLED 0
+// TODO: Enable flush-on-close
+#define MANIFEST_STORAGE_FLUSH_ON_CLOSE_ENABLED 0
+// TODO: Enable storage-detect
+#define MANIFEST_STORAGE_STORAGE_DETECT_ENABLED 0
+// TODO: Enable async callbacks for config store
+#define MFST_ASYNC_KV_ASYNC 1
+#endif // MANIFEST_MANAGER_CONFIG_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmCryptoUtils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,510 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "arm_uc_mmCryptoUtils.h"
+#include "arm_uc_mmCommon.h"
+#include "arm_uc_mmConfig.h"
+#include "arm_uc_mmDerManifestParser.h"
+#include "update-client-common/arm_uc_crypto.h"
+
+#include "update-client-control-center/arm_uc_certificate.h"
+
+#include "arm_uc_mmDerManifestAccessors.h"
+#include "update-client-manifest-manager/update-client-manifest-manager.h"
+
+#include <string.h>
+
+void ARM_UC_mmVerifySignatureEntry(uint32_t event);
+/**
+ * @file Cryptographic utilities
+ * This file provides two primary APIs:
+ * * Verifying manifest hashes
+ * * Verifying manifest signatures
+ *
+ * Some utility functions used by other files in this module are also provided.
+ *
+ * Algorithm support:
+ * ECC is currently supported, but RSA is not.
+ * Currently, only ECC secp256r1 (prime256v1) is supported.
+ * Currently, only SHA256 is supported.
+ * HMAC is not yet supported.
+ */
+
+/**
+ * @brief Returns the sizes of the cryptographic primitives used by the supplied manifest.
+ * @details Extracts the cryptomode field from a manifest and returns a struct that describes the size of cryptographic
+ *          primitives used in the manifest. The supplied manifest must have been validated. No validation is performed
+ *          by this function.
+ *
+ * @param[in]  buffer A buffer that contains a validated manifest.
+ * @return            A struct cryptsize, which contains the AES primitive sizes and SHA primitive size, both in bytes.
+ *                    An invalid cryptographic mode specifier will cause primitive sizes of `0` to be returned.
+ */
+struct cryptsize getCryptInfo(arm_uc_buffer_t* buffer)
+{
+    struct cryptsize cs = {0};
+    uint32_t cryptoMode = 1U; // default SHA256 and ECC
+    ARM_UC_mmGetCryptoMode(buffer, &cryptoMode);
+
+    switch(cryptoMode)
+    {
+        case MFST_CRYPT_SHA256_ECC_AES128_PSK:
+        // case MFST_CRYPT_SHA256_HMAC_AES128_PSK:
+            cs.aeslen = 128/CHAR_BIT;
+            // fall through
+        // case MFST_CRYPT_SHA256_HMAC:
+        case MFST_CRYPT_SHA256:
+            cs.hashlen = 256/CHAR_BIT;
+            break;
+        case MFST_CRYPT_SHA256_ECC:
+            cs.hashlen = 256/CHAR_BIT;
+        default:
+            break;
+    }
+    return cs;
+}
+
+/**
+ * @brief Converts a cryptographic mode enum to a structure with mode identifiers
+ * @details In order to simplify many tests, the cryptographic mode identifier is converted into a structure of mode
+ *          identifiers, one for each cryptographic primitive. This allows other parts of the code to examine the mode
+ *          of one particular primitive without testing against many enums. This function performs no validation. The
+ *          calling function should have performed validation in advance. If the cryptoMode is unrecognized, then a
+ *          return will be populated with 0 for every flag.
+ *
+ *          HMAC modes are not currently supported.
+ * TODO: Convert flags to enums
+ * @param[in]  cryptoMode The cryptographic mode enum that specifies the settings for each primitive
+ * @return                A structure of flags that indicate the mode of:
+ *                        * Hash algorithm
+ *                        * MAC
+ *                        * Symmetric Encryption
+ *                        * Pre-shared keys
+ *                        * Public Key modes
+ */
+arm_uc_mm_crypto_flags_t ARM_UC_mmGetCryptoFlags(uint32_t cryptoMode)
+{
+
+    switch(cryptoMode) {
+        case MFST_CRYPT_SHA256:
+            return (arm_uc_mm_crypto_flags_t) {.hash = 1U};
+        // case MFST_CRYPT_SHA256_HMAC:
+        //     return (arm_uc_mm_crypto_flags_t) {.hash = 1, .hmac = 1};
+        // case MFST_CRYPT_SHA256_HMAC_AES128_PSK:
+        //     return (arm_uc_mm_crypto_flags_t) {.hash = 1, .hmac = 1, .aes = 1, .psk = 1};
+        case MFST_CRYPT_SHA256_ECC:
+            return (arm_uc_mm_crypto_flags_t) {.hash = 1U, .ecc = 1U};
+        case MFST_CRYPT_SHA256_ECC_AES128_PSK:
+            return (arm_uc_mm_crypto_flags_t) {.hash = 1U, .ecc = 1U, .aes = 1U, .psk = 1U};
+    }
+    return (arm_uc_mm_crypto_flags_t) {.hash = 0};
+
+}
+
+/**
+ * @brief Extracts the hash of a manifest from the manifest wrapper.
+ * @details This is a utility function that is used to extract the hash of the manifest for signature validation.
+ *          This function does not perform validation of the hash buffer, so the hash buffer is expected to be populated
+ *          with a known-good hash buffer. Typically, this buffer will be stack-allocated.
+ * @param[in]   buffer The manifest to parse
+ * @param[out]  hash   Output buffer object to fill with the hash
+ * @return             MFST_ERR_NONE on success, or a parser error code otherwise
+ */
+arm_uc_error_t ARM_UC_mmGetManifestHashFromBin(arm_uc_buffer_t* buffer, arm_uc_buffer_t* hash)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_SIG_HASH;
+    int rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, hash);
+    if (rc) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+
+/**
+ * Utility function for printing the hex value of a buffer. Used only for debugging.
+ * @param buf [description]
+ */
+#if 0
+static void hexprint_buffer(arm_uc_buffer_t* buf)
+{
+    for (size_t i = 0; i < buf->size; i++)
+    {
+        printf("%02x", buf->ptr[i]);
+    }
+}
+#endif
+
+/**
+ * @brief ARM_UC_mmValidateManifestHash processes a manifest in order to validate its hash
+ * @details The manifest parser extracts the manifest hash, calculates the hash of the manifest, then compares it to the
+ *          hash included in the manifest.
+ *
+ *          The outer wrapper of the manifest is called a SignedResource. It contains a Resource object and a
+ *          ResourceSignature object. The Resource object contains a Resource Type identifier, an optional URL, and
+ *          either a manifest or binary data.
+ *
+ *          This function extracts the Resource object and the ResourceSignature object so that the Resource can be
+ *          hashed and verified against the hash in the ResourceSignature.
+ *
+ *          TODO: The dependency on the cryptoMode contained within the manifest will be removed with the change to CMS
+ *          First, the Resource object is extracted. Next, the cryptoMode is extracted from the Resource object. This
+ *          requires that the Resource object be a Manifest.
+ *
+ * @param[in]  buffer The buffer that contains the manifest to validate
+ * @retval            MFST_ERR_NONE on success
+ * @retval            MFST_ERR_CRYPTO_MODE if there is a cryptographic mode error
+ * @retval            Otherwise, a DER Parser error can be expected
+ */
+arm_uc_error_t ARM_UC_mmValidateManifestHash(arm_uc_buffer_t* buffer)
+{
+    uint8_t localhash[MAX_HASH_BYTES];      ///< An array to store the locally calculated hash
+    arm_uc_buffer_t local = {               ///< A buffer structure to use for the locally calculated hash
+        .size_max = MAX_HASH_BYTES,
+        .size     = 0,
+        .ptr      = localhash
+    };
+    arm_uc_buffer_t remote = {             ///< A buffer for the hash provided in the manifest
+        .size_max = MAX_HASH_BYTES,
+        .size     = 0,
+        .ptr      = NULL
+    };
+    arm_uc_buffer_t resource = {            ///< A buffer for the resource (the manifest) that is wrapped by a signature
+        .size_max = MAX_HASH_BYTES,
+        .size     = 0,
+        .ptr      = NULL
+    };
+    arm_uc_mdHandle_t hDigest = {0};        ///< This handle is for the digest algorithm
+    arm_uc_error_t err = {MFST_ERR_NONE};   ///< The return code variable
+    uint32_t cryptoMode = 0;                ///< A temporary local copy of the crytpoMode
+    arm_uc_mdType_t mdType = 0;             ///< A type designator for the type of hash in use
+
+    // Extract the "resource" contained in the Signed Resource object
+    err = ARM_UC_mmDERSignedResourceGetSingleValue(buffer, ARM_UC_MM_DER_RESOURCE, &resource);
+    if (!err.error)
+    {
+        // Extract the hash from the manifest
+        err = ARM_UC_mmGetManifestHash(buffer, &remote);
+    }
+    if (!err.error)
+    {
+        // Extract the cryptographic mode from the manifest
+        err = ARM_UC_mmGetCryptoMode(buffer, &cryptoMode);
+    }
+    if (!err.error)
+    {
+        // Set the hash type identifier
+        switch(cryptoMode)
+        {
+            case MFST_CRYPT_SHA256_ECC_AES128_PSK:
+            case MFST_CRYPT_SHA256:
+            case MFST_CRYPT_SHA256_ECC:
+                mdType = ARM_UC_CU_SHA256;
+                break;
+            default:
+                err.code = MFST_ERR_CRYPTO_MODE;
+                break;
+        }
+    }
+    if (!err.error)
+    {
+        // Initialize the message digest API
+        err = ARM_UC_cryptoHashSetup(&hDigest, mdType);
+    }
+    if (!err.error)
+    {
+        // NOTE: If a hash accelerator is present on-chip, this could be converted from a blocking call to an
+        //       asynchronous one.
+        // Hash the resource
+        // Keep Coverity quiet - it can't resolve some semantic conditions here.
+        if ( resource.ptr == NULL ) {
+            ARM_UC_SET_ERROR(err, MFST_ERR_NULL_PTR);
+        } else  {
+            err = ARM_UC_cryptoHashUpdate(&hDigest, &resource);
+        }
+    }
+    if (!err.error)
+    {
+        // Extract the locally calculated hash from the hash API
+        err = ARM_UC_cryptoHashFinish(&hDigest, &local);
+    }
+    if (!err.error)
+    {
+        // Check that the hashes match
+        // Keep Coverity quiet - it can't resolve some semantic conditions here.
+        if ( remote.ptr == NULL ) {
+            ARM_UC_SET_ERROR(err, MFST_ERR_NULL_PTR);
+        } else if(ARM_UC_BinCompareCT(&local, &remote)) {
+            ARM_UC_SET_ERROR(err, MFST_ERR_HASH);
+        }
+    }
+    // Explicitly set the manifest manager's no-error code, rather than another module's, which may be present here.
+    if (!err.error)
+    {
+        ARM_UC_SET_ERROR(err, MFST_ERR_NONE);
+    }
+    return err;
+}
+
+enum arm_uc_mmCertificateFetchEvents {
+    ARM_UC_MM_CERTIFICATE_FETCH_UNINIT,
+    ARM_UC_MM_CERTIFICATE_FETCH_SUCCESS,
+    ARM_UC_MM_CERTIFICATE_FETCH_MISMATCH,
+    ARM_UC_MM_CERTIFICATE_FETCH_ERROR,
+};
+
+/**
+ * @brief Validates one signature of a manifest, once the signing certificate has been found.
+ * @param  buffer   Holding buffer for the manifest to validate.
+ * @param  ca       Buffer holding the certificate to use in verification
+ * @param  sigIndex Index of the manifest signature to verify with this certificate
+ * @retval          MFST_ERR_DER_FORMAT on parse error
+ * @retval          MFST_ERR_CERT_INVALID if the certificate is not valid
+ * @retval          MFST_ERR_INVALID_SIGNATURE if the signature is invalid
+ * @retval          MFST_ERR_NONE for a valid signature
+ */
+static arm_uc_error_t ARM_UC_mmValidateSignatureCert(arm_uc_buffer_t* buffer, arm_uc_buffer_t* ca, uint32_t sigIndex)
+{
+    const int32_t fieldIDs[] = {ARM_UC_MM_DER_SIG_HASH, ARM_UC_MM_DER_SIG_SIGNATURES};
+    arm_uc_buffer_t fields[ARRAY_SIZE(fieldIDs)];
+
+    // Get the signature list
+    int rc = ARM_UC_mmDERGetSignedResourceValues(buffer, ARRAY_SIZE(fieldIDs), fieldIDs, fields);
+    if (rc) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+
+    // Get the specified signature block
+    arm_uc_buffer_t sigblock;
+    rc = ARM_UC_mmDERGetSequenceElement(&fields[1], sigIndex, &sigblock);
+    if (rc) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+
+    // Load the specified signature out of the signature block
+    arm_uc_buffer_t sig;
+    const int32_t sigID = ARM_UC_MM_DER_SIG_SIGNATURE;
+    rc = ARM_UC_mmDERParseTree(&arm_uc_mmSignatures[0], &sigblock, 1U, &sigID, &sig);
+    if (rc) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+
+    // Validate the signature
+    return ARM_UC_verifyPkSignature(ca, &fields[0], &sig);
+}
+
+struct {
+    arm_uc_mm_validate_signature_context_t* ctx;
+    arm_uc_callback_t callbackStorage;
+} arm_uc_mmSignatureVerificationContext;
+
+
+/**
+ * @brief Callback function to continue signature verification once the certificate has been found
+ * @details This function should be called by the certificate lookup function, which is provided by the application.
+ *          The certificate lookup function should call this callback regardless of success or failure so that errors
+ *          can be reported correctly.
+ *
+ *          Caveats:
+ *          The certificate supplied here MUST be the same buffer as was provided to the certificate fetch function.
+ *          The fingerprint supplied here MUST be the same buffer as was provided to the certificate fetch function.
+ *
+ *          These requirements are in place to ensure that only one signature verification may be carried out at a time.
+ *
+ *          Once the basic checks are performed in the callback, it schedules the manifest manager to execute later.
+ *
+ * @param status      Error code provided by the certificat lookup function
+ * @param certificate Buffer containing the certificate
+ * @param fingerprint Buffer containing the certificate fingerprint
+ */
+void ARM_UC_mmCertificateCallback(arm_uc_error_t status, const arm_uc_buffer_t* certificate, const arm_uc_buffer_t* fingerprint)
+{
+    uint32_t event = ARM_UC_MM_CERTIFICATE_FETCH_UNINIT;
+    UC_MMGR_TRACE("%s (%u)\n", __PRETTY_FUNCTION__, (unsigned)event);
+    if (status.error == ERR_NONE)
+    {
+        // Verify that this is the same buffer as was provided to the certificate fetch function.
+        if (fingerprint != &arm_uc_mmSignatureVerificationContext.ctx->fingerprint ||
+            certificate != &arm_uc_mmSignatureVerificationContext.ctx->cert)
+        {
+            event = ARM_UC_MM_CERTIFICATE_FETCH_MISMATCH;
+        }
+        else
+        {
+            event = ARM_UC_MM_CERTIFICATE_FETCH_SUCCESS;
+        }
+    }
+    else
+    {
+        // Store the error for later reporting
+        arm_uc_mmSignatureVerificationContext.ctx->storedError = status;
+        event = ARM_UC_MM_CERTIFICATE_FETCH_ERROR;
+    }
+    // Post the Manifest Manager state machine entry point to the Update Client event queue
+    UC_MMGR_TRACE("%s Posting ARM_UC_mmVerifySignatureEntry(%lu)\n", __PRETTY_FUNCTION__, event);
+    ARM_UC_PostCallback(&arm_uc_mmSignatureVerificationContext.callbackStorage, ARM_UC_mmVerifySignatureEntry, event);
+}
+
+/**
+ * @brief State machine that controls the verification of signatures.
+ * @details First, the state machine attempts to fetch the certificate. When the certificate has been fetched,
+ *          the state machine validates the signature, then alerts the calling application with the result.
+ *
+ *
+ * @param[in]  ctx   Context pointer for the state machine
+ * @param[in]  event Event to move the state machine forward
+ * @retval           MFST_ERR_NONE on success
+ * @retval           MFST_ERR_PENDING when the validation has not completed and is waiting for external input
+ *                   (e.g. certificate fetching)
+ * @retval           Another error code otherwise.
+ */
+static arm_uc_error_t ARM_UC_mmValidateSignatureFSM(arm_uc_mm_validate_signature_context_t* ctx, uint32_t event)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    enum arm_uc_mm_pk_sig_state oldState;
+    UC_MMGR_TRACE("%s (%lu)\n", __PRETTY_FUNCTION__, event);
+    do
+    {
+        oldState = ctx->state;
+        UC_MMGR_TRACE("%s state:%u\n", __PRETTY_FUNCTION__, oldState);
+        switch(ctx->state)
+        {
+            case UCMM_PKSIG_STATE_FIND_CA:
+                // Start the search for a certificate
+                // This state transitions automatically to UCMM_PKSIG_STATE_FINDING_CA unless there is an error
+                err = ARM_UC_certificateFetch(&ctx->cert,
+                                              &ctx->fingerprint,
+                                              &ctx->certList,
+                                              ARM_UC_mmCertificateCallback);
+                if (err.error == ERR_NONE || err.code == MFST_ERR_PENDING)
+                {
+                    ctx->state = UCMM_PKSIG_STATE_FINDING_CA;
+                    err.code = MFST_ERR_PENDING;
+                }
+                break;
+            case UCMM_PKSIG_STATE_FINDING_CA:
+                // Wait the Certificate fetch to complete. On completion, this state decides what to do with the result.
+                switch(event)
+                {
+                    // If the certificate was fetched successfully, proceed to signature verification
+                    case ARM_UC_MM_CERTIFICATE_FETCH_SUCCESS:
+                        err.code = MFST_ERR_NONE;
+                        ctx->state = UCMM_PKSIG_STATE_CHECK;
+                        break;
+                    // If an error occured, extract the error.
+                    case ARM_UC_MM_CERTIFICATE_FETCH_ERROR:
+                        err = ctx->storedError;
+                        break;
+                    // Otherwise, report a bad event.
+                    case ARM_UC_MM_CERTIFICATE_FETCH_UNINIT:
+                    case ARM_UC_MM_CERTIFICATE_FETCH_MISMATCH:
+                    default:
+                        err.code = MFST_ERR_BAD_EVENT;
+                        break;
+                }
+                break;
+            // Validate the signature
+            case UCMM_PKSIG_STATE_CHECK:
+                err = ARM_UC_mmValidateSignatureCert(ctx->manifest,
+                    &ctx->cert, ctx->sigIndex);
+                if (err.code == MFST_ERR_NONE)
+                {
+                    ctx->state = UCMM_PKSIG_STATE_IDLE;
+                }
+                break;
+            case UCMM_PKSIG_STATE_IDLE:
+                err.code = MFST_ERR_NONE;
+                // The Entry function will report success after this state exits.
+                break;
+            default:
+                err = (arm_uc_error_t){MFST_ERR_INVALID_STATE};
+                break;
+        }
+
+    } while (err.code == MFST_ERR_NONE && ctx->state != oldState);
+    UC_MMGR_TRACE("%s() return code: %c%c:%hu (%s)\n",
+        __PRETTY_FUNCTION__, err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err));
+    return err;
+}
+/**
+ * @brief Start signature verification.
+ * @details This API initiates a signature verification. The actual signature verification is carried out by
+ *
+ *
+ * @param[in]  ctx        Signature validation context. This contains all the state used by the signature validator.
+ * @param[in]  buffer     A buffer containing the manifest to verify
+ * @param[in]  certBuffer A temporary storage buffer for certificate fetching
+ * @param[in]  sigIndex   Index of the signature to verify.
+ * @retval                MFST_ERR_NONE on success
+ * @retval                MFST_ERR_PENDING when the validation has not completed and is waiting for external input
+ *                        (e.g. certificate fetching)
+ * @retval                Another error code otherwise.
+ */
+arm_uc_error_t ARM_UC_mmValidateSignature(arm_uc_mm_validate_signature_context_t* ctx,
+                                          void (*applicationEventHandler)(uint32_t),
+                                          arm_uc_buffer_t* buffer,
+                                          arm_uc_buffer_t* certBuffer,
+                                          uint32_t sigIndex)
+{
+    UC_MMGR_TRACE("%s (%u)\n", __PRETTY_FUNCTION__, (unsigned)sigIndex);
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    if (ctx == NULL)
+    {
+        ARM_UC_SET_ERROR(err, MFST_ERR_NULL_PTR);
+    }
+    if (err.error == ERR_NONE)
+    {
+#ifdef ATOMIC_QUEUE_CONFIG_ELEMENT_LOCK
+        arm_uc_mmSignatureVerificationContext.callbackStorage.lock = 0;
+#endif
+        arm_uc_mmSignatureVerificationContext.ctx = ctx;
+        // Extract the certificate identifier from the manifest
+        err = ARM_UC_mmGetCertificateId(buffer, sigIndex, &arm_uc_mmSignatureVerificationContext.ctx->fingerprint);
+        UC_MMGR_TRACE("%s %c%c:%hu (%s)\n", "Get Certificate ID return code:", err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err));
+    }
+    if(err.error == 0 && ctx)
+    {
+        // Copy all the relevant inputs into the state variable
+        err.code = MFST_ERR_NONE;
+        arm_uc_mmSignatureVerificationContext.ctx->manifest                = buffer;
+        arm_uc_mmSignatureVerificationContext.ctx->applicationEventHandler = applicationEventHandler;
+        arm_uc_mmSignatureVerificationContext.ctx->state                   = UCMM_PKSIG_STATE_FIND_CA;
+        arm_uc_mmSignatureVerificationContext.ctx->sigIndex                = sigIndex;
+        ARM_UC_buffer_shallow_copy(&arm_uc_mmSignatureVerificationContext.ctx->cert, certBuffer);
+        UC_MMGR_TRACE("%s Posting ARM_UC_mmVerifySignatureEntry(%lu)\n", __PRETTY_FUNCTION__, ARM_UC_MM_EVENT_BEGIN);
+        ARM_UC_PostCallback(&arm_uc_mmSignatureVerificationContext.callbackStorage, ARM_UC_mmVerifySignatureEntry, ARM_UC_MM_EVENT_BEGIN);
+    }
+    UC_MMGR_TRACE("%s %c%c:%hu (%s)\n", __PRETTY_FUNCTION__, err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err));
+    return err;
+}
+
+/**
+ * @brief Main entry point for callbacks to enter the state machine.
+ * @details Calls the signature verification state machine. If the result is not Pending, calls the application event
+ *          handler with a result code.
+ *          Application event handler is invoked directly, not queued because this function should have minimal stack
+ *          and it should be called directly from the event queue.
+ * @param[in] event Event to forward to the state machine
+ */
+void ARM_UC_mmVerifySignatureEntry(uint32_t event)
+{
+    UC_MMGR_TRACE("%s (%u)\n", __PRETTY_FUNCTION__, (unsigned)event);
+    arm_uc_error_t err = ARM_UC_mmValidateSignatureFSM(arm_uc_mmSignatureVerificationContext.ctx , event);
+    if (err.code != MFST_ERR_NONE && err.code != MFST_ERR_PENDING)
+    {
+        arm_uc_mmSignatureVerificationContext.ctx->storedError = err;
+        arm_uc_mmSignatureVerificationContext.ctx->applicationEventHandler(ARM_UC_MM_RC_ERROR);
+    }
+    if (err.code == MFST_ERR_NONE && arm_uc_mmSignatureVerificationContext.ctx->state == UCMM_PKSIG_STATE_IDLE)
+    {
+        // A callback is not posted since this runs inside
+        arm_uc_mmSignatureVerificationContext.ctx->applicationEventHandler(ARM_UC_MM_RC_DONE);
+    }
+    UC_MMGR_TRACE("%s %c%c:%hu (%s)\n", __PRETTY_FUNCTION__, err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmCryptoUtils.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,49 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef MANIFEST_MANAGER_CRYPTO_FSM_H
+#define MANIFEST_MANAGER_CRYPTO_FSM_H
+
+#include "update-client-manifest-manager/update-client-manifest-manager-context.h"
+#include "update-client-manifest-manager/update-client-manifest-types.h"
+
+
+arm_uc_error_t ARM_UC_mmValidateManifestHash(arm_uc_buffer_t* buffer);
+arm_uc_error_t ARM_UC_mmValidateSignature(arm_uc_mm_validate_signature_context_t* ctx,
+                                          void (*applicationEventHandler)(uint32_t),
+                                          arm_uc_buffer_t* buffer,
+                                          arm_uc_buffer_t* certBuffer,
+                                          uint32_t sigIndex);
+arm_uc_error_t ARM_UC_mmGetManifestHashFromBin(arm_uc_buffer_t* buffer, arm_uc_buffer_t* hash);
+void ARM_UC_mmGetFirmwareHashFromBin(arm_uc_buffer_t* manifest, arm_uc_buffer_t* hash);
+
+
+struct cryptsize {
+    uint32_t hashlen;
+    uint32_t aeslen;
+};
+
+struct cryptsize getCryptInfo(arm_uc_buffer_t* buffer);
+/**
+ * NOTE: This function does no validation. cryptomode must already have been validated by validateCryptoMode
+ *
+ * */
+arm_uc_mm_crypto_flags_t ARM_UC_mmGetCryptoFlags(uint32_t cryptoMode);
+
+
+#endif // MANIFEST_MANAGER_CRYPTO_FSM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmDerManifestAccessors.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,260 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "arm_uc_mmDerManifestAccessors.h"
+#include "arm_uc_mmDerManifestParser.h"
+#include <string.h>
+
+
+arm_uc_error_t ARM_UC_wrapMbedTLSError(int32_t mt_err) {
+    return (arm_uc_error_t){.error = -mt_err, .module = MBED_TLS_ERROR_PREFIX};
+}
+
+arm_uc_error_t ARM_UC_mmDERSignedResourceGetSingleValue(arm_uc_buffer_t* buffer, const int32_t fieldID, arm_uc_buffer_t* val)
+{
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, val);
+    arm_uc_error_t err = {ARM_UC_DP_ERR_UNKNOWN};
+    if (rc < 0) {
+        err = ARM_UC_wrapMbedTLSError(rc);
+    } else if (rc == 0) {
+        err.code = ARM_UC_DP_ERR_NONE;
+    } else { //if (rc > 0)
+        err.code = ARM_UC_DP_ERR_NOT_FOUND;
+    }
+    return err;
+}
+
+arm_uc_error_t ARM_UC_mmDERGetSingleValue(
+        const struct arm_uc_mmDerElement* desc,
+        arm_uc_buffer_t* buffer,
+        const int32_t valueID,
+        arm_uc_buffer_t* val)
+{
+    int32_t rc = ARM_UC_mmDERParseTree(desc, buffer, 1U, &valueID, val);
+    arm_uc_error_t err = {ARM_UC_DP_ERR_UNKNOWN};
+    if (rc < 0) {
+        err = ARM_UC_wrapMbedTLSError(rc);
+    } else if (rc == 0) {
+        err.code = ARM_UC_DP_ERR_NONE;
+    } else { //if (rc > 0)
+        err.code = ARM_UC_DP_ERR_NOT_FOUND;
+    }
+    return err;
+}
+
+uint32_t ARM_UC_mmGetCryptoModeInline(arm_uc_buffer_t* buffer)
+{
+    uint32_t val = 1U; // default to SHA256 and ECC
+    ARM_UC_mmGetCryptoMode(buffer, &val);
+    return val;
+}
+arm_uc_error_t ARM_UC_mmGetVersion(arm_uc_buffer_t* buffer, uint32_t* val)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_VERSION;
+    arm_uc_buffer_t field = { 0UL };
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, &field);
+    if (rc || field.ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    *val = ARM_UC_mmDerBuf2Uint(&field);
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetCryptoMode(arm_uc_buffer_t* buffer, uint32_t* val)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_ENC_ENUM;
+    arm_uc_buffer_t field = { 0UL };
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, &field);
+    if (rc || field.ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    *val = ARM_UC_mmDerBuf2Uint(&field);
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetTimestamp(arm_uc_buffer_t* buffer, uint64_t* val)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_TIMESTAMP;
+    arm_uc_buffer_t field = { 0UL };
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, &field);
+    if (rc || field.ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    *val = ARM_UC_mmDerBuf2Uint64(&field);
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetValidFrom(arm_uc_buffer_t* buffer, uint64_t* val)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_VALID_FROM;
+    arm_uc_buffer_t field = { 0UL };
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, &field);
+    if (rc < 0 || field.ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    if (rc > 0) return (arm_uc_error_t){MFST_ERR_EMPTY_FIELD};
+    *val = ARM_UC_mmDerBuf2Uint64(&field);
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetValidTo(arm_uc_buffer_t* buffer, uint64_t* val)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_VALID_TO;
+    arm_uc_buffer_t field = { 0UL };
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, &field);
+    if (rc < 0 || field.ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    if (rc > 0) return (arm_uc_error_t){MFST_ERR_EMPTY_FIELD};
+    *val = ARM_UC_mmDerBuf2Uint64(&field);
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetVendorGuid(arm_uc_buffer_t* buffer, arm_uc_buffer_t* guid)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_VENDOR_UUID;
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, guid);
+    if (rc || guid->ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetClassGuid(arm_uc_buffer_t* buffer, arm_uc_buffer_t* guid)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_CLASS_UUID;
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, guid);
+    if (rc || guid->ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetDeviceGuid(arm_uc_buffer_t* buffer, arm_uc_buffer_t* guid)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_DEVICE_UUID;
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, guid);
+    if (rc || guid->ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+
+arm_uc_error_t ARM_UC_mmGetFwInitVector(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_FW_CRYPT_IV;
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, val);
+    if (rc || val->ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetFwUri(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL;
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, val);
+    if (rc || val->ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetFwSize(arm_uc_buffer_t* buffer, uint32_t* val)
+{
+    arm_uc_buffer_t field = { 0UL };
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE;
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, &field);
+    if (rc || field.ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    *val = ARM_UC_mmDerBuf2Uint(&field);
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetFwHash(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH;
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, val);
+    if (rc || val->ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetFwSymmKey(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val)
+{
+    return (arm_uc_error_t){MFST_ERR_VERSION};
+}
+arm_uc_error_t ARM_UC_mmGetFwCertId(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_FW_CRYPT_ID_LOCAL;
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, val);
+    if (rc || val->ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetDescription(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_DESC;
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, val);
+    if (rc || val->ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetManifestLinksUri(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_DEP_REF_URL;
+    int32_t rc = ARM_UC_mmDERParseTree(arm_uc_mmManifestDependencies, buffer, 1U, &fieldID, val);
+    if (rc || val->ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetManifestLinksHash(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val)
+{
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_DEP_REF_HASH;
+    int32_t rc = ARM_UC_mmDERParseTree(arm_uc_mmManifestDependencies, buffer, 1U, &fieldID, val);
+    if (rc || val->ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetManifestLinksElement(arm_uc_buffer_t* buffer, uint32_t index, arm_uc_buffer_t* element)
+{
+    arm_uc_buffer_t elements = { 0UL };
+    const int32_t fieldID = ARM_UC_MM_DER_MFST_DEPS;
+    int32_t rc = ARM_UC_mmDERGetSignedResourceValues(buffer, 1U, &fieldID, &elements);
+    if (rc || elements.ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    element->ptr = NULL;
+    rc = ARM_UC_mmDERGetSequenceElement(&elements, index, element);
+    if (rc) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetManifestHash(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val)
+{
+    return ARM_UC_mmDERSignedResourceGetSingleValue(buffer, ARM_UC_MM_DER_SIG_HASH, val);
+}
+arm_uc_error_t ARM_UC_mmGetSignatureBlock(arm_uc_buffer_t* buffer, uint32_t idx, arm_uc_buffer_t* block)
+{
+    arm_uc_buffer_t signatures = { 0UL };
+    arm_uc_error_t err = ARM_UC_mmDERSignedResourceGetSingleValue(buffer, ARM_UC_MM_DER_SIG_SIGNATURES, &signatures);
+    if (err.error) return err;
+    if (signatures.ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+
+    int32_t rc = ARM_UC_mmDERGetSequenceElement(&signatures, idx, block);
+    if (rc) return ARM_UC_wrapMbedTLSError(rc);
+    if (block->ptr == NULL) return (arm_uc_error_t){ARM_UC_DP_ERR_NO_MORE_ELEMENTS};
+
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetSignature(arm_uc_buffer_t* buffer, uint32_t idx, arm_uc_buffer_t* val)
+{
+    arm_uc_buffer_t signatureBlock = { 0UL };
+    arm_uc_error_t err = ARM_UC_mmGetSignatureBlock(buffer, idx, &signatureBlock);
+    if (err.error) return err;
+    if (signatureBlock.ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+
+    err = ARM_UC_mmDERGetSingleValue(arm_uc_mmSignatures, &signatureBlock, ARM_UC_MM_DER_SIG_SIGNATURE, val);
+    if (err.error) return err;
+    if (val->ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+
+arm_uc_error_t ARM_UC_mmGetCertificateId(arm_uc_buffer_t* buffer, uint32_t sigIdx, arm_uc_buffer_t* val)
+{
+    arm_uc_buffer_t signatureBlock = { 0UL };
+    arm_uc_error_t err = ARM_UC_mmGetSignatureBlock(buffer, sigIdx, &signatureBlock);
+    if (err.error) return err;
+    if (signatureBlock.ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+
+    arm_uc_buffer_t seq = { 0UL };
+    err = ARM_UC_mmDERGetSingleValue(arm_uc_mmSignatures, &signatureBlock, ARM_UC_MM_DER_SIG_CERTS, &seq);
+    if (err.error) return err;
+    if (seq.ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+
+    arm_uc_buffer_t element = { 0UL };
+    element.ptr = NULL;
+    int32_t rc = ARM_UC_mmDERGetSequenceElement(&seq, 0, &element);
+    if (rc) return ARM_UC_wrapMbedTLSError(rc);
+    if (element.ptr == NULL) return (arm_uc_error_t){ARM_UC_DP_ERR_NO_MORE_ELEMENTS};
+
+    err = ARM_UC_mmDERGetSingleValue(arm_uc_mmSignatureCertificateReferences, &element, ARM_UC_MM_DER_SIG_CERT_FINGERPRINT, val );
+    if (err.error) return err;
+    if (val->ptr == NULL) return (arm_uc_error_t){MFST_ERR_DER_FORMAT};
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmDerManifestAccessors.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,63 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_CLIENT_MANIFEST_MANAGER_ACCESSORS_H
+#define ARM_UPDATE_CLIENT_MANIFEST_MANAGER_ACCESSORS_H
+// WARNING: THIS IS A MACHINE-GENERATED FILE. DO NOT MODIFY.
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_common.h"
+#define MFST_MAGIC 1414743629
+enum {
+    ARM_UC_MFST_CRYPTOMODE_UNINIT = 0,
+    ARM_UC_MFST_CRYPTOMODE_SHA256,
+    ARM_UC_MFST_CRYPTOMODE_SHA256_HMAC,
+    ARM_UC_MFST_CRYPTOMODE_SHA256_HMAC_AES128,
+    ARM_UC_MFST_CRYPTOMODE_SHA256_ECC,
+    ARM_UC_MFST_CRYPTOMODE_SHA256_ECC_AES128,
+    ARM_UC_MFST_CRYPTOMODE_MAX,
+};
+
+uint32_t ARM_UC_mmGetUint32_t(arm_uc_buffer_t* buffer, uint32_t offset);
+arm_uc_error_t ARM_UC_mmGetMagic(arm_uc_buffer_t* buffer, uint32_t* val);
+arm_uc_error_t ARM_UC_mmGetVersion(arm_uc_buffer_t* buffer, uint32_t* val);
+arm_uc_error_t ARM_UC_mmGetCryptoMode(arm_uc_buffer_t* buffer, uint32_t* val);
+arm_uc_error_t ARM_UC_mmGetNonce(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val);
+arm_uc_error_t ARM_UC_mmGetVendorGuid(arm_uc_buffer_t* buffer, arm_uc_buffer_t* guid);
+arm_uc_error_t ARM_UC_mmGetClassGuid(arm_uc_buffer_t* buffer, arm_uc_buffer_t* guid);
+arm_uc_error_t ARM_UC_mmGetDeviceGuid(arm_uc_buffer_t* buffer, arm_uc_buffer_t* guid);
+arm_uc_error_t ARM_UC_mmGetTimestamp(arm_uc_buffer_t* buffer, uint64_t* val);
+arm_uc_error_t ARM_UC_mmGetValidFrom(arm_uc_buffer_t* buffer, uint64_t* val);
+arm_uc_error_t ARM_UC_mmGetValidTo(arm_uc_buffer_t* buffer, uint64_t* val);
+arm_uc_error_t ARM_UC_mmGetCertificateId(arm_uc_buffer_t* buffer, uint32_t sigIdx, arm_uc_buffer_t* val);
+arm_uc_error_t ARM_UC_mmGetFwInitVector(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val);
+arm_uc_error_t ARM_UC_mmGetFwUri(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val);
+arm_uc_error_t ARM_UC_mmGetFwSize(arm_uc_buffer_t* buffer, uint32_t* val);
+arm_uc_error_t ARM_UC_mmGetFwHash(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val);
+arm_uc_error_t ARM_UC_mmGetFwSymmKey(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val);
+arm_uc_error_t ARM_UC_mmGetFwCertId(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val);
+arm_uc_error_t ARM_UC_mmGetDescription(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val);
+arm_uc_error_t ARM_UC_mmGetManifestLinksUri(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val);
+arm_uc_error_t ARM_UC_mmGetManifestLinksHash(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val);
+arm_uc_error_t ARM_UC_mmGetManifestLinksElementCount(arm_uc_buffer_t* buffer, uint32_t* val);
+uint32_t ARM_UC_mmGetManifestLinksElementSize(arm_uc_buffer_t* buffer, uint32_t baseOffset);
+arm_uc_error_t ARM_UC_mmGetManifestLinksElement(arm_uc_buffer_t* buffer, uint32_t index, arm_uc_buffer_t* element);
+arm_uc_error_t ARM_UC_mmGetManifestHash(arm_uc_buffer_t* buffer, arm_uc_buffer_t* val);
+
+arm_uc_error_t ARM_UC_mmDERSignedResourceGetSingleValue(arm_uc_buffer_t* buffer, const int32_t fieldID, arm_uc_buffer_t* val);
+
+#endif // ARM_UPDATE_CLIENT_MANIFEST_MANAGER_ACCESSORS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmDerManifestParser.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,885 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "arm_uc_mmDerManifestParser.h"
+
+#include <stdio.h>
+
+#define DER_MANDATORY 0
+#define DER_OPTIONAL 1
+
+#define ARM_UC_MM_DER_ELEMENT_INIT(ID, TAG, OPT, CHILDREN)\
+    {.id = (ID), .subElements = (CHILDREN), .tag = (TAG), .optional = (OPT), .nSubElements = sizeof(CHILDREN)/sizeof(struct arm_uc_mmDerElement)}
+#define ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ID, TAG, OPT)\
+    {.id = (ID), .subElements = NULL, .tag = (TAG), .optional = (OPT), .nSubElements = 0}
+
+
+/**
+ * @brief Descriptor for the apply period of a manifest.
+ *
+ * applyPeriod SEQUENCE {
+ *     validFrom     INTEGER,
+ *     validTo       INTEGER
+ * }
+ */
+static const struct arm_uc_mmDerElement ManifestApplyPeriod[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_VALID_FROM, ARM_UC_MM_ASN1_INTEGER, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_VALID_TO, ARM_UC_MM_ASN1_INTEGER, DER_MANDATORY),
+};
+/**
+ * @brief Descriptor of the encryptionMode
+ *
+ * encryptionMode  CHOICE {
+ *     enum    ENUMERATED {
+ *         invalid(0),
+ *         aes-128-ctr-ecc-secp256r1-sha256(1),
+ *         none-ecc-secp256r1-sha256(2),
+ *         none-none-sha256(3)
+ *     },
+ *     objectId    OBJECT IDENTIFIER
+ * }
+ */
+static const struct arm_uc_mmDerElement encryptionModeChoice[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_ENC_ENUM, ARM_UC_MM_ASN1_ENUMERATED, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_ENC_OID, ARM_UC_MM_ASN1_OID, DER_MANDATORY),
+};
+/**
+ * @brief Descriptor for resource aliases
+ *
+ * ResourceAlias ::= SEQUENCE {
+ *     hash        OCTET STRING,
+ *     url         Url
+ * }
+ */
+static const struct arm_uc_mmDerElement manifestResourceAlias[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_RESOURCE_ALIAS_HASH, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_RESOURCE_ALIAS_URL, ARM_UC_MM_ASN1_UTF8_STRING, DER_MANDATORY),
+};
+/**
+ * @brief Descriptor of an Alias container
+ *
+ */
+static const struct arm_uc_mmDerElement manifestResourceAliases[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_RESOURCE_ALIAS, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, manifestResourceAlias)
+};
+
+/**
+ * @brief Descriptor of the firmware format
+ *
+ * format      CHOICE {F
+ *     enum    ENUMERATED {
+ *         undefined(0), raw-binary(1), cbor(2), hex-location-length-data(3), elf(4)
+ *     },
+ *     objectId    OBJECT IDENTIFIER
+ * },
+ */
+static const struct arm_uc_mmDerElement manifestFwFmtChoice[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_FMT_ENUM, ARM_UC_MM_ASN1_ENUMERATED, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_FMT_OID, ARM_UC_MM_ASN1_OID, DER_MANDATORY),
+};
+
+/**
+ * @brief Descriptor of the certificate reference used for ECDH
+ * @details References an ECC certificate, which is used to perform ECDH with the target device's private key. This will
+ * allow derivation of a shared secret, which has been used to encrypt the symmetric encryption key.
+ * NOTE: this is the same ASN.1 sequence as arm_uc_mmSignatureCertificateReference, but it is duplicated in the parser to reduce parsing time.
+ *
+ * CertificateReference ::= SEQUENCE {
+ *     fingerprint  Bytes,
+ *     url          Url
+ * }
+ *
+ */
+static const struct arm_uc_mmDerElement manifestFwCryptIdCertRef[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_FINGERPRINT, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_URL, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
+};
+/**
+ * @brief Descriptor of the Local Info ID choice
+ * @details Describes either a locally held pre-shared key or a certificate.
+ *
+ * id CHOICE {
+ *     key OCTET STRING,
+ *     certificate CertificateReference
+ * },
+ */
+static const struct arm_uc_mmDerElement manifestFwCryptIdChoice[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_LOCAL, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_REF, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, manifestFwCryptIdCertRef),
+};
+/**
+ * @brief Descriptor of the encryption key options
+ * @details Encryption is currently not supported.
+ * When supported, the encryption key will be delivered either as an encrypted blob in the manifest, or in a key table,
+ * which is referenced in the Resource Reference below.
+ *
+ * key      CHOICE {
+ *   keyTable  Url,
+ *   cipherKey OCTET STRING
+ * } OPTIONAL
+ *
+ */
+static const struct arm_uc_mmDerElement manifestFwCryptKeyChoice[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_KEYTABLE_REF, ARM_UC_MM_ASN1_UTF8_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CIPHERKEY, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+};
+/**
+ * @brief Descriptor of cryptographic information block
+ * @details Contains the information necessary to manage the encryption of the payload.
+ * encryptionInfo SEQUENCE {
+ *     initVector OCTET STRING,
+ *     id,
+ *     key
+ * } OPTIONAL,
+ */
+static const struct arm_uc_mmDerElement manifestFwCryptInfo[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_CRYPT_IV, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CHOICE, ARM_UC_MM_ASN1_CHOICE, DER_MANDATORY, manifestFwCryptIdChoice),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CHOICE, ARM_UC_MM_ASN1_CHOICE, DER_OPTIONAL, manifestFwCryptKeyChoice),
+};
+
+/**
+ * @brief Descriptor of a firmware resource reference.
+ * @details Provides a hash, URL, and size of a payload
+ *
+ * ResourceReference ::= SEQUENCE {
+ *   hash        OCTET STRING,
+ *   url     Url OPTIONAL,
+ *   size    INTEGER
+ * }
+ */
+static const struct arm_uc_mmDerElement manifestFwRsrcRef[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE, ARM_UC_MM_ASN1_INTEGER, DER_MANDATORY),
+};
+
+/**
+ * @brief Descriptor of a payload description block
+ * @details Describes the payload, including:
+ * * The payload format
+ * * Any cryptographic information required to decrypt the payload
+ * * The storage identifier for payload (where to store it on the target)
+ * * The resource reference of the payload (where it is stored, etc)
+ * * A free-text version field
+ *
+ * FirmwareDescription ::= SEQUENCE {
+ *    format,
+ *    encryptionInfo OPTIONAL,
+ *    storageIdentifier UTF8String,
+ *    reference    ResourceReference,
+ *    version     UTF8String OPTIONAL
+ * }
+ */
+static const struct arm_uc_mmDerElement arm_uc_mmManifestFirmwareDescriptionElements[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FW_FMT_CHOICE, ARM_UC_MM_ASN1_CHOICE, DER_MANDATORY, manifestFwFmtChoice),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FW_CRYPT_INFO, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_OPTIONAL, manifestFwCryptInfo),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_STRG_ID, ARM_UC_MM_ASN1_UTF8_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FW_RSRC_REF, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, manifestFwRsrcRef),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_FW_VER, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
+};
+
+const struct arm_uc_mmDerElement arm_uc_mmManifestFirmwareDescription[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FIRMWARE, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_OPTIONAL, arm_uc_mmManifestFirmwareDescriptionElements),
+};
+
+/**
+ * @brief Descriptor of a manifest dependency reference
+ * @details Provides a hash, URL, and size of a manifest dependency
+ * ResourceReference ::= SEQUENCE {
+ *     hash        OCTET STRING,
+ *     url     Url OPTIONAL,
+ *     size    INTEGER
+ * }
+ */
+static const struct arm_uc_mmDerElement arm_uc_mmManifestDependency[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_DEP_REF_HASH, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_DEP_REF_URL, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_DEP_REF_SIZE, ARM_UC_MM_ASN1_INTEGER, DER_MANDATORY),
+};
+/**
+ * @brief Descriptor of a manifest dependency container
+ * @details Contains manifest dependency references
+ */
+const struct arm_uc_mmDerElement arm_uc_mmManifestDependencies[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_DEP, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmManifestDependency)
+};
+
+/**
+ * @brief Descriptor of the manifest sequence
+ * @details Contains all the information necessary to describe a manifest.
+ *
+ * Manifest ::= SEQUENCE {
+ *     manifestVersion     ENUMERATED {
+ *       v1(1)
+ *     },
+ *     description UTF8String OPTIONAL,
+ *     timestamp   INTEGER,
+ *     vendorId    UUID,
+ *     classId     UUID,
+ *     deviceId    UUID,
+ *     nonce       OCTET STRING,
+ *     vendorInfo  OCTET STRING,
+ *     applyPeriod OPTIONAL,
+ *     applyImmediately    BOOLEAN,
+ *     encryptionMode  CHOICE {
+ *         enum    ENUMERATED {
+ *             invalid(0),
+ *             aes-128-ctr-ecc-secp256r1-sha256(1),
+ *             none-ecc-secp256r1-sha256(2),
+ *             none-none-sha256(3)
+ *         },
+ *         objectId    OBJECT IDENTIFIER
+ *     },
+ *     aliases         SEQUENCE OF ResourceAlias,
+ *     dependencies    SEQUENCE OF ResourceReference,
+ *     firmware        FirmwareDescription OPTIONAL
+ */
+static const struct arm_uc_mmDerElement ManifestElements[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_VERSION, ARM_UC_MM_ASN1_ENUMERATED, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_DESC, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_TIMESTAMP, ARM_UC_MM_ASN1_INTEGER, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_VENDOR_UUID, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_CLASS_UUID, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_DEVICE_UUID, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_NONCE, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_VENDOR_INFO, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_APPLY_PERIOD, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_OPTIONAL, ManifestApplyPeriod),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_MFST_APPLY_IMMEDIATELY, ARM_UC_MM_ASN1_BOOLEAN, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_ENCRYPTION_MODE_CHOICE, ARM_UC_MM_ASN1_CHOICE, DER_OPTIONAL, encryptionModeChoice),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_RESOURCE_ALIASES, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, manifestResourceAliases),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_DEPS, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmManifestDependencies),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST_FIRMWARE, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_OPTIONAL, arm_uc_mmManifestFirmwareDescriptionElements),
+};
+
+/**
+ * @brief Descriptor of the Resource Choice
+ * @details The resource can be one of a limited number of options. Currently, the supported resource types are Manifest
+ * and Firmware Image. The firmware image is simply an OCTET STRING, whereas the Manifest is an ASN.1 SEQUENCE (DER
+ * encoded)
+ *
+ * resource CHOICE {
+ *     manifest Manifest,
+ *     firmware Firmware
+ * }
+ */
+static const struct arm_uc_mmDerElement ResourceChoiceElements[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_MFST, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, ManifestElements),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_FW_IMAGE, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+};
+
+/**
+ * @brief Descriptor of a Resource object.
+ * @details A resource is composed of an optional reference URL, a resource type identifier, and a resource.
+ *
+ * Resource ::= SEQUENCE {
+ *     url     Url OPTIONAL,
+ *     resourceType        ENUMERATED {
+ *         manifest(0), firmware(1)
+ *     },
+ *     resource
+ * }
+ */
+static const struct arm_uc_mmDerElement ResourceElements[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_RESOURCE_URL, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_RESOURCE_TYPE, ARM_UC_MM_ASN1_ENUMERATED, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_RESOURCE_CHOICE, ARM_UC_MM_ASN1_CHOICE, DER_MANDATORY, ResourceChoiceElements),
+};
+/**
+* @brief Descriptor of the certificate reference used for ECDSA signature verification
+* @details References an ECC certificate, which is used to perform ECDSA with the target device's public key. The
+* certificate used to sign the manifest is used to determine the permissions to be applied to the manifest.
+* NOTE: this is the same ASN.1 sequence as manifestFwCryptIdCertRef, but it is duplicated in the parser to reduce parsing time.
+*
+* CertificateReference ::= SEQUENCE {
+*     fingerprint  Bytes,
+*     url          Url
+* }
+
+ */
+static const struct arm_uc_mmDerElement arm_uc_mmSignatureCertificateReference[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_SIG_CERT_FINGERPRINT, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_SIG_CERT_URL, ARM_UC_MM_ASN1_UTF8_STRING, DER_OPTIONAL),
+};
+/**
+ * @brief Certificate Reference container
+ */
+const struct arm_uc_mmDerElement arm_uc_mmSignatureCertificateReferences[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_SIG_CERT, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmSignatureCertificateReference),
+};
+
+const struct arm_uc_mmDerElement arm_uc_mmSignatureBlock[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_SIG_SIGNATURE, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_SIG_CERTS, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmSignatureCertificateReferences),
+};
+const struct arm_uc_mmDerElement arm_uc_mmSignatures[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_SIG_SIGNATURE_BLOCK, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmSignatureBlock),
+};
+/**
+ * @brief Descriptor of a resource signature
+ * @details Contains the signature of the resource object. To facilitate fast integrity checking, a hash is also
+ * provided. The certificate references allow the target device to establish a chain of trust.
+ *
+ * ResourceSignature ::= SEQUENCE {
+ *     certificates SEQUENCE OF CertificateReference,
+ *     hash        OCTET STRING,
+ *     signature   OCTET STRING
+ * }
+ */
+const struct arm_uc_mmDerElement arm_uc_mmResourceSignature[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT_LEAF(ARM_UC_MM_DER_SIG_HASH, ARM_UC_MM_ASN1_OCTET_STRING, DER_MANDATORY),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_SIG_SIGNATURES, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmSignatures),
+};
+/**
+ * @brief Descriptor of a signed resource.
+ * @details The signed resource is a container for a resource and a signature.
+ * SignedResource ::= SEQUENCE {
+ *     resource  Resource,
+ *     signature ResourceSignature
+ * }
+ */
+static const struct arm_uc_mmDerElement SignedResourceElements[] =
+{
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_RESOURCE, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, ResourceElements),
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_SIG, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, arm_uc_mmResourceSignature),
+};
+/**
+ * @brief Container of a Signed Resource.
+ */
+static const struct arm_uc_mmDerElement SignedResource =
+    ARM_UC_MM_DER_ELEMENT_INIT(ARM_UC_MM_DER_ROOT, ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE, DER_MANDATORY, SignedResourceElements);
+
+#include "update-client-common/arm_uc_trace.h"
+
+enum arm_uc_mmDerParserLogLevels {
+    DER_PARSER_LOG_LEVEL_NONE,
+    DER_PARSER_LOG_LEVEL_DESCRIPTORS,
+    DER_PARSER_LOG_LEVEL_TAGS,
+    DER_PARSER_LOG_LEVEL_SIZES,
+    DER_PARSER_LOG_LEVEL_VALUES,
+    DER_PARSER_LOG_LEVEL_MAX
+};
+uint32_t arm_uc_mm_derRecurseDepth;
+
+#ifndef ARM_UC_DER_PARSER_TRACE_ENABLE
+#define ARM_UC_DER_PARSER_TRACE_ENABLE 0
+#endif
+
+#if ARM_UC_DER_PARSER_TRACE_ENABLE
+volatile uint32_t arm_uc_mm_der_gDebugLevel = DER_PARSER_LOG_LEVEL_MAX;
+
+#define DER_PARSER_LOG_INDENT(LOG_LEVEL)\
+do { \
+    if((LOG_LEVEL) <= arm_uc_mm_der_gDebugLevel) \
+    { \
+        for (uint32_t i = 0; i < arm_uc_mm_derRecurseDepth; i++) \
+        { \
+            printf("  "); \
+        } \
+    } \
+} while(0)
+
+#define DER_PARSER_LOG(LOG_LEVEL,...)\
+    do { \
+        if((LOG_LEVEL) <= arm_uc_mm_der_gDebugLevel) \
+        { \
+            printf(__VA_ARGS__); \
+        } \
+    } while(0)
+#else
+#define DER_PARSER_LOG_INDENT(LOG_LEVEL)
+#define DER_PARSER_LOG(LOG_LEVEL,...)
+#endif
+
+/*
+ * ASN.1 DER decoding routines
+ */
+int ARM_UC_MM_ASN1_get_len( unsigned char **p,
+                  const unsigned char *end,
+                  size_t *len )
+{
+    if( ( end - *p ) < 1 )
+        return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
+
+    if( ( **p & 0x80 ) == 0 )
+        *len = *(*p)++;
+    else
+    {
+        switch( **p & 0x7F )
+        {
+        case 1:
+            if( ( end - *p ) < 2 )
+                return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
+
+            *len = (*p)[1];
+            (*p) += 2;
+            break;
+
+        case 2:
+            if( ( end - *p ) < 3 )
+                return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
+
+            *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2];
+            (*p) += 3;
+            break;
+
+        case 3:
+            if( ( end - *p ) < 4 )
+                return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
+
+            *len = ( (size_t)(*p)[1] << 16 ) |
+                   ( (size_t)(*p)[2] << 8  ) | (*p)[3];
+            (*p) += 4;
+            break;
+
+        case 4:
+            if( ( end - *p ) < 5 )
+                return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
+
+            *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) |
+                   ( (size_t)(*p)[3] << 8  ) |           (*p)[4];
+            (*p) += 5;
+            break;
+
+        default:
+            return( ARM_UC_DP_ERR_ASN1_INVALID_LENGTH );
+        }
+    }
+
+    if( *len > (size_t) ( end - *p ) )
+        return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
+
+    return( 0 );
+}
+
+int ARM_UC_MM_ASN1_get_tag( unsigned char **p,
+                  const unsigned char *end,
+                  size_t *len, int tag )
+{
+    if( ( end - *p ) < 1 )
+        return( ARM_UC_DP_ERR_ASN1_OUT_OF_DATA );
+
+    if( **p != tag )
+        return( ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG );
+
+    (*p)++;
+
+    return( ARM_UC_MM_ASN1_get_len( p, end, len ) );
+}
+
+
+const char* ARM_UC_mmDERDescID2Str(uint32_t id)
+{
+    switch (id) {
+        #define ENUM_AUTO(name) case name: return #name;
+        ARM_UC_MM_DER_ID_LIST
+        #undef ENUM_AUTO
+    default:
+        return "Unknown DER ID";
+    }
+}
+
+/**
+ * @brief Internal state of the parser
+ */
+struct ARM_UC_MM_DERParserState {
+    uint32_t nValues;         //!< Number of values remaining to parse
+    const int32_t* valueIDs; //!< Current element of the value identifier array
+    arm_uc_buffer_t* buffers; //!< Current buffer of the value output array
+};
+/**
+ * @brief Converts a buffer to an unsigned 32-bit integer
+ * @details Assumes that the buffer is an unsigned, big-endian integer and returns it.
+ * Limitations:
+ * * Expects the buffer to be 4 bytes long or less
+ * * Does not trap NULL buffers
+ * * Does not trap NULL pointers
+ * * Does not permit sign extension of negative values
+ * @param[in] buf The buffer to convert to an integer
+ * @return The integer value of the buffer
+ */
+uint32_t ARM_UC_mmDerBuf2Uint(arm_uc_buffer_t* buf)
+{
+    uint32_t rc = 0;
+    unsigned i;
+    for (i = 0; i < buf->size && i < sizeof(uint32_t); i++)
+    {
+        rc = (rc << 8) | buf->ptr[i];
+    }
+    return rc;
+}
+/**
+ * @brief Converts a buffer to an unsigned 64-bit integer
+ * @details Assumes that the buffer is an unsigned, big-endian integer and returns it.
+ * Limitations:
+ * * Expects the buffer to be 8 bytes long or less
+ * * Does not trap NULL buffers
+ * * Does not trap NULL pointers
+ * * Does not permit sign extension of negative values
+ * @param[in] buf The buffer to convert to an integer
+ * @return The integer value of the buffer
+ */
+uint64_t ARM_UC_mmDerBuf2Uint64(arm_uc_buffer_t* buf)
+{
+    uint64_t rc = 0;
+    unsigned i;
+    for (i = 0; i < buf->size && i < sizeof(uint64_t); i++)
+    {
+        rc = (rc << 8) | buf->ptr[i];
+    }
+    return rc;
+}
+
+/**
+ * @brief Extracts the next tag in the DER string
+ * @details Validates the length of the string, then extracts the next value, interpreting it as a tag.
+ * Limitations:
+ * * Does not verify that any of the pointers are non-NULL
+ * * Does not validate tag values
+ * @param[in] p The current position in DER string
+ * @param[in] end The last position in the DER string
+ * @param[out] tag The extracted DER tag
+ * @retval 1 if the end has been encountered
+ * @retval 0 if the tag was successfully retrieved
+ */
+int ARM_UC_mmDERPeekTag(uint8_t* p, uint8_t* end, int* tag)
+{
+    if( ( end - p ) < 1 )
+    {
+        return( 1 );
+    }
+    *tag = *p;
+    return 0;
+}
+
+/**
+ * @brief Extracts one or more tagged values from DER encoded data
+ * @details Recursively traverses the DER tree, searching for the identified values.
+ * The parser parses the input data, identified by `*pos` according to the following rules:
+ *
+ * * If the current descriptor is a choice, `ARM_UC_mmDERGetValues` attempts to resolve the choice.
+ *     * Obtain the actual tag
+ *     * Loop through each child of the choice element and compare it to the tag
+ *     * If no tag mathces, return `ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG`
+ *     * Otherwise replace `desc` with the descriptor of the matching tag
+ * * Get the tag for the current descriptor
+ * * If the tag is not found
+ *     * If it was optional, exit with success
+ *     * Otherwise, exit with ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG
+ * * If the descriptor ID matches the current extraction ID
+ *     * Extract the value into the current buffer.
+ *     * Advance the ID pointer, the buffer pointer, and decrement the value pointer.
+ * * If the descriptor is a sequence with more than one child, recurse into it (single-child sequences are SEQUENCE OF)
+ *     * For each child element,
+ *         * If the end has been not reached or the child descriptor is mandatory
+ *             * call `ARM_UC_mmDERGetValues` with the child descriptor.
+ * * If the end does not match pos
+ *     * fail with `ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH`
+ * * Otherwise
+ *     * Update the current position
+ * * return success
+ *
+ * WARNING: ARM_UC_mmDERGetValues cannot resolve choices between two different sequences.
+ *
+ * NOTE: Choices are not currently returnable
+ * NOTE: An optimization should be possible to reduce the parsing time by skipping elements whose descriptors do not
+ *       contain the next requested element ID
+ * NOTE: Length mismatch checking is not currently supported.
+ *
+ * To parse a SEQUENCE OF element, search for the SEQUENCE OF. Then, iterate through its elements with
+ * `ARM_UC_mmDERGetSequenceElement`. With each element, call `ARM_UC_mmDERParseTree` with the descriptor for the
+ * contents of the SEQUENCE OF.
+ *
+ * @param[in] desc Contains the current parsing descriptor
+ * @param[in] pos Pointer to pointer that holds the current parsing location
+ * @param[in] end Pointer to the end of the current element's container
+ * @param[in,out] state Parser state. Contains the parser's
+ * @retval ARM_UC_DP_ERR_ASN1_OUT_OF_DATA     The parser has run out of data before running out of descriptors
+ * @retval ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG  The parser has encountered an encoding error, or unsupported DER document
+ * @retval ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH The elements of the DER tree do not have consistent lengths.
+ * @retval 0                                Success!
+ */
+int32_t ARM_UC_mmDERGetValues(const struct arm_uc_mmDerElement* desc, uint8_t** pos, uint8_t* end, struct ARM_UC_MM_DERParserState* state)
+{
+    size_t len;
+    int rc;
+    uint8_t* ElementEnd;
+    DER_PARSER_LOG_INDENT(DER_PARSER_LOG_LEVEL_DESCRIPTORS);
+    DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, "%s", ARM_UC_mmDERDescID2Str(desc->id));
+
+    // TODO: return a choice result when a choice ID is in the list.
+    // Resolve the a choice. Cannot distinguish choices between two sequences.
+    if (desc->tag == ARM_UC_MM_ASN1_CHOICE)
+    {
+        int tag;
+        unsigned i;
+        DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, "\n");
+        // Get the tag of the next element and identify the descriptor that matches that tag.
+        rc = ARM_UC_mmDERPeekTag(*pos, end, &tag);
+        if (rc)
+            return rc;
+        rc = ( ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG );
+        arm_uc_mm_derRecurseDepth++;
+        for (i = 0; i < desc->nSubElements; i++)
+        {
+            if (tag == desc->subElements[i].tag)
+            {
+                // desc = &desc->subElements[i];
+                // rc = 0;
+                rc = ARM_UC_mmDERGetValues(&desc->subElements[i], pos, end, state);
+                break;
+            }
+            else
+            {
+                DER_PARSER_LOG_INDENT(DER_PARSER_LOG_LEVEL_DESCRIPTORS);
+                DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, "%s (skipped)\n", ARM_UC_mmDERDescID2Str(desc->subElements[i].id));
+            }
+        }
+        arm_uc_mm_derRecurseDepth--;
+        // If the matching tag is not in one of the desctiptors, then a parse error has been encountered.
+        // if (rc)
+        return rc;
+    }
+    // Store the entry position for saving sequences
+    uint8_t* seqpos = *pos;
+    // Get the next tag & length, advancing the parse position to just after the tag/length pair.
+    rc = ARM_UC_MM_ASN1_get_tag(pos, end, &len, desc->tag);
+    // If an optional tag was expected, but not encountered, it is not an error unless it was requested by the user.
+    if (rc == ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG && desc->optional && desc->id != (unsigned)(state->valueIDs[0]))
+    {
+        DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, " (skipped)\n");
+        return 0;
+    } // TODO evaluate length handling in ARM_UC_MM_ASN1_get_tag
+    // If an error was encountered, abort.
+    if (rc)
+    {
+        DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, " (error %d)\n", rc);
+        return rc;
+    }
+    // If the encountered tag is one of the requested IDs, record its location and size, then move on to the next value
+    if (desc->id == (unsigned)(state->valueIDs[0]))
+    {
+        // If the element is a sequence, store the whole element, not just the content.
+        if (desc->tag == (ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE) && desc->nSubElements != 1)
+        {
+            state->buffers[0].ptr = seqpos;
+            state->buffers[0].size = len + (*pos - seqpos);
+            state->buffers[0].size_max = len + (*pos - seqpos);
+        }
+        else
+        {
+            state->buffers[0].ptr = *pos;
+            state->buffers[0].size = len;
+            state->buffers[0].size_max = len;
+        }
+        state->nValues--;
+        state->valueIDs++;
+        state->buffers++;
+        DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, " (stored)\n");
+    }
+    else
+    {
+        DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_DESCRIPTORS, "\n");
+    }
+    DER_PARSER_LOG_INDENT(DER_PARSER_LOG_LEVEL_TAGS);
+    DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_TAGS, "%02X", desc->tag);
+    DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_SIZES, " %X", len);
+    if (desc->tag != (ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE))
+    {
+        DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_VALUES, " ");
+        for (uint32_t i = 0; i < len; i++)
+        {
+            if (desc->tag == ARM_UC_MM_ASN1_UTF8_STRING)
+            {
+                DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_VALUES, "%c", (char)(*pos)[i]);
+            }
+            else
+            {
+                DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_VALUES, "%X", (*pos)[i]);
+            }
+        }
+    }
+    DER_PARSER_LOG(DER_PARSER_LOG_LEVEL_TAGS, "\n");
+
+    // TODO: At this point, it should be possible to exit parsing of this element early if no requested ID is owned by
+    // this element or one of its children.
+
+    // Update the end of the current element to pos+len
+    ElementEnd = *pos + len;
+    // If the element is a sequence, parse the sequence.
+    if (desc->tag == (ARM_UC_MM_ASN1_CONSTRUCTED | ARM_UC_MM_ASN1_SEQUENCE))
+    {
+        /* Sequences with only a single element are treated as a SEQUENCE OF, which has special semantics. In order to
+         * extract the contents of a SEQUENCE OF, the caller must request the SEQUENCE OF element ID, then use
+         * ARM_UC_mmDERGetSequenceElement to extract the contents of the sequence, passing each one to
+         * ARM_UC_mmDERParseTree in order to extract any */
+        if (desc->nSubElements != 1) // SEQUENCE
+        {
+            int i;
+            end = *pos + len;
+            arm_uc_mm_derRecurseDepth++;
+            for ( i = 0; rc == 0 && state->nValues != 0 && i < desc->nSubElements; i++ )
+            {
+                // Escape if the end has been reached and the parsing elements are optional
+                if (!(*pos >= end && desc->subElements[i].optional)) {
+                    // Parse a sub-tree
+                    rc = ARM_UC_mmDERGetValues(&desc->subElements[i], pos, end, state);
+                }
+            }
+            arm_uc_mm_derRecurseDepth--;
+        }
+    }
+
+    if (*pos > ElementEnd) // TODO: Add length mismatch check
+    {
+        // Fail if there is a length mismatch
+        return ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH;
+    }
+    else
+    {
+        // Update the current parsing position
+        *pos = ElementEnd;
+    }
+    return rc;
+}
+
+/**
+ * @brief Extracts elements from an ASN.1 SEQUENCE OF by index
+ * @details Parses a SEQUENCE OF element, skipping elements until it finds the requested element.
+ * When the last element has been parsed, a further call to `ARM_UC_mmDERGetSequenceElement` will cause element to be
+ * populated with a NULL buffer pointer and 0 length, but `ARM_UC_mmDERGetSequenceElement` will still return success.
+ *
+ * @param[in]  buffer  The data to parse
+ * @param[in]  index   The element index to extract
+ * @param[out] element The buffer to populate with the extracted element
+ *
+ * @retval ARM_UC_DP_ERR_ASN1_OUT_OF_DATA     The parser has run out of data before running out of descriptors
+ * @retval ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG  The parser has encountered an encoding error, or unsupported DER document
+ * @retval ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH The elements of the DER tree do not have consistent lengths.
+ * @retval 0                                Success!
+ */
+int32_t ARM_UC_mmDERGetSequenceElement(arm_uc_buffer_t* buffer, uint32_t index, arm_uc_buffer_t* element)
+{
+    uint8_t* pos      = buffer->ptr;
+    uint8_t* end      = pos + buffer->size;
+    int rc            = 0;
+    size_t len        = 0;
+    element->ptr      = NULL;
+    element->size     = 0;
+    element->size_max = 0;
+    for(; !rc; index--)
+    {
+        int tag;
+        rc = ARM_UC_mmDERPeekTag(pos, end, &tag);
+        if (rc)
+        {
+            // Peek-tag can only fail if pos >= end, so there was no element
+            // This is not an error, since the parser may not know how many elements are in the sequence.
+            return 0;
+        }
+        if (!index)
+        {
+            element->ptr = pos;
+        }
+        rc = ARM_UC_MM_ASN1_get_tag(&pos, end, &len, tag);
+        if (!index && !rc)
+        {
+            element->size     = len + pos - element->ptr;
+            element->size_max = element->size;
+            break;
+        }
+        if (rc)
+        {
+            element->ptr = NULL;
+            break;
+        }
+        pos += len;
+    }
+    return rc;
+}
+
+/**
+ * @brief Parses a tree of DER data by calling `ARM_UC_mmDERGetValues`
+ * @details Populates a parser state with the IDs to be extracted, the number of values and the buffers to extract into
+ * @param[in]  desc     Contains the current parsing descriptor
+ * @param[in]  buffer   The data to parse
+ * @param[in]  nValues  The number of values to search for
+ * @param[in]  valueIDs Array of value identifiers
+ * @param[out] buffers  Array of buffers to populate with the elements matching valueIDs
+ * @retval ARM_UC_DP_ERR_ASN1_OUT_OF_DATA     The parser has run out of data before running out of descriptors
+ * @retval ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG  The parser has encountered an encoding error, or unsupported DER document
+ * @retval ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH The elements of the DER tree do not have consistent lengths.
+ * @retval 0                                Success!
+ * @retval >0                               Number of remaining elements
+ */
+int32_t ARM_UC_mmDERParseTree(const struct arm_uc_mmDerElement* desc, arm_uc_buffer_t* buffer, uint32_t nValues, const int32_t* valueIDs, arm_uc_buffer_t* buffers)
+{
+    uint8_t *pos = buffer->ptr;
+    uint8_t *end = pos + buffer->size;
+    struct ARM_UC_MM_DERParserState state = {
+        nValues, valueIDs, buffers
+    };
+    arm_uc_mm_derRecurseDepth = 0;
+    int32_t rc = ARM_UC_mmDERGetValues(desc, &pos, end, &state);
+    // printf("Failed at: index %lu: %lu with return code: %ld\n", nValues-state.nValues, *state.valueIDs, rc);
+    if (rc == 0 && state.nValues != 0)
+    {
+        return state.nValues;
+    }
+    return rc;
+}
+/**
+ * @brief Parses a tree of DER data by calling `ARM_UC_mmDERGetValues`
+ * @details Populates a parser state with the IDs to be extracted, the number of values and the buffers to extract into
+ * Calls `ARM_UC_mmDERParseTree` with `SignedResource`
+ * @param[in]  buffer   The data to parse
+ * @param[in]  nValues  The number of values to search for
+ * @param[in]  valueIDs Array of value identifiers
+ * @param[out] buffers  Array of buffers to populate with the elements matching valueIDs
+ * @retval ARM_UC_DP_ERR_ASN1_OUT_OF_DATA     The parser has run out of data before running out of descriptors
+ * @retval ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG  The parser has encountered an encoding error, or unsupported DER document
+ * @retval ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH The elements of the DER tree do not have consistent lengths.
+ * @retval 0                                Success!
+ * @retval >0                               Number of remaining elements
+ */
+int32_t ARM_UC_mmDERGetSignedResourceValues(arm_uc_buffer_t* buffer, uint32_t nValues, const int32_t* valueIDs, arm_uc_buffer_t* buffers)
+{
+    return ARM_UC_mmDERParseTree(&SignedResource, buffer, nValues, valueIDs, buffers);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmDerManifestParser.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,181 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_MM_DERPARSE_H
+#define ARM_UC_MM_DERPARSE_H
+
+#include "update-client-common/arm_uc_types.h"
+#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name DER constants
+ * These constants comply with DER encoded the ANS1 type tags.
+ * DER encoding uses hexadecimal representation.
+ * An example DER sequence is:\n
+ * - 0x02 -- tag indicating INTEGER
+ * - 0x01 -- length in octets
+ * - 0x05 -- value
+ * Such sequences are typically read into \c ::mbedtls_x509_buf.
+ * \{
+ */
+#define ARM_UC_MM_ASN1_BOOLEAN                 0x01
+#define ARM_UC_MM_ASN1_INTEGER                 0x02
+#define ARM_UC_MM_ASN1_BIT_STRING              0x03
+#define ARM_UC_MM_ASN1_OCTET_STRING            0x04
+#define ARM_UC_MM_ASN1_NULL                    0x05
+#define ARM_UC_MM_ASN1_OID                     0x06
+#define ARM_UC_MM_ASN1_ENUMERATED              0x0A
+#define ARM_UC_MM_ASN1_UTF8_STRING             0x0C
+#define ARM_UC_MM_ASN1_SEQUENCE                0x10
+#define ARM_UC_MM_ASN1_SET                     0x11
+#define ARM_UC_MM_ASN1_PRINTABLE_STRING        0x13
+#define ARM_UC_MM_ASN1_T61_STRING              0x14
+#define ARM_UC_MM_ASN1_IA5_STRING              0x16
+#define ARM_UC_MM_ASN1_UTC_TIME                0x17
+#define ARM_UC_MM_ASN1_GENERALIZED_TIME        0x18
+#define ARM_UC_MM_ASN1_UNIVERSAL_STRING        0x1C
+#define ARM_UC_MM_ASN1_BMP_STRING              0x1E
+#define ARM_UC_MM_ASN1_PRIMITIVE               0x00
+#define ARM_UC_MM_ASN1_CONSTRUCTED             0x20
+#define ARM_UC_MM_ASN1_CONTEXT_SPECIFIC        0x80
+#define ARM_UC_MM_ASN1_CHOICE                  0xFF // NOTE: This is not a real ASN1 number; it is a marker for choices
+
+/* \} name */
+
+/**
+ * \name ASN1 Error codes
+ * These error codes are OR'ed to X509 error codes for
+ * higher error granularity.
+ * ASN1 is a standard to specify data structures.
+ * \{
+ */
+#define ARM_UC_DP_ERR_ASN1_OUT_OF_DATA                      -0x0060  /**< Out of data when parsing an ASN1 data structure. */
+#define ARM_UC_DP_ERR_ASN1_UNEXPECTED_TAG                   -0x0062  /**< ASN1 tag was of an unexpected value. */
+#define ARM_UC_DP_ERR_ASN1_INVALID_LENGTH                   -0x0064  /**< Error when trying to determine the length or invalid length. */
+#define ARM_UC_DP_ERR_ASN1_LENGTH_MISMATCH                  -0x0066  /**< Actual length differs from expected length. */
+#define ARM_UC_DP_ERR_ASN1_INVALID_DATA                     -0x0068  /**< Data is invalid. (not used) */
+#define ARM_UC_DP_ERR_ASN1_ALLOC_FAILED                     -0x006A  /**< Memory allocation failed */
+#define ARM_UC_DP_ERR_ASN1_BUF_TOO_SMALL                    -0x006C  /**< Buffer too small when writing ASN.1 data structure. */
+
+/* \} name */
+
+
+#define ARM_UC_MM_DER_ID_LIST \
+    ENUM_AUTO(ARM_UC_MM_DER_UNINIT)\
+    ENUM_AUTO(ARM_UC_MM_DER_ROOT)\
+    ENUM_AUTO(ARM_UC_MM_DER_RESOURCE)\
+    ENUM_AUTO(ARM_UC_MM_DER_RESOURCE_URL)\
+    ENUM_AUTO(ARM_UC_MM_DER_RESOURCE_TYPE)\
+    ENUM_AUTO(ARM_UC_MM_DER_RESOURCE_CHOICE)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_VERSION)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_DESC)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_TIMESTAMP)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_UUIDS)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_VENDOR_UUID)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_CLASS_UUID)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_DEVICE_UUID)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_NONCE)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_VENDOR_INFO)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_APPLY_PERIOD)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_VALID_FROM)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_VALID_TO)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_APPLY_IMMEDIATELY)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_ENCRYPTION_MODE_CHOICE)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_ENC_ENUM)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_ENC_OID)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_RESOURCE_ALIASES)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_RESOURCE_ALIAS)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_RESOURCE_ALIAS_HASH)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_RESOURCE_ALIAS_URL)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FIRMWARE)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_FMT_CHOICE)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_FMT_ENUM)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_FMT_OID)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_INFO)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_IV)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CHOICE)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_LOCAL)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_REF)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_FINGERPRINT)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_URL)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CHOICE)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CIPHERKEY)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_KEYTABLE_REF)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_STRG_ID)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_VER)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_DEPS)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_DEP)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_DEP_REF_HASH)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_DEP_REF_URL)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_DEP_REF_SIZE)\
+    ENUM_AUTO(ARM_UC_MM_DER_FW_IMAGE)\
+    ENUM_AUTO(ARM_UC_MM_DER_SIG)\
+    ENUM_AUTO(ARM_UC_MM_DER_SIG_HASH)\
+    ENUM_AUTO(ARM_UC_MM_DER_SIG_SIGNATURES)\
+    ENUM_AUTO(ARM_UC_MM_DER_SIG_SIGNATURE_BLOCK)\
+    ENUM_AUTO(ARM_UC_MM_DER_SIG_SIGNATURE)\
+    ENUM_AUTO(ARM_UC_MM_DER_SIG_CERTS)\
+    ENUM_AUTO(ARM_UC_MM_DER_SIG_CERT)\
+    ENUM_AUTO(ARM_UC_MM_DER_SIG_CERT_FINGERPRINT)\
+    ENUM_AUTO(ARM_UC_MM_DER_SIG_CERT_URL)\
+
+enum derIDs {
+#define ENUM_AUTO(X) X,
+    ARM_UC_MM_DER_ID_LIST
+#undef ENUM_AUTO
+};
+
+#define ARM_UC_DER_PARSER_ERROR_PREFIX TWO_CC('D', 'P')
+
+struct arm_uc_mmDerElement
+{
+    uint32_t id;
+    const struct arm_uc_mmDerElement* subElements;
+    uint8_t tag;
+    uint8_t optional;
+    uint8_t nSubElements;
+};
+
+extern const struct arm_uc_mmDerElement arm_uc_mmManifestUUID[];
+extern const struct arm_uc_mmDerElement arm_uc_mmManifestDependencies[];
+extern const struct arm_uc_mmDerElement arm_uc_mmManifestFirmwareDescription[];
+extern const struct arm_uc_mmDerElement arm_uc_mmResourceSignature[];
+extern const struct arm_uc_mmDerElement arm_uc_mmSignatures[];
+extern const struct arm_uc_mmDerElement arm_uc_mmSignatureCertificateReferences[];
+
+int32_t ARM_UC_mmDERGetSignedResourceValues(arm_uc_buffer_t* buffer, uint32_t nValues, const int32_t* valueIDs, arm_uc_buffer_t* buffers);
+uint32_t ARM_UC_mmDerBuf2Uint(arm_uc_buffer_t* buf);
+uint64_t ARM_UC_mmDerBuf2Uint64(arm_uc_buffer_t* buf);
+int32_t ARM_UC_mmDERGetSequenceElement(arm_uc_buffer_t* buffer, uint32_t index, arm_uc_buffer_t* element);
+int32_t ARM_UC_mmDERParseTree(const struct arm_uc_mmDerElement* desc, arm_uc_buffer_t* buffer, uint32_t nValues, const int32_t* valueIDs, arm_uc_buffer_t* buffers);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // ARM_UC_MM_DERPARSE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmFSMHelper.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,36 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_MM_FSM_HELPER_H
+#define ARM_UC_MM_FSM_HELPER_H
+
+#define ARM_UC_MM_FSM_HELPER_START(CONTEXT, STATE_STR_FN)\
+    uint32_t oldState;\
+    ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES, "> %s (%u)\n", __PRETTY_FUNCTION__, (unsigned)event);\
+    do {\
+        oldState = (CONTEXT).state;\
+        ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES, "+ %s state: %s(%u)\n", __PRETTY_FUNCTION__,\
+            STATE_STR_FN((CONTEXT).state), (unsigned)(CONTEXT).state);\
+        switch ((CONTEXT).state)
+
+#define ARM_UC_MM_FSM_HELPER_FINISH(CONTEXT)\
+    } while (err.code == MFST_ERR_NONE && oldState != (CONTEXT).state);\
+    ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES, "< %s %c%c:%hu (%s)\n", __PRETTY_FUNCTION__,\
+        err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err))
+
+#endif // ARM_UC_MM_FSM_HELPER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmFetchFirmwareInfo.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,393 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "arm_uc_mmCryptoUtils.h"
+#include "arm_uc_mmCommon.h"
+#include "arm_uc_mmConfig.h"
+#include "arm_uc_mmDerManifestAccessors.h"
+#include "arm_uc_mmDerManifestParser.h"
+#include "arm_uc_mmFSMHelper.h"
+#include "update-client-common/arm_uc_scheduler.h"
+
+#include "update-client-manifest-manager/update-client-manifest-manager.h"
+#include "update-client-manifest-manager/update-client-manifest-types.h"
+
+#include "pal.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+
+#define htobe PAL_HTONL
+#ifndef htobe
+static inline uint32_t htobe(uint32_t x)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+    return __builtin_bswap32(x);
+#else
+    return x;
+#endif
+}
+#endif
+
+#undef ARRAY_SIZE
+#define ARRAY_SIZE(ENUM_AUTO)\
+    (sizeof(ENUM_AUTO)/sizeof((ENUM_AUTO)[0]))
+
+
+#define ARM_UC_MM_MFST_IMAGE_REF_FIELDS \
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_FMT_ENUM)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_STRG_ID)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE)\
+
+static const int32_t imageRefFields [] = {
+    #define ENUM_AUTO(ENUM_AUTO) ENUM_AUTO,
+    ARM_UC_MM_MFST_IMAGE_REF_FIELDS
+    #undef ENUM_AUTO
+};
+enum imageRefFieldIdxs {
+    #define ENUM_AUTO(ENUM_AUTO) IRF_ ## ENUM_AUTO ## _IDX,
+    ARM_UC_MM_MFST_IMAGE_REF_FIELDS
+    #undef ENUM_AUTO
+};
+
+#if ARM_UC_MANIFEST_MANAGER_TRACE_ENABLE
+static const char* ARM_UC_mmFwState2Str(uint32_t state)
+{
+    switch (state) {
+        #define ENUM_AUTO(name) case name: return #name;
+        #define ENUM_FIXED(name, val) ENUM_AUTO(name)
+        ARM_UC_MM_FW_STATE_LIST
+        #undef ENUM_AUTO
+        #undef ENUM_FIXED
+    default:
+        return "Unknown State";
+    }
+}
+#endif
+
+int ARM_UC_mmGetImageRef(manifest_firmware_info_t* info, arm_uc_buffer_t* mfst_fwref)
+{
+    arm_uc_buffer_t buffers[ARRAY_SIZE(imageRefFields)];
+    int rc = ARM_UC_mmDERParseTree(arm_uc_mmManifestFirmwareDescription,
+                          mfst_fwref,
+                          ARRAY_SIZE(imageRefFields),
+                          imageRefFields,
+                          buffers);
+    if (rc == 0)
+    {
+        // Found local key ID and encrypted key
+        info->cipherMode = ARM_UC_MM_CIPHERMODE_NONE;
+        // TODO: Handle non-enum format
+        uint32_t format = ARM_UC_mmDerBuf2Uint(&buffers[IRF_ARM_UC_MM_DER_MFST_FW_FMT_ENUM_IDX]);
+        memset(&info->format, 0, sizeof(info->format));
+        info->format.words[RFC_4122_WORDS-1] = htobe(format);
+
+        ARM_UC_buffer_shallow_copy(&info->strgId, &buffers[IRF_ARM_UC_MM_DER_MFST_FW_STRG_ID_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->hash, &buffers[IRF_ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->uri, &buffers[IRF_ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL_IDX]);
+        info->size = ARM_UC_mmDerBuf2Uint(&buffers[IRF_ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE_IDX]);
+    }
+    return rc;
+}
+
+#define ARM_UC_MM_MFST_CRYPT_LOCAL_ID_FIELDS \
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_FMT_ENUM)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_IV)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_LOCAL)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CIPHERKEY)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_STRG_ID)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE)\
+
+static const int32_t localEncKeyFields [] = {
+    #define ENUM_AUTO(ENUM_AUTO) ENUM_AUTO,
+    ARM_UC_MM_MFST_CRYPT_LOCAL_ID_FIELDS
+    #undef ENUM_AUTO
+};
+enum localEncKeyFieldIdxs {
+    #define ENUM_AUTO(ENUM_AUTO) LEK_ ## ENUM_AUTO ## _IDX,
+    ARM_UC_MM_MFST_CRYPT_LOCAL_ID_FIELDS
+    #undef ENUM_AUTO
+};
+
+int ARM_UC_mmGetLocalIDAndKey(manifest_firmware_info_t* info, arm_uc_buffer_t* mfst_fwref)
+{
+    arm_uc_buffer_t buffers[ARRAY_SIZE(localEncKeyFields)];
+    int rc = ARM_UC_mmDERParseTree(arm_uc_mmManifestFirmwareDescription,
+                          mfst_fwref,
+                          ARRAY_SIZE(localEncKeyFields),
+                          localEncKeyFields,
+                          buffers);
+    if (rc == 0)
+    {
+        // Found local key ID and encrypted key
+        info->cipherMode = ARM_UC_MM_CIPHERMODE_PSK;
+        // TODO: Handle non-enum format
+        uint32_t format = ARM_UC_mmDerBuf2Uint(&buffers[LEK_ARM_UC_MM_DER_MFST_FW_FMT_ENUM_IDX]);
+        memset(&info->format, 0, sizeof(info->format));
+        info->format.words[RFC_4122_WORDS-1] = htobe(format);
+        ARM_UC_buffer_shallow_copy(&info->initVector, &buffers[LEK_ARM_UC_MM_DER_MFST_FW_CRYPT_IV_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->psk.keyID, &buffers[LEK_ARM_UC_MM_DER_MFST_FW_FMT_ENUM_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->psk.cipherKey, &buffers[LEK_ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CIPHERKEY_IDX]);
+
+        ARM_UC_buffer_shallow_copy(&info->strgId, &buffers[LEK_ARM_UC_MM_DER_MFST_FW_STRG_ID_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->hash, &buffers[LEK_ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->uri, &buffers[LEK_ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL_IDX]);
+        info->size = ARM_UC_mmDerBuf2Uint(&buffers[LEK_ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE_IDX]);
+    }
+    return rc;
+}
+
+
+#define ARM_UC_MM_MFST_CRYPT_CERT_KEY_FIELDS \
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_FMT_ENUM)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_IV)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_FINGERPRINT)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_URL)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CIPHERKEY)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_STRG_ID)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE)\
+
+static const int32_t certEncKeyFields [] = {
+    #define ENUM_AUTO(ENUM_AUTO) ENUM_AUTO,
+    ARM_UC_MM_MFST_CRYPT_CERT_KEY_FIELDS
+    #undef ENUM_AUTO
+};
+
+enum certEncKeyFieldIdxs {
+    #define ENUM_AUTO(ENUM_AUTO) CEK_ ## ENUM_AUTO ## _IDX,
+    ARM_UC_MM_MFST_CRYPT_CERT_KEY_FIELDS
+    #undef ENUM_AUTO
+};
+
+int ARM_UC_mmGetCertAndKey(manifest_firmware_info_t* info, arm_uc_buffer_t* mfst_fwref)
+{
+    arm_uc_buffer_t buffers[ARRAY_SIZE(certEncKeyFields)];
+    int rc = ARM_UC_mmDERParseTree(arm_uc_mmManifestFirmwareDescription,
+                          mfst_fwref,
+                          ARRAY_SIZE(certEncKeyFields),
+                          certEncKeyFields,
+                          buffers);
+    if (rc == 0)
+    {
+        info->cipherMode = ARM_UC_MM_CIPHERMODE_CERT_CIPHERKEY;
+        // TODO: Handle non-enum format
+        uint32_t format = ARM_UC_mmDerBuf2Uint(&buffers[CEK_ARM_UC_MM_DER_MFST_FW_FMT_ENUM_IDX]);
+        memset(&info->format, 0, sizeof(info->format));
+        info->format.words[RFC_4122_WORDS-1] = htobe(format);
+        ARM_UC_buffer_shallow_copy(&info->initVector, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_CRYPT_IV_IDX]);
+
+        ARM_UC_buffer_shallow_copy(&info->certCK.certFingerPrint, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_FINGERPRINT_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->certCK.certURL, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_URL_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->certCK.cipherKey, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_CIPHERKEY_IDX]);
+
+        ARM_UC_buffer_shallow_copy(&info->strgId, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_STRG_ID_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->hash, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->uri, &buffers[CEK_ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL_IDX]);
+        info->size = ARM_UC_mmDerBuf2Uint(&buffers[CEK_ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE_IDX]);
+    }
+    return rc;
+}
+
+
+#define ARM_UC_MM_MFST_CRYPT_CERT_KEYTABLE_FIELDS \
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_FMT_ENUM)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_IV)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_FINGERPRINT)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_URL)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_KEYTABLE_REF)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_STRG_ID)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL)\
+    ENUM_AUTO(ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE)\
+
+static const int32_t certKeyTableFields [] = {
+    #define ENUM_AUTO(ENUM_AUTO) ENUM_AUTO,
+    ARM_UC_MM_MFST_CRYPT_CERT_KEYTABLE_FIELDS
+    #undef ENUM_AUTO
+};
+
+enum certKeyTableFieldIdxs {
+    #define ENUM_AUTO(ENUM_AUTO) CKT_ ## ENUM_AUTO ## _IDX,
+    ARM_UC_MM_MFST_CRYPT_CERT_KEYTABLE_FIELDS
+    #undef ENUM_AUTO
+};
+
+int ARM_UC_mmGetCertAndKeyTable(manifest_firmware_info_t* info, arm_uc_buffer_t* mfst_fwref)
+{
+    arm_uc_buffer_t buffers[ARRAY_SIZE(certKeyTableFields)];
+    int rc = ARM_UC_mmDERParseTree(arm_uc_mmManifestFirmwareDescription,
+                          mfst_fwref,
+                          ARRAY_SIZE(certKeyTableFields),
+                          certKeyTableFields,
+                          buffers);
+    if (rc == 0)
+    {
+        info->cipherMode = ARM_UC_MM_CIPHERMODE_CERT_KEYTABLE;
+        // TODO: Handle non-enum format
+        uint32_t format = ARM_UC_mmDerBuf2Uint(&buffers[CKT_ARM_UC_MM_DER_MFST_FW_FMT_ENUM_IDX]);
+        memset(&info->format, 0, sizeof(info->format));
+        info->format.words[RFC_4122_WORDS-1] = htobe(format);
+        ARM_UC_buffer_shallow_copy(&info->initVector, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_CRYPT_IV_IDX]);
+
+        ARM_UC_buffer_shallow_copy(&info->certKT.certFingerPrint, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_FINGERPRINT_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->certKT.certURL, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_CRYPT_ID_CERT_URL_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->certKT.keyTableURL, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_CRYPT_KEY_KEYTABLE_REF_IDX]);
+
+        ARM_UC_buffer_shallow_copy(&info->strgId, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_STRG_ID_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->hash, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_RSRC_REF_HASH_IDX]);
+        ARM_UC_buffer_shallow_copy(&info->uri, &buffers[CKT_ARM_UC_MM_DER_MFST_FW_RSRC_REF_URL_IDX]);
+        info->size = ARM_UC_mmDerBuf2Uint(&buffers[CKT_ARM_UC_MM_DER_MFST_FW_RSRC_REF_SIZE_IDX]);
+    }
+    return rc;
+}
+
+arm_uc_error_t ARM_UC_mmFetchFirmwareInfoFSM(uint32_t event)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    if (arm_uc_mmPersistentContext.ctx == NULL || *arm_uc_mmPersistentContext.ctx == NULL)
+    {
+        return (arm_uc_error_t){MFST_ERR_NULL_PTR};
+    }
+    struct arm_uc_mm_fw_context_t* ctx = &(*arm_uc_mmPersistentContext.ctx)->getFw;
+    if (ctx->info == NULL)
+    {
+        return (arm_uc_error_t){MFST_ERR_NULL_PTR};
+    }
+    ARM_UC_MM_FSM_HELPER_START(*ctx, ARM_UC_mmFwState2Str) {
+        case ARM_UC_MM_FW_STATE_IDLE:
+            err = (arm_uc_error_t){MFST_ERR_NONE};
+            break;
+        case ARM_UC_MM_FW_STATE_BEGIN:
+        {
+            // If there is no manifest storage, assume it is still present in the input buffer
+            ctx->state = ARM_UC_MM_FW_STATE_READ_URI;
+            ARM_UC_MM_SET_BUFFER(ctx->current_data, ctx->info->manifestBuffer);
+            ctx->current_data.size = ctx->info->manifestSize;
+            break;
+        }
+        case ARM_UC_MM_FW_STATE_READ_URI:
+        {
+            // Get the encryption mode and the firmware info block.
+            const int32_t fieldIDs [] = {ARM_UC_MM_DER_MFST_ENC_ENUM, ARM_UC_MM_DER_MFST_FIRMWARE};
+            arm_uc_buffer_t buffers [sizeof(fieldIDs)/sizeof(fieldIDs[0])];
+            int rc = ARM_UC_mmDERGetSignedResourceValues(
+                    &ctx->current_data,
+                    sizeof(fieldIDs)/sizeof(fieldIDs[0]),
+                    fieldIDs,
+                    buffers);
+            if (rc < 0)
+            {
+                err.code = MFST_ERR_DER_FORMAT;
+                break;
+            }
+            else if (rc > 0)
+            {
+                // in storage mode, firmware must be supplied.
+                err.code = MFST_ERR_EMPTY_FIELD;
+                break;
+            }
+            arm_uc_buffer_t fwBuf;
+            ARM_UC_buffer_shallow_copy(&fwBuf, &buffers[1]);
+
+            // Store timestamp
+            ARM_UC_MM_SET_BUFFER(ctx->current_data, ctx->info->manifestBuffer);
+            ctx->current_data.size = ctx->info->manifestSize;
+            err = ARM_UC_mmGetTimestamp(&ctx->current_data, &ctx->info->timestamp);
+            if (err.error != 0)
+            {
+                break;
+            }
+
+            ctx->info->cipherMode = ARM_UC_MM_CIPHERMODE_NONE;
+            // Found an encryption mode and firmware!
+            uint32_t cryptoMode = ARM_UC_mmDerBuf2Uint(&buffers[0]);
+            if (!ARM_UC_mmGetCryptoFlags(cryptoMode).aes)
+            {
+                // Encryption not in use. Skip key, ID, and IV extraction.
+                rc = ARM_UC_mmGetImageRef(ctx->info, &fwBuf);
+                if (rc == 0)
+                {
+                    ctx->state = ARM_UC_MM_FW_STATE_NOTIFY;
+                    err.code = MFST_ERR_NONE;
+                }
+                else
+                {
+                    err.code = MFST_ERR_DER_FORMAT;
+                }
+                break;
+            }
+            // There are three possible combinations of encryption info:
+            // local key ID & encrypted key
+            rc = ARM_UC_mmGetLocalIDAndKey(ctx->info, &fwBuf);
+            if (!rc) {
+                ctx->state = ARM_UC_MM_FW_STATE_NOTIFY;
+                err.code = MFST_ERR_NONE;
+                break;
+            }
+            // Certificate and encrypted key
+            rc = ARM_UC_mmGetCertAndKey(ctx->info, &fwBuf);
+            if (!rc) {
+                ctx->state = ARM_UC_MM_FW_STATE_NOTIFY;
+                err.code = MFST_ERR_NONE;
+                break;
+            }
+            // Certificate and key table reference
+            rc = ARM_UC_mmGetCertAndKeyTable(ctx->info, &fwBuf);
+            if (!rc) {
+                ctx->state = ARM_UC_MM_FW_STATE_NOTIFY;
+                err.code = MFST_ERR_NONE;
+                break;
+            }
+
+            break;
+        }
+        case ARM_UC_MM_FW_STATE_GET_FW_REF:
+
+            // TODO: Ref only
+        case ARM_UC_MM_FW_STATE_NOTIFY:
+            ctx->state = ARM_UC_MM_FW_STATE_ROOT_NOTIFY_WAIT;
+            err.code = MFST_ERR_PENDING;
+            ARM_UC_PostCallback(&ctx->callbackStorage, arm_uc_mmPersistentContext.applicationEventHandler, ARM_UC_MM_RC_NEED_FW);
+            break;
+
+        case ARM_UC_MM_FW_STATE_ROOT_NOTIFY_WAIT:
+            if (event == ARM_UC_MM_EVENT_BEGIN)
+            {
+                err.code = MFST_ERR_NONE;
+                ctx->state = ARM_UC_MM_FW_STATE_DONE;
+            }
+            break;
+        case ARM_UC_MM_FW_STATE_DONE:
+            // NOTE: The outer FSM will send the "done" message.
+            ctx->state = ARM_UC_MM_FW_STATE_IDLE;
+            break;
+        case ARM_UC_MM_FW_STATE_INVALID:
+        default:
+            err = (arm_uc_error_t){MFST_ERR_INVALID_STATE};
+            break;
+    } ARM_UC_MM_FSM_HELPER_FINISH(*ctx);
+    return err;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmFetchFirmwareInfo.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,28 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef MANIFEST_MANAGER_FETCH_FIRMWARE_INFO_H
+#define MANIFEST_MANAGER_FETCH_FIRMWARE_INFO_H
+
+
+#include "arm_uc_mmConfig.h"
+#include "update-client-common/arm_uc_common.h"
+
+arm_uc_error_t ARM_UC_mmFetchFirmwareInfoFSM(uint32_t event);
+
+#endif // MANIFEST_MANAGER_FETCH_FIRMWARE_INFO_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmGetLatestTimestamp.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,87 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "arm_uc_mmConfig.h"
+
+#include "arm_uc_mmGetLatestTimestamp.h"
+#include "update-client-manifest-manager/update-client-manifest-manager-context.h"
+#if !MANIFEST_MANAGER_NO_STORAGE
+#include "cfstore-fsm.h"
+#endif
+
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_types.h"
+
+#define ARM_UC_MM_GET_LATEST_TS_STATE_LIST\
+    ENUM_FIXED(ARM_UC_MM_GET_LATEST_TS_STATE_INVALID,0)\
+    ENUM_AUTO(ARM_UC_MM_GET_LATEST_TS_STATE_BEGIN)\
+    ENUM_AUTO(ARM_UC_MM_GET_LATEST_TS_STATE_FIND)\
+    ENUM_AUTO(ARM_UC_MM_GET_LATEST_TS_STATE_READ)\
+    ENUM_AUTO(ARM_UC_MM_GET_LATEST_TS_STATE_FETCH_NAME)\
+
+enum arm_uc_mm_get_latest_ts_state {
+    #define ENUM_AUTO(name) name,
+    #define ENUM_FIXED(name, val) name = val,
+    ARM_UC_MM_GET_LATEST_TS_STATE_LIST
+    #undef ENUM_AUTO
+    #undef ENUM_FIXED
+};
+
+const char* ARM_UC_mmGetLatestTsState2Str(uint32_t state)
+{
+    switch (state) {
+        #define ENUM_AUTO(name) case name: return #name;
+        #define ENUM_FIXED(name, val) ENUM_AUTO(name)
+        ARM_UC_MM_GET_LATEST_TS_STATE_LIST
+        #undef ENUM_FIXED
+        #undef ENUM_AUTO
+    default:
+        return "Unknown State";
+    }
+}
+
+/**
+ * @brief Search the key/value store to find the latest timestamp.
+ * @detail Searches for all *.ts entries in the manifest manager key/value store prefix. As each entry is found,
+ * `getLatestManifestTimestampFSM()` updates ts with the largest timestamp encountered. If key is non-NULL, it is
+ * populated with the path to the largest timestamp.
+ *
+ * @param[out] ts Pointer to a 64-bit unsigned integer. Contains the largest timestamp encountered when
+ *                getLatestManifestTimestampFSM completes.
+ * @param[out] key Pointer to a buffer; the location to store the key that contained the largest timestamp.
+ * @retval MFST_ERR_NONE Always returns success.
+ */
+arm_uc_error_t getLatestManifestTimestamp(uint64_t *ts, arm_uc_buffer_t* key)
+{
+    *ts = 0;
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+
+/**
+ * @brief Run the getLatestManifestTimestampstate machine.
+ * @details Processes through the getLatestManifestTimestamp state machine in response to received events
+ *
+ * @param[in] event The event which has caused this run through the state machine
+ * @retval MFST_ERR_NONE    getLatestManifestTimestampFSM has completed
+ * @retval MFST_ERR_PENDING getLatestManifestTimestampFSM is still on-going and waiting for an event
+ * @return any other error code indicates an error has occurred
+ */
+arm_uc_error_t getLatestManifestTimestampFSM(uint32_t event)
+{
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmGetLatestTimestamp.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,28 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_MM_GET_LATEST_TIMESTAMP_H
+#define ARM_UC_MM_GET_LATEST_TIMESTAMP_H
+
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_types.h"
+
+arm_uc_error_t getLatestManifestTimestamp(uint64_t *ts, arm_uc_buffer_t* key);
+arm_uc_error_t getLatestManifestTimestampFSM(uint32_t event);
+
+#endif // ARM_UC_MM_GET_LATEST_TIMESTAMP_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmInit.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,424 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "arm_uc_mmInit.h"
+#include "arm_uc_mmCommon.h"
+#if !MANIFEST_MANAGER_NO_STORAGE
+#include "update-client-manifest-manager/update-client-manifest-manager-context.h"
+#include "arm_uc_mmGetLatestTimestamp.h"
+#include "arm_uc_mm_derparse.h"
+#include "cfstore-fsm.h"
+#include "crypto-fsm.h"
+#include "accessors.h"
+#include "update-client-common/arm_uc_types.h"
+#include "update-client-common/arm_uc_common.h"
+#include "update-client-common/arm_uc_error.h"
+#include "mbedtls/sha256.h"
+
+#include "arm_uc_mmFSMHelper.h"
+
+#ifndef min
+#define min(X,Y) ((X) < (Y) ? (X) : (Y))
+#endif
+
+const char* ARM_UC_mmInitState2Str(uint32_t state)
+{
+    switch (state) {
+        #define ENUM_AUTO(name) case name: return #name;
+        #define ENUM_FIXED(name, val) ENUM_AUTO(name)
+        ARM_UC_MM_INIT_STATE_LIST
+        #undef ENUM_FIXED
+        #undef ENUM_AUTO
+    default:
+        return "Unknown State";
+    }
+}
+
+
+
+arm_uc_error_t arm_uc_mmInitFSM(uint32_t event)
+{
+    if (arm_uc_mmPersistentContext.ctx == NULL || *arm_uc_mmPersistentContext.ctx == NULL)
+    {
+        return (arm_uc_error_t){MFST_ERR_NULL_PTR};
+    }
+    struct arm_uc_mmInitContext_t* ctx = &(*arm_uc_mmPersistentContext.ctx)->init;
+    arm_uc_error_t err = {MFST_ERR_PENDING};
+
+    ARM_UC_MM_FSM_HELPER_START(*ctx, ARM_UC_mmInitState2Str){
+    case ARM_UC_MM_INIT_BEGIN:
+        // Find the latest manifest.
+        ARM_UC_MM_SET_BUFFER(ctx->keyPath, ctx->pathBuffer);
+        err = getLatestManifestTimestamp(&ctx->timestamp, &ctx->keyPath);
+        ctx->state = ARM_UC_MM_INIT_LATEST_MFST;
+        // clear the missing dep flag
+        ctx->missingDep = 0;
+        // Set the root manifest flag
+        ctx->root = 1;
+
+        event = ARM_UC_MM_EVENT_BEGIN;
+        break;
+    case ARM_UC_MM_INIT_LATEST_MFST:
+    {
+        err = getLatestManifestTimestampFSM(event);
+        if (err.code != MFST_ERR_NONE)
+        {
+            break;
+        }
+        if (ctx->timestamp == 0)
+        {
+            err.code = MFST_ERR_NO_MANIFEST;
+            break;
+        }
+        // Copy out the root manifest's base path
+        strncpy((char*)ctx->rootManifestBasePath, (char*)ctx->keyPath.ptr, sizeof(ctx->rootManifestBasePath)-1);
+        ctx->rootManifestBasePath[sizeof(ctx->rootManifestBasePath)-1] = 0;
+        // Modify the key path.
+        char* pos = (char*)ctx->keyPath.ptr + strlen((char*)ctx->keyPath.ptr) - strlen("ts");
+        *pos = 'm';
+        *(pos + 1) = 0;
+        // Setup the manifest buffer
+        ARM_UC_MM_SET_BUFFER(ctx->manifest, ctx->manifestBuffer);
+        // Find the manifest
+        err = ARM_UC_mmCfStoreFindKey(&ctx->keyPath);
+        if (err.code != MFST_ERR_NONE)
+        {
+            break;
+        }
+        event = ARM_UC_MM_EVENT_CF_BEGIN;
+        ctx->state = ARM_UC_MM_INIT_FINDING;
+        // no break;
+    }
+    case ARM_UC_MM_INIT_FINDING:
+        if (event == UCMM_EVENT_CF_FIND_FAILED)
+        {
+            if (ctx->root)
+            {
+                //TODO: assert! This should not be possible!
+                err.code = MFST_ERR_INVALID_STATE;
+            } else {
+                // No more deps to find.
+                err.code = MFST_ERR_NONE;
+            }
+            break;
+        }
+        err = ARM_UC_mmCfStoreFindKeyFSM(event);
+        if (err.code != MFST_ERR_NONE)
+        {
+            break;
+        }
+        // Read the manifest
+        err = ARM_UC_mmCfStoreReadLastKey(&ctx->manifest);
+        if (err.code != MFST_ERR_NONE) {
+            break;
+        }
+        event = ARM_UC_MM_EVENT_CF_BEGIN;
+        ctx->state = ARM_UC_MM_INIT_READING;
+        // no break;
+    case ARM_UC_MM_INIT_READING:
+        // Read the manifest into a buffer
+        err = ARM_UC_mmCfStoreReadLastKeyFSM(event);
+        if (err.code != MFST_ERR_NONE)
+        {
+            break;
+        }
+        ctx->state = ARM_UC_MM_INIT_STATE_HASH_VERIFY;
+        // Preserve the manifest key
+        ARM_UC_mmCfStorePreserveLastKey();
+
+        // no break;
+    case ARM_UC_MM_INIT_STATE_HASH_VERIFY:
+        // Verify the manifest hash
+        err = ucmmValidateManifestHash(&ctx->manifest);
+        if (err.code == MFST_ERR_NONE) {
+            uint32_t val;
+            err = ARM_UC_mmGetCryptoMode(&ctx->manifest, &val);
+            if (err.code != MFST_ERR_NONE)
+            {
+                break;
+            }
+            ucmm_crypto_flags_t cryptoMode = ARM_UC_mmGetCryptoFlags(val);
+            if(cryptoMode.ecc || cryptoMode.rsa) {
+                ctx->state = ARM_UC_MM_INIT_STATE_PK_VERIFY;
+            } else {
+                ctx->state = ARM_UC_MM_INIT_STATE_ROOT_DEPS_VERIFY_BEGIN;
+            }
+        }
+        break;
+    case ARM_UC_MM_INIT_STATE_PK_VERIFY:
+        // Verify the manifest signature
+        err = ucmmValidateSignature(&ctx->manifest);
+        if (err.code == MFST_ERR_NONE)
+        {
+            ctx->state = ARM_UC_MM_INIT_STATE_PK_VERIFYING;
+        }
+        break;
+    case ARM_UC_MM_INIT_STATE_PK_VERIFYING:
+        err = ucmmValidateSignatureFSM(event);
+        if (err.code == MFST_ERR_NONE)
+        {
+            ctx->state = ARM_UC_MM_INIT_STATE_ROOT_DEPS_VERIFY_BEGIN;
+        }
+        break;
+    case ARM_UC_MM_INIT_STATE_ROOT_DEPS_VERIFY_BEGIN:
+    // ATTACKVECTOR: If an attacker can add a manifest to the dependency prefix in the config store, the manifest
+    // manager has no way to know that it is not valid, due to the flat file heirarchy.
+        ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_MANIFEST_BEGIN;
+        // NO BREAK;
+    case ARM_UC_MM_INIT_STATE_DEPS_LOOP_MANIFEST_BEGIN:
+        // Loop: manifest
+            // Set the depidx to 0
+        ctx->depidx = 0;
+        ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_GET_HASH;
+        // NO BREAK;
+    case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_GET_HASH:
+    {
+        arm_uc_buffer_t dependency;
+        arm_uc_buffer_t hash;
+        // Read the dependency at depidx
+        err = ARM_UC_mmGetManifestLinksElement(&ctx->manifest, ctx->depidx, &dependency);
+        // If there isn't one
+        if (err.code != MFST_ERR_NONE)
+        {
+            break;
+        }
+        if (dependency.ptr == NULL)
+        {
+            // Exit Loop: dependency
+            ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_END;
+            err.code = MFST_ERR_NONE;
+            break;
+        }
+        // Get the dependency hash
+        err = ARM_UC_mmGetManifestLinksHash(&dependency, &hash);
+        if (err.code != MFST_ERR_NONE)
+        {
+            break;
+        }
+        // Store the dependency hash
+        memcpy(ctx->currentHash, hash.ptr, min(hash.size, sizeof(ctx->currentHash)));
+        // Format the dependency search key
+        // The result of this operation is:
+        // com.arm.mbed.update.mm.m.<root manifest hash>.deps.<dependency hash>.m
+        // ASSUMES sizeof keypath > sizeof rootManifestBasePath
+        strncpy((char*)ctx->keyPath.ptr, (char*)ctx->rootManifestBasePath, sizeof(ctx->keyPath.ptr));
+        ctx->keyPath.size = strlen(ctx->keyPath.ptr);
+        // Back up one space to remove the 'm'
+        strncpy((char*)ctx->keyPath.ptr + ctx->keyPath.size-1, "deps.", ctx->keyPath.size_max - ctx->keyPath.size);
+        ctx->keyPath.size = strlen(ctx->keyPath.ptr);
+        ARM_UC_Base64Enc(ctx->keyPath.ptr + ctx->keyPath.size, ctx->keyPath.size_max - ctx->keyPath.size, &hash);
+        ctx->keyPath.size = strlen(ctx->keyPath.ptr);
+        strncpy((char*)ctx->keyPath.ptr + ctx->keyPath.size, ".m", ctx->keyPath.size_max - ctx->keyPath.size);
+        ctx->keyPath.size += 3; // add one for null terminator
+
+        // Find the dependency in the config store
+        err = ucmmCfstoreFindAndRead((char*)ctx->keyPath.ptr, &ctx->manifest);
+        if (err.code == MFST_ERR_NONE)
+        {
+            event = ARM_UC_MM_EVENT_BEGIN;
+            ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_READING_DEPENDENCY;
+        }
+        break;
+    }
+    case ARM_UC_MM_INIT_STATE_DEPS_LOOP_READING_DEPENDENCY:
+        // If there is no matching dependency
+        if (event == UCMM_EVENT_CF_FIND_FAILED)
+        {
+            // Set the missing dep flag
+            ctx->missingDep = 1;
+            ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_URI_CHECK;
+            // Continue...
+            err.code = MFST_ERR_NONE;
+            break;
+        }
+        // Find/Read the dependency manifest
+        err = ucmmCfstoreFindAndReadFSM(event);
+        if (err.code != MFST_ERR_NONE)
+        {
+            break;
+        }
+        // There is a matching dependency
+        ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_CHECK_HASH;
+        // No break;
+    case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_CHECK_HASH:
+    {
+#if MAX_HASH_BYTES != 256/8
+#error Hash size mismatch
+#endif
+        uint8_t localhash[MAX_HASH_BYTES];
+        arm_uc_buffer_t local = {
+            .size_max = MAX_HASH_BYTES,
+            .size     = 256/8,
+            .ptr      = localhash
+        };
+        arm_uc_buffer_t resource;
+        const int32_t valueID = ARM_UC_MM_DER_RESOURCE;
+        int rc = ARM_UC_mmDERGetSignedResourceValues(&resource, 1, &valueID, &resource);
+        if (rc)
+        {
+            err.code = MFST_ERR_DER_FORMAT;
+            break;
+        }
+        {
+            // Calculate the dependency hash
+            mbedtls_sha256_context ctx;
+            mbedtls_sha256_init(&ctx);
+            mbedtls_sha256_starts(&ctx, 0);
+            mbedtls_sha256_update(&ctx, resource.ptr, resource.size);
+            mbedtls_sha256_finish(&ctx, local.ptr);
+        }
+        {
+            arm_uc_buffer_t remote = {
+                .size_max = MAX_HASH_BYTES,
+                .size     = 256/8,
+                .ptr      = ctx->currentHash
+            };
+            // Validate the dependency hash
+            if(ARM_UC_BinCompareCT(&local, &remote))
+            {
+                // If invalid, Set the missing dep flag
+                ctx->missingDep = 1;
+                // Delete the manifest
+                ARM_UC_mmCfStoreDeleteLastKey();
+                ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_DELETE;
+                event = ARM_UC_MM_EVENT_CF_BEGIN;
+            }
+            else
+            {
+                // End Loop: dependency
+                ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_READ;
+                // Increment the depidx
+                ctx->depidx++;
+            }
+        }
+        break;
+    }
+    case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_DELETE:
+        err = ARM_UC_mmCfStoreDeleteLastKeyFSM(event);
+        if (err.code == MFST_ERR_NONE)
+        {
+            // Make sure a URI exists.
+            ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_URI_CHECK;
+        }
+        break;
+    case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_URI_CHECK:
+    {
+        // modify the search path
+        char* pos = (char*)ctx->keyPath.ptr + ctx->keyPath.size - 2; // null terminator
+        strncpy(pos, "uri", ctx->keyPath.size_max - (ctx->keyPath.size - 2)); // null terminator
+        // Check if there is a URI entry
+        // HACK: No API for find without ovewriting the existing stored key. Use find/read even though we don't need the
+        // data.
+        err = ucmmCfstoreFindAndRead((char*)ctx->keyPath.ptr, &ctx->manifest);
+        if (err.code != MFST_ERR_NONE)
+        {
+            break;
+        }
+        ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_URI_CHECKING;
+        event = ARM_UC_MM_EVENT_CF_BEGIN;
+        // no break
+    }
+    case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_URI_CHECKING:
+        if (event == UCMM_EVENT_CF_FIND_FAILED)
+        {
+            // TODO: Erase all deps and start over.
+            err.code = MFST_ERR_INVALID_STATE;
+            break;
+        }
+        err = ucmmCfstoreFindAndReadFSM(event);
+        if (err.code == MFST_ERR_NONE)
+        {
+            // Increment the depidx
+            ctx->depidx++;
+            // End Loop: dependency
+            ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_READ;
+        }
+        break;
+    case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_READ:
+            // Loop: dependency
+        // Restore the manifest key
+        ARM_UC_mmCfStoreRestoreLastKey();
+        // Seek the current key
+        err = ARM_UC_mmCfStoreSeekLastKey(0);
+        if (err.code == MFST_ERR_NONE)
+        {
+            ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_SEEKING;
+        }
+        break;
+    case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_SEEKING:
+        err = ARM_UC_mmCfStoreSeekLastKeyFSM(event);
+        if (err.code != MFST_ERR_NONE)
+        {
+            break;
+        }
+        // Read the current key
+        err = ARM_UC_mmCfStoreReadLastKey(&ctx->manifest);
+        if (err.code != MFST_ERR_NONE)
+        {
+            break;
+        }
+        ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_READING;
+        event = ARM_UC_MM_EVENT_CF_BEGIN;
+        // no break
+    case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_READING:
+        err = ARM_UC_mmCfStoreReadLastKeyFSM(event);
+        if (err.code == MFST_ERR_NONE)
+        {
+            ctx->state = ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_GET_HASH;
+            // Preserve the manifest key
+            ARM_UC_mmCfStorePreserveLastKey();
+        }
+        break;
+    case ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_END:
+        // Format the dependency search key
+        strncpy((char*)ctx->keyPath.ptr, (char*)ctx->rootManifestBasePath, sizeof(ctx->rootManifestBasePath));
+        ctx->keyPath.size = sizeof(ctx->rootManifestBasePath)-1;
+        strncpy((char*)ctx->keyPath.ptr + ctx->keyPath.size, ".deps.*", ctx->keyPath.size_max - ctx->keyPath.size);
+        ctx->keyPath.size += sizeof(".deps.*") - 1;
+        // If the root flag is set
+        if (ctx->root)
+        {
+            // Clear the root flag
+            ctx->root = 0;
+            // Start the dependency search
+            err = ARM_UC_mmCfStoreFindKey(&ctx->keyPath);
+        }
+        else
+        {
+            // Continue the dependency search
+            err = ARM_UC_mmCfStoreFindNextKey();
+        }
+        if (err.code == MFST_ERR_NONE)
+        {
+            event = ARM_UC_MM_EVENT_CF_BEGIN;
+            // End Loop: manifest
+            ctx->state = ARM_UC_MM_INIT_FINDING;
+        }
+        break;
+    default:
+        err.code = MFST_ERR_INVALID_STATE;
+        break;
+    } ARM_UC_MM_FSM_HELPER_FINISH(*ctx);
+    if (err.code == MFST_ERR_NONE && ctx->missingDep == 1)
+    {
+        // TODO: Configure & trigger insert FSM
+    }
+    return err;
+}
+
+#endif // !MANIFEST_MANAGER_NO_STORAGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmInit.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,59 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_MM_INIT_H
+#define ARM_UC_MM_INIT_H
+
+#include "update-client-manifest-manager/update-client-manifest-manager-context.h"
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_types.h"
+
+#define ARM_UC_MM_INIT_STATE_LIST\
+    ENUM_FIXED(ARM_UC_MM_INIT_UNINIT,0)\
+    ENUM_AUTO(ARM_UC_MM_INIT_BEGIN)\
+    ENUM_AUTO(ARM_UC_MM_INIT_LATEST_MFST)\
+    ENUM_AUTO(ARM_UC_MM_INIT_FINDING)\
+    ENUM_AUTO(ARM_UC_MM_INIT_READING)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_HASH_VERIFY)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_PK_VERIFY)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_PK_VERIFYING)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_ROOT_DEPS_VERIFY_BEGIN)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_DEPS_LOOP_MANIFEST_BEGIN)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_GET_HASH)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_DEPS_LOOP_READING_DEPENDENCY)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_CHECK_HASH)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_DELETE)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_URI_CHECK)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_URI_CHECKING)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_READ)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_SEEKING)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_READING)\
+    ENUM_AUTO(ARM_UC_MM_INIT_STATE_DEPS_LOOP_DEPENDENCY_END)\
+
+
+enum arm_uc_mm_init_state {
+    #define ENUM_AUTO(name) name,
+    #define ENUM_FIXED(name, val) name = val,
+    ARM_UC_MM_INIT_STATE_LIST
+    #undef ENUM_AUTO
+    #undef ENUM_FIXED
+};
+
+arm_uc_error_t arm_uc_mmInitFSM(uint32_t event);
+
+#endif // ARM_UC_MM_INIT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmInsertManifest.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,668 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "arm_uc_mmCryptoUtils.h"
+#include "arm_uc_mmCommon.h"
+#include "arm_uc_mmConfig.h"
+#include "arm_uc_mmStateSelector.h"
+#include "arm_uc_mmDerManifestAccessors.h"
+#include "arm_uc_mmDerManifestParser.h"
+#include "arm_uc_mmGetLatestTimestamp.h"
+#include "arm_uc_mmFSMHelper.h"
+#include "arm_uc_mmInsertManifest.h"
+#include "update-client-common/arm_uc_scheduler.h"
+
+#include "update-client-manifest-manager/update-client-manifest-manager-context.h"
+#include "update-client-manifest-manager/update-client-manifest-manager.h"
+#include "update-client-manifest-manager/update-client-manifest-types.h"
+
+#include "pal4life-device-identity/pal_device_identity.h"
+#include "pal.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+
+/**
+ * @file arm_uc_mmInsertManifest.c
+ * @brief Inserts a manifest into a slot specified by the manifest.
+ * @details This API is used by the manifest manager to validate and store a manifest.
+ *
+ * The workflow for inserting a manifest is:
+ * 1. Check the version of the manifest
+ * 2. Validate the cryptographic mode
+ * 3. Verify the hash of the manifest.
+ * 4. Verify each signature of the manifest.
+ * 5. Validate the applicability of the manifest (GUID matching)
+ * 6. Validate the storage identifier
+ * TBD: Store the manifest in the KCM
+ *
+ * NOTE: There is a security vs. energy tradeoff in this code.
+ * To optimize for energy, the cheapest fields should be checked first, that means checking applicability before
+ * hash or signature. However, to optimize for security, we must prioritize safety over energy. Since parsers are
+ * notorious sources of bugs, we must make every effort to protect the parser from insecure content. This means
+ * accessing the absolute minimum of fields prior to verifyinng the signature.
+ *
+ * The current version of this code optimizes for security. Once the parser has been more thoroughly validated, we can
+ * consider exposing it to more unvalidated data as an energy saving measure.
+ *
+ * @dot
+ * digraph {
+ *     Idle
+ *     Idle -> Begin [label="[event == BEGIN]"]
+ *     Begin
+ *     Begin -> VerifyBasicParameters
+ *     VerifyBasicParameters
+ *     // Validate the manifest size             (This is a precursor to security validation)
+ *     // Validate the manifest version          (This is required in order to know how to parse the manifest)
+ *     // Validate the manifest encryption mode  (This is required in order to know how to validate the signature)
+ *     VerifyBasicParameters -> VerifyHash
+ *     VerifyBasicParameters -> VerifyFail [label="[Basic Parameters invalid]"]
+ *     VerifyHash
+ *     VerifyHash -> VerifySignatureLoopStart
+ *     VerifyHash -> VerifyFail [label="[Hash invalid]"]
+ *     VerifySignatureLoopStart
+ *     VerifySignatureLoopStart -> VerifySignatureStart
+ *     VerifySignatureStart
+ *     VerifySignatureStart -> VerifySignature
+ *     VerifySignatureStart -> VerifyParameters [label="[No More Signatures]"]
+ *     VerifySignature
+ *     VerifySignature -> VerifyParameters [label="[Last Signature]"]
+ *     VerifySignature -> VerifyFail [label="[Signature invalid]"]
+ *     // Validate the applicability of the manifest (GUID matching)
+ *     // Validate the storage identifier
+ *     VerifyParameters
+ *     VerifyParameters -> VerifyTimestamp
+ *     VerifyParameters -> VerifyFail [label="[Parameters invalid]"]
+ *     VerifyTimestampStart
+ *     VerifyTimestampStart -> VerifyTimestamp
+ *     VerifyTimestamp
+ *     VerifyTimestamp -> VerifyApplication
+ *     VerifyTimestamp -> VerifyFail [label="[Timestamp too old]"]
+ *     VerifyApplication
+ *     VerifyApplication -> VerifyDone
+ *     VerifyApplication -> VerifyFail [label="[App denied]"]
+ *     VerifyFail
+ *     VerifyFail -> Idle
+ *     VerifyDone
+ *     VerifyDone -> AlertHub
+ *     AlertHub
+ *     AlertHub -> Idle
+ * }
+ * @enddot
+ */
+
+#if ARM_UC_MANIFEST_MANAGER_TRACE_ENABLE
+static const char* ARM_UC_mmInsertState2Str(uint32_t state)
+{
+    switch (state) {
+        #define ENUM_AUTO(name) case name: return #name;
+        #define ENUM_FIXED(name, val) ENUM_AUTO(name)
+        ARM_UC_MM_INS_STATE_LIST
+        #undef ENUM_AUTO
+        #undef ENUM_FIXED
+    default:
+        return "Unknown State";
+    }
+}
+#endif
+
+#define max(A,B) ((A)>(B)?(A):(B))
+
+/** @brief Validate that the resource contained in this signed container is a manifest.
+ */
+static arm_uc_error_t validateResourceType(arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    arm_uc_buffer_t type = { 0 };
+    // Read the resource type field.
+    err = ARM_UC_mmDERSignedResourceGetSingleValue(buffer,
+                                                   ARM_UC_MM_DER_RESOURCE_TYPE, &type);
+    if (type.ptr == NULL)
+    {
+        err.code = MFST_ERR_DER_FORMAT;
+    }
+    else if (err.error == ERR_NONE)
+    {
+        // The resource type must be a manifest.
+        if (ARM_UC_mmDerBuf2Uint(&type) != 0)
+        {
+            ARM_UC_MFST_SET_ERROR(err, MFST_ERR_DER_FORMAT);
+        }
+    }
+    return err;
+}
+/** @brief Validate that this manifest is a supported version
+ */
+static arm_uc_error_t validateManifestVersion(arm_uc_buffer_t* buffer)
+{
+    uint32_t val = 0;
+    // Read the manifest version
+    arm_uc_error_t err = ARM_UC_mmGetVersion(buffer, &val);
+    if (err.code == MFST_ERR_NONE)
+    {
+        // Verify the manifest version
+        if (val != MANIFEST_SUPPORTED_VERSION) {
+            ARM_UC_MFST_SET_ERROR(err, MFST_ERR_VERSION);
+        }
+    }
+    return err;
+}
+
+/** @brief Validate the manifest size
+ */
+static arm_uc_error_t validateManifestSize(arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    arm_uc_buffer_t val = {0};
+
+    // Get the manifest inner part
+    err = ARM_UC_mmDERSignedResourceGetSingleValue(buffer, ARM_UC_MM_DER_MFST, &val);
+    if (err.error == ERR_NONE)
+    {
+        // Make sure that the manifest does not overrun.
+        uintptr_t bufend = (uintptr_t)buffer->ptr + buffer->size;
+        uintptr_t valend = (uintptr_t)val.ptr + val.size;
+        if (bufend < valend)
+        {
+            ARM_UC_MFST_SET_ERROR(err, MFST_ERR_SIZE);
+        }
+        // TODO: There should be a minimum size for the manifest too.
+    }
+    return err;
+}
+
+/** @brief Validate the crypto mode
+ *  @details The manifest must contain a cryptographic mode identifier. Only a small number of modes are supported. If
+ *           the manifest is to be processed, then one of these modes must be supported.
+ *
+ *           While the manifest format supports OID cryptographic mode identifiers, these are not currently supported in
+ *           the update client.
+ */
+static arm_uc_error_t validateCryptoMode(arm_uc_buffer_t* buffer, arm_uc_mm_crypto_flags_t* flags)
+{
+    uint32_t cryptoMode = 1U; // default SHA256 and ECC
+    arm_uc_error_t err = ARM_UC_mmGetCryptoMode(buffer, &cryptoMode);
+    if (err.error == ERR_NONE)
+    {
+        if (cryptoMode <= MFST_CRYPT_UNINIT || MFST_CRYPT_MAX <= cryptoMode)
+        {
+            ARM_UC_MFST_SET_ERROR(err, MFST_ERR_CRYPTO_MODE);
+        }
+        else
+        {
+            *flags = ARM_UC_mmGetCryptoFlags(cryptoMode);
+        }
+    }
+    return err;
+}
+
+// Validate that the manifest applies to this device
+static arm_uc_error_t validateFirmwareApplicability(arm_uc_buffer_t* buffer)
+{
+    arm_uc_buffer_t vendor_guid = {0};
+    arm_uc_buffer_t class_guid  = {0};
+    arm_uc_buffer_t device_guid = {0};
+
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    if (err.code == MFST_ERR_NONE)
+        err = ARM_UC_mmGetVendorGuid(buffer, &vendor_guid);
+    if (err.code == MFST_ERR_NONE)
+        err = ARM_UC_mmGetClassGuid(buffer, &class_guid);
+    if (err.code == MFST_ERR_NONE)
+        err = ARM_UC_mmGetDeviceGuid(buffer, &device_guid);
+    if (err.code == MFST_ERR_NONE)
+        err = pal_deviceIdentityCheck(
+            (vendor_guid.size != 0UL ? &vendor_guid : NULL),
+            (class_guid.size != 0UL ? &class_guid : NULL),
+            (device_guid.size != 0UL ? &device_guid : NULL)
+        );
+    return err;
+}
+/*
+ * DOT Setup
+ * DOT: digraph {
+ */
+
+/* @brief Idle state
+ * @details The idle state generates no events and causes no state transitions. It only moves to a new state when the
+ *          `ARM_UC_MM_EVENT_BEGIN` event is received.
+ * DOT States:
+ * DOT:    Idle
+ * DOT:    Idle -> Begin [label="[event == BEGIN]"]
+ */
+static arm_uc_error_t state_idle(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    if (*event == ARM_UC_MM_EVENT_BEGIN)
+    {
+        ctx->state = ARM_UC_MM_INS_STATE_BEGIN;
+    }
+    return err;
+}
+/* @brief Begin state
+ * @details This is an empty placeholder state that is used as a state transition target for Idle. This allows
+ *          modifications to the FSM flow without modifying Idle.
+ * DOT States:
+ * DOT:    Begin
+ * DOT:    Begin -> VerifyBasicParameters
+ */
+static arm_uc_error_t state_begin(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    ctx->state = ARM_UC_MM_INS_STATE_VERIFY_BASIC_PARAMS;
+    return err;
+}
+/* @brief Verify critical pre-security parameters
+ * @details Some parameters must be verified before security validation. These parameters are critical to either finding
+ *          or validating the security parameters themselves. The parameters validated are:
+ *
+ * * The resource size             (This is a precursor to security validation)
+ * * The resource is a manifest    (A non-manifest will not be accepted)
+ * * The manifest version          (This is required in order to know how to parse the manifest)
+ * * The manifest encryption mode  (This is required in order to know how to validate the signature)
+ *
+ * DOT States:
+ * DOT:    VerifyBasicParameters
+ * DOT:    VerifyBasicParameters -> VerifyHash
+ * DOT:    VerifyBasicParameters -> VerifyFail [label="[Basic Parameters invalid]"]
+ */
+static arm_uc_error_t state_verifyBasicParameters(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+
+    if (err.error == ERR_NONE)
+    {
+        err = validateResourceType(&ctx->manifest);
+    }
+    if (err.error == ERR_NONE)
+    {
+        err = validateManifestSize(&ctx->manifest);
+    }
+    if (err.error == ERR_NONE)
+    {
+        err = validateManifestVersion(&ctx->manifest);
+    }
+    if (err.error == ERR_NONE)
+    {
+        err = validateCryptoMode(&ctx->manifest, &ctx->cryptoMode);
+    }
+    // Set the state based on error condition
+    if (err.error == ERR_NONE)
+    {
+        ctx->state = ARM_UC_MM_INS_STATE_HASH_VERIFY;
+    }
+    else
+    {
+        ctx->state = ARM_UC_MM_INS_STATE_VERIFY_FAIL;
+    }
+    return err;
+}
+/** @brief   Verify the manifest hash
+ *  @details Manifest hash verification happens in a single state. This is because hash verification is currently
+ *           considered to be a blocking operation. If an asynchronous hash accelerator is used, this will need to be
+ *           modified to use two states to handle hash initiation and waiting for completion.
+ *
+ * DOT States:
+ * DOT:     VerifyHash
+ * DOT:     VerifyHash -> VerifySignatureLoopStart
+ * DOT:     VerifyHash -> VerifyFail [label="[Hash invalid]"]
+ */
+static arm_uc_error_t state_verifyHash(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    arm_uc_error_t err = ARM_UC_mmValidateManifestHash(&ctx->manifest);
+    if (err.error == ERR_NONE)
+    {
+        // If the cryptoMode specifies either ecc or rsa, then we can validate that.
+        if(ctx->cryptoMode.ecc || ctx->cryptoMode.rsa)
+        {
+            ctx->state = ARM_UC_MM_INS_STATE_VERIFY_SIG_LOOP;
+        }
+        else
+        {
+            // Unsigned manifests are not supported at this time, so they count as a failure.
+            ARM_UC_MFST_SET_ERROR(err, MFST_ERR_INVALID_SIGNATURE);
+            ctx->state = ARM_UC_MM_INS_STATE_VERIFY_FAIL;
+        }
+    }
+    else
+    {
+        ARM_UC_MFST_SET_ERROR(err, MFST_ERR_HASH);
+        ctx->state = ARM_UC_MM_INS_STATE_VERIFY_FAIL;
+    }
+    return err;
+}
+/** @brief Start the signature verification loop.
+ *  @details This state provides initialization for the signature verification loop.
+ *           The outer loop is tracked by `loopCounters[0]` and represents the signature index.
+ *
+ * DOT States:
+ * DOT:     VerifySignatureLoopStart
+ * DOT:     VerifySignatureLoopStart -> VerifySignatureStart
+ */
+static arm_uc_error_t state_verifySignatureLoopStart(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    // Set the exterior loop counter
+    ctx->loopCounters[0] = 0;
+    ctx->state = ARM_UC_MM_INS_STATE_VERIFY_SIG_START;
+    return err;
+}
+/** @brief   Begin verifying the signature.
+ *  @details This calls the ARM_UC_mmValidateSignature setup function, but does not start the signature verification
+ *           state machine. `ARM_UC_mmValidateSignature` attempts to read a signature at the index specified by the
+ *           outer loop counter (`loopCounters[0]`). If it fails, it assumes that all signatures have been processed.
+ *           If at least one signature has been processed, then continue with validation, but a minimum of one signature
+ *           is required for validation.
+ *
+ * DOT States:
+ * DOT:     VerifySignatureStart
+ * DOT:     VerifySignatureStart -> VerifySignature
+ * DOT:     VerifySignatureStart -> VerifyParameters [label="[No More Signatures]"]
+ */
+static arm_uc_error_t state_verifySignatureStart(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    // start the signature verification
+    arm_uc_error_t err = ARM_UC_mmValidateSignature(&ctx->signatureContext,
+                                                    ARM_UC_mmCallbackFSMEntry,
+                                                    &ctx->manifest,
+                                                    &ctx->certificateStorage,
+                                                    ctx->loopCounters[0]);
+    if (err.error == ERR_NONE)
+    {
+        ctx->state = ARM_UC_MM_INS_STATE_VERIFY_SIG_WAIT;
+        *event = ARM_UC_MM_RC_NONE;
+        ARM_UC_MFST_SET_ERROR(err, MFST_ERR_PENDING);
+    }
+    // If there are no more signatures and at least one signature was validated
+    if (err.code == ARM_UC_DP_ERR_NO_MORE_ELEMENTS)
+    {
+        if (ctx->loopCounters[0] >= 1)
+        {
+            // Signature validation done. Move on to parameter validation.
+            ctx->state = ARM_UC_MM_INS_STATE_VERIFY_PARAMS;
+            ARM_UC_MFST_SET_ERROR(err, MFST_ERR_NONE);
+        }
+        else
+        {
+            // WARNING: If the fingerprint is empty, MFST_ERR_INVALID_SIGNATURE is returned.
+            // At least one signature is required.
+            ARM_UC_MFST_SET_ERROR(err, MFST_ERR_INVALID_SIGNATURE);
+            ctx->state = ARM_UC_MM_INS_STATE_VERIFY_FAIL;
+        }
+    }
+    return err;
+}
+/** @brief   Wait for signature validation to complete.
+ *  @details Calls the `ARM_UC_mmValidateSignature` state machine and collects exit status. When signature validation is
+ *           complete, the return value will be `MFST_ERR_NONE`.
+ *
+ * DOT States:
+ * DOT:     VerifySignature
+ * DOT:     VerifySignature -> VerifyFail [label="[Signature invalid]"]
+ * DOT:     VerifySignature -> VerifySignatureStart
+ */
+static arm_uc_error_t state_verifySignature(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    // Wait for the signature verification to end.
+    // If the signature validation ended
+    if (*event == ARM_UC_MM_RC_DONE)
+    {
+        // Increment the loop counter
+        ctx->loopCounters[0] += 1;
+        // Return to the beginning of the loop.
+        ctx->state = ARM_UC_MM_INS_STATE_VERIFY_SIG_START;
+    }
+    else if (*event == ARM_UC_MM_RC_ERROR)
+    {
+        err = ctx->signatureContext.storedError;
+    }
+    else
+    {
+        ARM_UC_MFST_SET_ERROR(err,  MFST_ERR_BAD_EVENT);
+    }
+    return err;
+}
+/** @brief   Validates remaining parsable parameters
+ *  @details This currently means only the firmware applicability, as identified by UUID. Several additiional parameters
+ *           could be validated:
+ *
+ *           * Storage identifier
+ *           * Payload type identifier
+ *           * URI validation in payload reference
+ *           * Valid size of payload hash
+ *           * nonce size, non-zero
+ *           * Valid From, Valid To
+ *           * timestamp
+ *           * Encryption info
+ *
+ *
+ * DOT States:
+ * DOT:     VerifyParameters
+ * DOT:     VerifyParameters -> VerifyApplication
+ * DOT:     VerifyParameters -> VerifyFail [label="[Parameters invalid]"]
+ */
+static arm_uc_error_t state_verifyParameters(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    arm_uc_error_t err = validateFirmwareApplicability(&ctx->manifest);
+    if (err.error == ERR_NONE)
+    {
+        ctx->state = ARM_UC_MM_INS_STATE_VERIFY_TS_START;
+    }
+    return err;
+}
+/** @brief   Initiate timestamp verification.
+ *  @details This starts the process of loading the active timestamp. This may be a non-blocking operation.
+ *
+ * DOT States:
+ * DOT:     VerifyTimestampStart
+ * DOT:     VerifyTimestampStart -> VerifyTimestamp
+ */
+static arm_uc_error_t state_verifyTimestampStart(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    // Since this is a root manifest, extract maximum stored timestamp
+    arm_uc_error_t err = getLatestManifestTimestamp(&ctx->max_ts, NULL);
+    if (err.error == ERR_NONE)
+    {
+        ctx->state = ARM_UC_MM_INS_STATE_VERIFY_TS;
+        *event = ARM_UC_MM_EVENT_BEGIN;
+    }
+    return err;
+}
+/** @brief   Waits for the active timestamp to be loaded.
+ *  @details Once the active timestamp has been loaded, this validates the inserted manifest timestamp.
+ *
+ * DOT States:
+ * DOT:    VerifyTimestamp
+ * DOT:    VerifyTimestamp -> VerifyApplication
+ * DOT:    VerifyTimestamp -> VerifyFail [label="[Timestamp too old]"]
+ */
+static arm_uc_error_t state_verifyTimestamp(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    arm_uc_error_t err = getLatestManifestTimestampFSM(*event);
+    if (err.error == ERR_NONE)
+    {
+        err = ARM_UC_mmGetTimestamp(&ctx->manifest, &ctx->current_ts);
+    }
+    if (err.error == ERR_NONE)
+    {
+#if MANIFEST_ROLLBACK_PROTECTION
+        // Validate the timestamp for rollback protection.
+        if (arm_uc_mmContext.max_ts >= arm_uc_mmContext.current_ts)
+        {
+            ARM_UC_MFST_SET_ERROR(err, MFST_ERR_ROLLBACK);
+        }
+        else
+#endif
+        {
+            ARM_UC_MFST_SET_ERROR(err, MFST_ERR_NONE);
+            ctx->state = ARM_UC_MM_INS_STATE_VERIFY_APP;
+        }
+    }
+    return err;
+}
+
+/** @brief   Calls out to a handler provided by the application.
+ *  @details Currently unimplemented.
+ *
+ * DOT States:
+ * DOT:     VerifyApplication
+ * DOT:     VerifyApplication -> VerifyDone
+ * DOT:     VerifyApplication -> VerifyFail [label="[App denied]"]
+ */
+static arm_uc_error_t state_verifyApplication(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    if (err.error == ERR_NONE)
+    {
+        ctx->state = ARM_UC_MM_INS_STATE_VERIFY_DONE;
+    }
+    return err;
+}
+/** @brief   Verification has failed.
+ *  @details This state will never be entered. This is for documentation purposes only. The state machine exits when an
+ *           error is detected, so this state cannot be entered. The hub will be notified via the state machine's error
+ *           handler.
+ *
+ * DOT States:
+ * DOT:     VerifyFail
+ * DOT:     VerifyFail -> Idle
+ */
+
+
+/** @brief   Verification has completed successfully.
+ *  @details This is a placeholder state that may be useful if more operations must be performed after verification,
+ *           for example, storage of the manifest.
+ *
+ * DOT States:
+ * DOT:     VerifyDone
+ * DOT:     VerifyDone -> AlertHub
+ */
+static arm_uc_error_t state_verifyDone(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    if (err.error == ERR_NONE)
+    {
+        ctx->state = ARM_UC_MM_INS_STATE_ALERT;
+    }
+    return err;
+}
+/** @brief   Alert the hub that insert has finished processing the manifest.
+ *  @details Queues a callback to the hub, that reports completion.
+ *
+ * DOT States:
+ * DOT:     AlertHub
+ * DOT:     AlertHub -> Idle
+ */
+static arm_uc_error_t state_alertHub(struct arm_uc_mmInsertContext_t* ctx, uint32_t* event)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    return err;
+}
+/**
+ * DOT Teardown
+ * DOT: }
+ */
+
+arm_uc_error_t ARM_UC_mmInsertFSM(uint32_t event)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    struct arm_uc_mmInsertContext_t* ctx;
+    if (arm_uc_mmPersistentContext.ctx == NULL || *arm_uc_mmPersistentContext.ctx == NULL)
+    {
+        return (arm_uc_error_t){MFST_ERR_NULL_PTR};
+    }
+    ctx = &(*arm_uc_mmPersistentContext.ctx)->insert;
+
+    uint32_t oldState;
+#if ARM_UC_MM_ENABLE_INSERT_TEST_VECTORS
+    uint32_t oldEvent;
+#endif
+    ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES, "> %s (%u)\n", __PRETTY_FUNCTION__, (unsigned)event);
+    do {
+        // Preserve the old state to check for state transitions
+        oldState = ctx->state;
+
+#if ARM_UC_MM_ENABLE_INSERT_TEST_VECTORS
+        // Preserve the old event for testing
+        oldEvent = event;
+#endif
+        // Reset error logging
+        arm_uc_mmPersistentContext.errorFile = NULL;
+        arm_uc_mmPersistentContext.errorLine = 0;
+
+        ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES, "+ %s state: %s(%u)\n", __PRETTY_FUNCTION__,
+            ARM_UC_mmInsertState2Str(ctx->state), (unsigned)ctx->state);\
+        switch (ctx->state)
+        {
+            case ARM_UC_MM_INS_STATE_IDLE:
+                err = state_idle(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_BEGIN:
+                err = state_begin(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_VERIFY_BASIC_PARAMS:
+                err = state_verifyBasicParameters(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_HASH_VERIFY:
+                err = state_verifyHash(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_VERIFY_SIG_LOOP:
+                err = state_verifySignatureLoopStart(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_VERIFY_SIG_START:
+                err =  state_verifySignatureStart(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_VERIFY_SIG_WAIT:
+                err = state_verifySignature(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_VERIFY_PARAMS:
+                err = state_verifyParameters(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_VERIFY_TS_START:
+                err = state_verifyTimestampStart(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_VERIFY_TS:
+                err = state_verifyTimestamp(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_VERIFY_APP:
+                err = state_verifyApplication(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_VERIFY_DONE:
+                err = state_verifyDone(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_ALERT:
+                err = state_alertHub(ctx, &event);
+                break;
+            case ARM_UC_MM_INS_STATE_INVALID:
+            default:
+                err = (arm_uc_error_t){MFST_ERR_INVALID_STATE};
+                break;
+        }
+#if ARM_UC_MM_ENABLE_INSERT_TEST_VECTORS
+        if (arm_uc_mmPersistentContext.testHook)
+        {
+            arm_uc_mmPersistentContext.testHook("insert", *arm_uc_mmPersistentContext.ctx, oldState, oldEvent, err);
+        }
+#endif
+    } while (err.code == MFST_ERR_NONE && oldState != ctx->state);
+    ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES, "< %s %c%c:%hu (%s)\n", __PRETTY_FUNCTION__, err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err));
+    return err;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmInsertManifest.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,28 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef MANIFEST_MANAGER_INSERT_MANIFEST_H
+#define MANIFEST_MANAGER_INSERT_MANIFEST_H
+
+
+#include "arm_uc_mmConfig.h"
+#include "update-client-common/arm_uc_common.h"
+
+arm_uc_error_t ARM_UC_mmInsertFSM(uint32_t event);
+
+#endif // MANIFEST_MANAGER_INSERT_MANIFEST_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmStateSelector.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,129 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "arm_uc_mmCryptoUtils.h"
+#include "arm_uc_mmCommon.h"
+#include "arm_uc_mmConfig.h"
+#include "arm_uc_mmStateSelector.h"
+#include "arm_uc_mmInit.h"
+#include "arm_uc_mmFSMHelper.h"
+#include "arm_uc_mmFetchFirmwareInfo.h"
+#include "arm_uc_mmInsertManifest.h"
+
+#include "update-client-manifest-manager/update-client-manifest-manager-context.h"
+#include "update-client-manifest-manager/update-client-manifest-manager.h"
+#include "update-client-manifest-manager/update-client-manifest-types.h"
+
+#include "update-client-common/arm_uc_scheduler.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+
+arm_uc_error_t ARM_UC_mmSetState(enum arm_uc_mmState_t newState)
+{
+    arm_uc_mmPersistentContext.state = newState;
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+
+#if 0
+static void printCryptoFlags(ucmm_crypto_flags_t *flags)
+{
+    printf("ucmm_crypto_flags_t @ %p = {\n", flags);
+    printf("    .hash = %u,\n",flags->hash);
+    printf("    .hmac = %u,\n",flags->hmac);
+    printf("    .rsa  = %u,\n",flags->rsa);
+    printf("    .ecc  = %u,\n",flags->ecc);
+    printf("    .aes  = %u,\n",flags->aes);
+    printf("}\n");
+}
+#endif
+
+arm_uc_error_t ARM_UC_mmFSM(uint32_t event)
+{
+    ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES, "> %s (%u)\n", __PRETTY_FUNCTION__, (unsigned)event);
+
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    enum arm_uc_mmState_t oldState;
+    do {
+        oldState = arm_uc_mmPersistentContext.state;
+        switch(arm_uc_mmPersistentContext.state)
+        {
+            case ARM_UC_MM_STATE_IDLE:
+                err = (arm_uc_error_t){MFST_ERR_NONE};
+                break;
+// Placeholder for init
+#if 0
+            case ARM_UC_MM_STATE_INIT:
+                err = arm_uc_mmInitFSM(event);
+                if (err.code == MFST_ERR_NONE)
+                {
+                    err = ARM_UC_mmSetState(ARM_UC_MM_STATE_IDLE);
+                    ARM_UC_PostCallback(&arm_uc_mmContext.cfstore_callback_storage, arm_uc_mmPersistentContext.applicationEventHandler, ARM_UC_MM_RC_DONE);
+                }
+                break;
+#endif
+            case ARM_UC_MM_STATE_INSERTING:
+                err = ARM_UC_mmInsertFSM(event);
+                if (err.code == MFST_ERR_NONE)
+                {
+                    err = ARM_UC_mmSetState(ARM_UC_MM_STATE_IDLE);
+                    ARM_UC_PostCallback(&arm_uc_mmPersistentContext.applicationCallbackStorage, arm_uc_mmPersistentContext.applicationEventHandler, ARM_UC_MM_RC_DONE);
+                }
+                break;
+            case ARM_UC_MM_STATE_FWINFO:
+                err = ARM_UC_mmFetchFirmwareInfoFSM(event);
+                if (err.code == MFST_ERR_NONE)
+                {
+                    err = ARM_UC_mmSetState(ARM_UC_MM_STATE_IDLE);
+                    ARM_UC_PostCallback(&arm_uc_mmPersistentContext.applicationCallbackStorage, arm_uc_mmPersistentContext.applicationEventHandler, ARM_UC_MM_RC_DONE);
+                }
+                break;
+            case ARM_UC_MM_STATE_TEST:
+                if (arm_uc_mmPersistentContext.testFSM != NULL) {
+                    err = arm_uc_mmPersistentContext.testFSM(event);
+                    if (err.code == MFST_ERR_NONE)
+                    {
+                        err = ARM_UC_mmSetState(ARM_UC_MM_STATE_IDLE);
+                        ARM_UC_PostCallback(&arm_uc_mmPersistentContext.applicationCallbackStorage, arm_uc_mmPersistentContext.applicationEventHandler, ARM_UC_MM_RC_DONE);
+                    }
+                    break;
+                }
+                // fall through
+            case ARM_UC_MM_STATE_INVALID:
+            default:
+                err = (arm_uc_error_t){MFST_ERR_INVALID_STATE};
+                break;
+        }
+    } while (err.code == MFST_ERR_NONE && oldState != arm_uc_mmPersistentContext.state);
+    ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES, "< %s %c%c:%hu (%s)\n", __PRETTY_FUNCTION__, err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err));
+    return err;
+}
+
+void ARM_UC_mmCallbackFSMEntry(uint32_t event)
+{
+    ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES,"> %s (%u)\n", __PRETTY_FUNCTION__, (unsigned)event);
+    arm_uc_error_t err = ARM_UC_mmFSM(event);
+    if (err.code != MFST_ERR_NONE && err.code != MFST_ERR_PENDING)
+    {
+        arm_uc_mmPersistentContext.reportedError = err;
+        arm_uc_mmPersistentContext.applicationEventHandler((uint32_t)ARM_UC_MM_RC_ERROR);
+    }
+    ARM_UC_MM_DEBUG_LOG(ARM_UC_MM_DEBUG_LOG_LEVEL_STATES,"< %s %c%c:%hu (%s)\n", __PRETTY_FUNCTION__, err.modulecc[0], err.modulecc[1], err.error, ARM_UC_err2Str(err));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/arm_uc_mmStateSelector.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,33 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef MANIFEST_MANAGER_CORE_FSM_H
+#define MANIFEST_MANAGER_CORE_FSM_H
+
+#include "update-client-common/arm_uc_scheduler.h"
+#include "arm_uc_mmConfig.h"
+
+#include "update-client-manifest-manager/update-client-manifest-manager-context.h"
+
+arm_uc_error_t ARM_UC_mmSetState(enum arm_uc_mmState_t newState);
+arm_uc_error_t ARM_UC_mmFSM(uint32_t event);
+void ARM_UC_mmCallbackFSMEntry(uint32_t event);
+
+
+
+#endif // MANIFEST_MANAGER_CORE_FSM_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/source/manifest-manager-api.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,157 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "arm_uc_mmCommon.h"
+#include "arm_uc_mmConfig.h"
+#include "arm_uc_mmStateSelector.h"
+#include "arm_uc_mmInit.h"
+
+#include "update-client-manifest-manager/update-client-manifest-manager.h"
+#include "update-client-manifest-manager/update-client-manifest-manager-context.h"
+#include "update-client-manifest-manager/update-client-manifest-types.h"
+#include "update-client-manifest-manager/arm-pal-kv.h"
+
+#include "update-client-common/arm_uc_scheduler.h"
+#include "update-client-common/arm_uc_utilities.h"
+#include "update-client-common/arm_uc_error.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+
+/**
+ * @file manifest_manager.c
+ * @brief Manifest Manager API
+ * @details This file specifies the API used to interact with the manifest manager
+ */
+
+arm_uc_error_t ARM_UC_mmInit(arm_uc_mmContext_t** mmCtx, void (*event_handler)(uint32_t), const arm_pal_key_value_api* api)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    if (mmCtx == NULL || *mmCtx == NULL)
+    {
+        return (arm_uc_error_t){MFST_ERR_NULL_PTR};
+    }
+
+    arm_uc_mmPersistentContext.ctx = mmCtx;
+    arm_uc_mmPersistentContext.applicationEventHandler = event_handler;
+    arm_uc_mmPersistentContext.testFSM = NULL;
+
+    // initialize callback node
+    arm_uc_mmPersistentContext.applicationCallbackStorage.lock = 0;
+
+    ARM_UC_PostCallback(&arm_uc_mmPersistentContext.applicationCallbackStorage, event_handler, ARM_UC_MM_RC_DONE);
+// This code will be re-enabled when storage is available
+#if 0
+    ARM_UC_mmCfStoreInit(api);
+
+    // Initialize the Init FSM
+    arm_uc_mmContext_t* ctx = *mmCtx;
+    ctx->init.state = ARM_UC_MM_INIT_BEGIN;
+
+    err = ARM_UC_mmSetState(ARM_UC_MM_STATE_INIT);
+    if (err.code != MFST_ERR_NONE)
+    {
+        return err;
+    }
+    // Start the Init FSM
+    ARM_UC_PostCallback(&ctx->init.callbackStorage, ARM_UC_mmCallbackFSMEntry, ARM_UC_MM_EVENT_BEGIN);
+#endif
+    return err;
+}
+
+arm_uc_error_t ARM_UC_mmInsert(arm_uc_mmContext_t** ctx, arm_uc_buffer_t* buffer, arm_uc_buffer_t* certificateStorage, arm_uc_manifest_handle_t* ID)
+{
+    if (ctx == NULL || *ctx == NULL || buffer == NULL )
+    {
+        return (arm_uc_error_t){MFST_ERR_NULL_PTR};
+    }
+    arm_uc_mmPersistentContext.ctx = ctx;
+    // Setup the state machine
+    arm_uc_error_t err = ARM_UC_mmSetState(ARM_UC_MM_STATE_INSERTING);
+    if (err.code != MFST_ERR_NONE)
+    {
+        return err;
+    }
+    struct arm_uc_mmInsertContext_t* insertCtx = &(*arm_uc_mmPersistentContext.ctx)->insert;
+    // Store the buffer pointer
+    ARM_UC_buffer_shallow_copy(&insertCtx->manifest, buffer);
+    insertCtx->state = ARM_UC_MM_INS_STATE_BEGIN;
+    // Store the ID pointer
+    insertCtx->ID = ID;
+    // Store the certificate buffer
+    ARM_UC_buffer_shallow_copy(&insertCtx->certificateStorage, certificateStorage);
+
+    // initialize callback node
+    insertCtx->callbackStorage.lock = 0;
+
+    // Start the FSM
+    ARM_UC_PostCallback(&insertCtx->callbackStorage, ARM_UC_mmCallbackFSMEntry, ARM_UC_MM_EVENT_BEGIN);
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmFetchFirmwareInfo(arm_uc_mmContext_t** ctx, struct manifest_firmware_info_t* info, const arm_uc_manifest_handle_t* ID)
+{
+    if (ctx == NULL || *ctx == NULL || info == NULL )
+    {
+        return (arm_uc_error_t){MFST_ERR_NULL_PTR};
+    }
+    arm_uc_mmPersistentContext.ctx = ctx;
+    // Initialize the state machine
+    arm_uc_error_t err = ARM_UC_mmSetState(ARM_UC_MM_STATE_FWINFO);
+    if (err.code != MFST_ERR_NONE)
+    {
+        return err;
+    }
+    struct arm_uc_mm_fw_context_t* fwCtx = &(*arm_uc_mmPersistentContext.ctx)->getFw;
+    fwCtx->state = ARM_UC_MM_FW_STATE_BEGIN;
+    fwCtx->info  = info;
+
+    // initialize callback node
+    fwCtx->callbackStorage.lock = 0;
+
+    // Start the state machine
+    ARM_UC_PostCallback(&fwCtx->callbackStorage, ARM_UC_mmCallbackFSMEntry, ARM_UC_MM_EVENT_BEGIN);
+
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmFetchNextFirmwareInfo(struct manifest_firmware_info_t* info)
+{
+    struct arm_uc_mm_fw_context_t* fwCtx = &(*arm_uc_mmPersistentContext.ctx)->getFw;
+    fwCtx->info = info;
+
+    // initialize callback node
+    fwCtx->callbackStorage.lock = 0;
+
+    // Continue the state machine
+    ARM_UC_PostCallback(&fwCtx->callbackStorage, ARM_UC_mmCallbackFSMEntry, ARM_UC_MM_EVENT_BEGIN);
+    return (arm_uc_error_t){MFST_ERR_NONE};
+}
+arm_uc_error_t ARM_UC_mmGetError()
+{
+    return arm_uc_mmPersistentContext.reportedError;
+}
+
+#if ARM_UC_MM_ENABLE_TEST_VECTORS
+arm_uc_error_t ARM_UC_mmRegisterTestHook(ARM_UC_mmTestHook_t hook)
+{
+    arm_uc_error_t err = {MFST_ERR_NONE};
+    arm_uc_mmPersistentContext.testHook = hook;
+    return err;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/update-client-manifest-manager/arm-pal-kv.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,82 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_PAL_KV_H
+#define ARM_PAL_KV_H
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define ARM_PAL_KV_KEY_MAX_PATH 220
+
+typedef struct arm_pal_key_value_api {
+    uint32_t (*keySize)();
+    void (*keyInit)(void* key);
+
+    int32_t (*Close)(void* hkey);
+    int32_t (*Create)(const char* key_name, size_t value_len, const void* kdesc, void* hkey);
+    int32_t (*Delete)(void* hkey);
+    int32_t (*Find)(const char* key_name_query, const void* previous, void* next);
+    int32_t (*Flush)(void);
+    int32_t (*GetKeyName)(void* hkey, char* key_name, uint8_t *key_len);
+    int32_t (*GetValueLen)(void* hkey, size_t *value_len);
+    int32_t (*Initialize)(
+        void(*callback)(int32_t status, int32_t cmd_code, void *client_context, void* handle),
+        void *client_context);
+    int32_t (*PowerControl)(uint32_t state);
+    int32_t (*Read)(void* hkey, void* data, size_t* len);
+    int32_t (*Open)(const char* key_name, uint32_t flags, void* hkey);
+    int32_t (*Rseek)(void* hkey, size_t offset);
+    int32_t (*Uninitialize)(void);
+    int32_t (*Write)(void* hkey, const char* data, size_t* len);
+} arm_pal_key_value_api;
+
+
+#define ARM_PAL_KV_OPENMODE_RD (1 << 3)
+
+uint32_t ARM_PAL_KV_keySize(const arm_pal_key_value_api* api);
+void ARM_PAL_KV_keyInit(const arm_pal_key_value_api* api, void* key);
+int32_t ARM_PAL_KV_Close(const arm_pal_key_value_api* api, void* hkey);
+int32_t ARM_PAL_KV_Create(const arm_pal_key_value_api* api, const char* key_name, size_t value_len, const void* kdesc, void* hkey);
+int32_t ARM_PAL_KV_Delete(const arm_pal_key_value_api* api, void* hkey);
+int32_t ARM_PAL_KV_Find(const arm_pal_key_value_api* api, const char* key_name_query, const void* previous, void* next);
+int32_t ARM_PAL_KV_Flush(const arm_pal_key_value_api* api);
+int32_t ARM_PAL_KV_GetKeyName(const arm_pal_key_value_api* api, void* hkey, char* key_name, uint8_t *key_len);
+int32_t ARM_PAL_KV_GetValueLen(const arm_pal_key_value_api* api, void* hkey, size_t *value_len);
+int32_t ARM_PAL_KV_Initialize(const arm_pal_key_value_api* api, void(*callback)(int32_t status, int32_t cmd_code, void *client_context, void* handle),void *client_context);
+int32_t ARM_PAL_KV_PowerControl(const arm_pal_key_value_api* api, uint32_t state);
+int32_t ARM_PAL_KV_Read(const arm_pal_key_value_api* api, void* hkey, void* data, size_t* len);
+int32_t ARM_PAL_KV_Open(const arm_pal_key_value_api* api, const char* key_name, uint32_t flags, void* hkey);
+int32_t ARM_PAL_KV_Rseek(const arm_pal_key_value_api* api, void* hkey, size_t offset);
+int32_t ARM_PAL_KV_Uninitialize(const arm_pal_key_value_api* api);
+int32_t ARM_PAL_KV_Write(const arm_pal_key_value_api* api, void* hkey, const char* data, size_t* len);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif // ARM_PAL_KV_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/update-client-manifest-manager/update-client-manifest-manager-context.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,235 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_MM_CONTEXT_TYPES_H
+#define ARM_UC_MM_CONTEXT_TYPES_H
+
+#include "update-client-manifest-manager/update-client-manifest-types.h"
+#include "update-client-manifest-manager/../source/arm_uc_mmConfig.h"
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_types.h"
+#include "update-client-common/arm_uc_scheduler.h"
+#include "update-client-manifest-manager/arm-pal-kv.h"
+
+
+struct arm_uc_mmInitContext_t {
+    uint64_t timestamp;
+    uint32_t state;
+    arm_uc_buffer_t manifest;
+    arm_uc_buffer_t keyPath;
+    uint32_t loopCounters[1];
+
+    arm_uc_callback_t callbackStorage; // initialized in hub
+    struct {
+        unsigned root:1;
+        unsigned depidx:3;
+        unsigned missingDep:1;
+    };
+    uint8_t rootManifestBasePath[sizeof(MANIFEST_PREFIX ".." ) + CFSTORE_HASH_ID_SIZE];
+    uint8_t pathBuffer[220];
+    uint8_t manifestBuffer[640];
+    uint8_t currentHash [MAX_HASH_BYTES];
+
+};
+
+struct arm_uc_mm_get_latest_ts_context {
+    uint64_t current_ts;
+    uint64_t* max_ts;
+    uint32_t state;
+    arm_uc_buffer_t current_data;
+    arm_uc_buffer_t max_ts_key;
+};
+
+enum arm_uc_mm_pk_sig_state {
+    UCMM_PKSIG_STATE_INVALID = 0,
+    UCMM_PKSIG_STATE_FIND_CA,
+    UCMM_PKSIG_STATE_FINDING_CA,
+    UCMM_PKSIG_STATE_CHECK,
+    UCMM_PKSIG_STATE_IDLE,
+};
+
+typedef struct arm_uc_mm_validate_signature_context{
+    enum arm_uc_mm_pk_sig_state  state;
+                         void (* applicationEventHandler)(uint32_t);
+                arm_uc_buffer_t  fingerprint;
+                arm_uc_buffer_t  certList;
+                arm_uc_buffer_t  cert;
+                arm_uc_buffer_t* manifest;
+                arm_uc_error_t   storedError;
+                uint32_t         sigIndex;
+} arm_uc_mm_validate_signature_context_t;
+
+#define ARM_UC_MM_FW_STATE_LIST\
+    ENUM_FIXED(ARM_UC_MM_FW_STATE_INVALID,0)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_IDLE)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_BEGIN)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_FIND_ROOT)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_FETCH_TS)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_FETCH_NAME)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_FIND_NEXT_ROOT)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_FORMAT_ROOT_PREFIX)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_FIND_MANIFEST)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_READ_MANIFEST)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_FETCH_ROOT)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_FIND_URI)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_READ_URI)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_FETCH_URI_KEY)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_FETCH_HASH)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_FETCH_DEP_URI)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_FETCH_DEP_HASH)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_GET_FW_REF)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_NOTIFY)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_ROOT_NOTIFY_WAIT)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_NEXT_IMAGE)\
+    ENUM_AUTO(ARM_UC_MM_FW_STATE_DONE)\
+
+
+enum arm_uc_mm_fw_state {
+    #define ENUM_AUTO(name) name,
+    #define ENUM_FIXED(name, val) name = val,
+    ARM_UC_MM_FW_STATE_LIST
+    #undef ENUM_AUTO
+    #undef ENUM_FIXED
+};
+
+struct arm_uc_mm_fw_context_t {
+    struct arm_uc_mm_get_latest_ts_context getLatestTs;
+                                  uint64_t ts;
+                 arm_uc_manifest_handle_t* ID;
+                   enum arm_uc_mm_fw_state state;
+          struct manifest_firmware_info_t* info;
+                         arm_uc_callback_t callbackStorage; // initialized in hub
+                           arm_uc_buffer_t current_data;
+                                      char hashIDbuffer[CFSTORE_HASH_ID_SIZE];
+                                   uint8_t keyBuffer[ARM_PAL_KV_KEY_MAX_PATH];
+};
+
+#define ARM_UC_MM_INS_STATE_LIST\
+    ENUM_FIXED(ARM_UC_MM_INS_STATE_INVALID,0)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_IDLE)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_BEGIN)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_VERIFY_BASIC_PARAMS)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_HASH_VERIFY)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_VERIFY_SIG_LOOP)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_VERIFY_SIG_START)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_VERIFY_SIG_WAIT)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_VERIFY_PARAMS)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_VERIFY_APP)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_VERIFY_FAIL)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_VERIFY_DONE)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_STORE_BEGIN)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_MATCHING)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_MATCH_FETCHING)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_STORE_MANIFEST_BEGIN)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_STORE_MANIFEST)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_STORE_FW_URI)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_STORE_FW_HASH)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_STORE_AES)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_STORE_DEPS)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_DEPSTART)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_DEP_WAITING)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_COMPLETION)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_COMPLETION_FINDING)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_VERIFY_TS_START)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_VERIFY_TS)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_STORE_TS_START)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_STORE_TS)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_DEP_CHECK)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_DEP_CHECKING)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_DEP_DELETE)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_DONE)\
+    ENUM_AUTO(ARM_UC_MM_INS_STATE_ALERT)\
+
+
+enum arm_uc_mm_insert_state {
+    #define ENUM_AUTO(name) name,
+    #define ENUM_FIXED(name, val) name = val,
+    ARM_UC_MM_INS_STATE_LIST
+    #undef ENUM_AUTO
+    #undef ENUM_FIXED
+};
+
+struct arm_uc_mmInsertContext_t {
+    struct arm_uc_mm_get_latest_ts_context getLatestTs;
+    arm_uc_mm_validate_signature_context_t signatureContext;
+                                  uint64_t max_ts;
+                                  uint64_t current_ts;
+                 arm_uc_manifest_handle_t* ID;
+               enum arm_uc_mm_insert_state state;
+                         arm_uc_callback_t callbackStorage; // initialized in hub
+                           arm_uc_buffer_t manifest;
+                  arm_uc_mm_crypto_flags_t cryptoMode;
+                           arm_uc_buffer_t certificateStorage;
+                                  uint32_t loopCounters[1];
+};
+
+struct arm_uc_mmContext_t {
+    // Operational Contexts
+    union {
+        struct arm_uc_mmInitContext_t   init;
+        struct arm_uc_mm_fw_context_t   getFw;
+        struct arm_uc_mmInsertContext_t insert;
+    };
+};
+typedef struct arm_uc_mmContext_t arm_uc_mmContext_t;
+
+
+enum arm_uc_mmState_t {
+    ARM_UC_MM_STATE_INVALID=0,
+    ARM_UC_MM_STATE_IDLE,
+    ARM_UC_MM_STATE_INIT,
+    ARM_UC_MM_STATE_INSERTING,
+    ARM_UC_MM_STATE_STORING_CA,
+    ARM_UC_MM_STATE_FWINFO,
+    ARM_UC_MM_STATE_TEST,
+};
+
+typedef void (*ARM_UC_mmTestHook_t)(const char*, arm_uc_mmContext_t*, uint32_t, uint32_t, arm_uc_error_t);
+
+struct arm_uc_mmPersistentContext_t {
+          enum arm_uc_mmState_t state;
+                 arm_uc_error_t reportedError;
+                    const char* errorFile;
+                       uint32_t errorLine;
+    struct arm_uc_mmContext_t** ctx;
+              arm_uc_callback_t applicationCallbackStorage; // initialized in mmCommon
+                           void (*applicationEventHandler)(uint32_t);
+                 arm_uc_error_t (*testFSM)(uint32_t event);
+#if ARM_UC_MM_ENABLE_TEST_VECTORS
+            ARM_UC_mmTestHook_t testHook;
+#endif
+};
+
+typedef struct arm_uc_mmPersistentContext_t arm_uc_mmPersistentContext_t;
+extern arm_uc_mmPersistentContext_t arm_uc_mmPersistentContext;
+
+static inline arm_uc_mmContext_t* arm_uc_mmBuf2Context(arm_uc_buffer_t* b) {
+    return (arm_uc_mmContext_t*)b->ptr;
+}
+
+static inline arm_uc_error_t arm_uc_mmContextBufSizeCheck(arm_uc_buffer_t* b) {
+    arm_uc_error_t err = { .code = MFST_ERR_NONE };
+    if (b->size_max < sizeof(arm_uc_mmContext_t)) {
+        err.code = MFST_ERR_SIZE;
+        return err;
+    }
+    return err;
+}
+
+
+#endif // ARM_UC_MM_CONTEXT_TYPES_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/update-client-manifest-manager/update-client-manifest-manager.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,199 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+/**
+ * @file draft-api.h
+ * @brief Manifest Manager API
+ * @details This file specifies the API used to interact with the manifest manager
+ * # Expected API call pattern
+ * The update hub should call the API in the following way:
+ * - The update hub initializes the manifest manager: `manifest_manager_init()`
+ *     - TODO: The manifest manager checks internal consistency of the latest manifest.
+ * - The udpate hub passes a manifest to the manifest manager: `manifest_manager_insert()`
+ * - The manifest manager:
+ *     - checks for validity of the manifest and exits with a failure if it is invalid.
+ *         - validates the integrity of the manifest (hash)
+ *         - validates the authenticity of the manifest (signature)
+ *         - checks that the manifest applies to the local hardware
+ *             - reports the Device, Vendor, and Device Class GUIDs to the update hub for validation.
+ *     - searches for a matching dependency placeholder
+ *     - if a match is found,
+ *         - stores the manifest as a dependency
+ *     - otherwise
+ *        - TODO: Validates the timestamp.
+ *          NOTE: Timestamp cannot be validated before this point since it is only validated on root manifests
+ *        - stores the maninfest as a new root manifest
+ *     - stores the firmware URI and hash (HACK: Also embeds the firmware size, inip vector and AES key in the hash)
+ *     - stores a placeholder for each linked manifest
+ *     - stores the manifest timestamp
+ *     - The manifest manager searches for dependency placeholders
+ *         - If there is a placeholder, report it to the hub and exit pending.
+ *         - otherwise, report DONE to the hub.
+ * - If the update hub receives a manifest request,
+ *     - It obtains that manifest and calls `manifest_manager_insert()` starting this process again.
+ * - If the update hub receives a DONE report,
+ *     - It initiates a firmware request, using the `ARM_UC_mmFetchFirmwareInfo()` API
+ *     - The manifest manager:
+ *         - finds the most recent root manifest
+ *         - searches for any firmware placeholders
+ *         - reports the firmware to the hub
+ * - Until the hub receives a DONE report, it
+ *     - extracts the firmware information using `ARM_UC_mmGetFirmwareInfo()`
+ *     - fetches the firmware image
+ *     - installs the firmware image
+ *     - starts the search for the next firmware, using `ARM_UC_mmFetchNextFirmwareInfo()`
+ */
+#include "update-client-manifest-manager-context.h"
+#include "update-client-manifest-manager/update-client-manifest-types.h"
+#include "update-client-manifest-manager/arm-pal-kv.h"
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const size_t arm_uc_mmDynamicContextSize;
+/**
+ * @brief Result codes for the application event handler
+ * @details These result codes are passed to the event handler. They are used to indicate action required by the calling
+ * application and status of the manifest manager.
+ */
+enum arm_uc_mmResultCode {
+    ARM_UC_MM_RC_ERROR = 0, /**< status: The manifest manager failed during the previous operation. Extract further
+                             *           error information using `ARM_UC_mmGetError()` */
+    ARM_UC_MM_RC_NONE,      ///< action: No action necessary
+    ARM_UC_MM_RC_NEED_DEP,  /**< action: The firmware manager needs the manifest specified by
+                             *           `ARM_UC_mmGetCurrentManifestDependency()` in order to keep processing the
+                             *           firmware update */
+    ARM_UC_MM_RC_NEED_FW,   /**< action: The firmware manager needs the firmware specified by
+                             *           `ARM_UC_mmGetFirmwareInfo()` in order to keep processing the firmware update */
+    ARM_UC_MM_RC_DONE       ///< status: The last operation completed successfully
+};
+
+
+/**
+ * @brief Initialize module and register event handler.
+ * @details The event handler is shared among all asynchronous calls.
+ *
+ * Walks the most recent manifest tree for validity of the tree and presence of the associated images
+ *
+ * @param[in] ctxbuf Context object for the manifest manager
+ * @param  callback Function pointer to event handler.
+ * @param  api Pointer to API structure for the key/value storage
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_mmInit(arm_uc_mmContext_t** ctxbuf, void (*event_handler)(uint32_t), const arm_pal_key_value_api* api);
+
+/**
+ * @brief Insert manifest.
+ * @details Validates and parses manifest.
+ *          Event is generated when call is complete.
+ *
+ * @param[in]  buffer Struct containing pointer to byte array, maximum length,
+ *               and actual length.
+ * @param[out] ID Pointer to a manifest handle. This handle will be populated on success.
+ * @return Error code, indicating parsing errors, validity of the manifest, etc. Error codes are TBD.
+ */
+arm_uc_error_t ARM_UC_mmInsert(arm_uc_mmContext_t** ctx, arm_uc_buffer_t* buffer, arm_uc_buffer_t* certificateStorage, arm_uc_manifest_handle_t* ID);
+
+/**
+ * @brief Get manifest firmware information
+ * @details Fills the manifest_firmware_info_t struct with URL information.
+ *
+ * struct manifest_firmware {
+ *     uint32_t        size;       ///< The size of the firmware in bytes
+ *     arm_uc_buffer_t hash;       ///< The hash of the firmware image
+ *     arm_uc_buffer_t uri;        ///< The location of the firmware
+ *     arm_uc_buffer_t initVector; ///< AES initialization vector
+ *     arm_uc_buffer_t keyID;      ///< Identifier for a locally stored AES key
+ *     arm_uc_buffer_t key;        ///< An encrypted AES key
+ *     manifest_guid_t format;     ///< The format used for the firmware. This is either an enum when the first 96 bits
+ *                                 ///  are 0. Otherwise, this is a RFC4122 GUID. * /
+ *     arm_uc_buffer_t  version;   ///< A text representation of the version number.
+ * };
+ *
+ *
+ * @param[in]  ID   Value identifying the manifest.
+ * @param[out] info Struct containing the URL.
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_mmFetchFirmwareInfo(arm_uc_mmContext_t** ctx, struct manifest_firmware_info_t* info, const arm_uc_manifest_handle_t* ID);
+
+/**
+ * @brief Starts extracting firmware information from a tree of manifests
+ * @details `ARM_UC_mmFetchFirmwareInfo()` begins the process of extracting firmware information in the config store
+ * This API should only be called once for a root manifest. It always completes asynchronously on success: a return of
+ *`MFST_ERR_NONE` will be followed by a callback with `ARM_UC_MM_RC_DONE`. Errors may be returned synchronously or
+ * asynchronously.
+ *
+ * The caller should wait for a callback via the function pointer provided in `manifest_manager_init()`. If the event
+ * provided to the callback is `ARM_UC_MM_RC_NEED_FW`, then a new firmware info block is ready for access via
+ * `ARM_UC_mmGetFirmwareInfo()`. If the event is `ARM_UC_MM_RC_DONE` then no more firmware info blocks are provided via
+ * this root manifest.
+ *
+ * @param[in]  ID a handle for the manifest to search. TODO: The manifest manager currently just selects the latest root
+ *                manifest.
+ * @return     An error code on failure, MFST_ERR_NONE on success, or MFST_ERR_PENDING if the find has not completed.
+ */
+// arm_uc_error_t ARM_UC_mmFetchFirmwareInfo(arm_uc_manifest_handle_t* ID);
+
+/**
+ * @brief Continues extracting firmware information from a tree of manifests
+ * @details `ARM_UC_mmFetchNextFirmwareInfo()` obtains the next firmware information block in a tree of manifests. It
+ * always completes asynchronously on success: a return of `MFST_ERR_NONE` will be followed by a callback with
+ * `ARM_UC_MM_RC_DONE`.
+ *
+ * The caller should wait for a callback via the function pointer provided in `manifest_manager_init()`. If the event
+ * provided to the callback is `ARM_UC_MM_RC_NEED_FW`, then a new firmware info block is ready for access via
+ * `ARM_UC_mmGetFirmwareInfo()`. If the event is `ARM_UC_MM_RC_DONE` then no more firmware info blocks are provided via
+ * this root manifest.
+ *
+ * @return     An error code on failure, MFST_ERR_NONE on success, or MFST_ERR_PENDING if the find has not completed.
+ */
+arm_uc_error_t ARM_UC_mmFetchNextFirmwareInfo(struct manifest_firmware_info_t* info);
+
+/**
+ * @brief Extract the last error reported to a callback with `ARM_UC_MM_RC_ERROR`
+ * @details Retrieves the internal error code stored in the manifest manager. When an error occurs in the manifest
+ * manager, during an asynchronous operation, it is not possible to pass this information directly to the application,
+ * so it is stored internally for later retrieval and an error event is queued for handling by the application event
+ * handler.
+ *
+ * @return The stored error code.
+ */
+arm_uc_error_t ARM_UC_mmGetError(void);
+
+/**
+ * @brief Extracts the current dependency manifest information
+ * @details When the manifest manager reports `ARM_UC_MM_RC_NEED_DEP` to the application event handler, it stores the
+ * manifest dependency that induced that request. When the application event handler processes the request, it can
+ * extract the manifest URI from the manifest manager using this function.
+ *
+ * @param[out] uri The buffer where the manifest URI should be stored.
+ * @return     An error code on failure or MFST_ERR_NONE on success.
+ */
+arm_uc_error_t ARM_UC_mmGetCurrentManifestDependency(arm_uc_buffer_t* uri);
+
+#if ARM_UC_MM_ENABLE_TEST_VECTORS
+arm_uc_error_t ARM_UC_mmRegisterTestHook(ARM_UC_mmTestHook_t hook);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/manifest-manager/update-client-manifest-manager/update-client-manifest-types.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,133 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef UPDATE_CLIENT_MANIFEST_MANAGER_TYPES_H
+#define UPDATE_CLIENT_MANIFEST_MANAGER_TYPES_H
+
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_common.h"
+
+#include <limits.h>
+#include <stdint.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define RFC_4122_BYTES (128/CHAR_BIT)
+#define RFC_4122_WORDS (RFC_4122_BYTES/sizeof(uint32_t))
+#define ARM_UC_MANIFEST_HANDLE_BUFFER_BYTES (256/CHAR_BIT)
+
+// NOTE: Manifest Handles are not used yet
+typedef uint8_t arm_uc_manifest_handle_t[ARM_UC_MANIFEST_HANDLE_BUFFER_BYTES];
+
+
+/**
+ * @brief RFC 4122 GUID container
+ * GUIDs are a fixed size, so this container provides a consistent storage for them. Accessors are provided for both
+ * byte-wise and word-wise access.
+ */
+typedef struct manifest_guid_t {
+    union {
+        uint8_t  bytes[RFC_4122_BYTES];
+        uint32_t words[RFC_4122_WORDS];
+    };
+} manifest_guid_t;
+
+/**
+ * @brief Allowed cryptographic modes
+ * This list must be kept in sync with the manifest generator.
+ * Only a minimum set of cryptographic modes should be permitted
+ */
+enum manifest_crypto_mode {
+    MFST_CRYPT_UNINIT = 0,             //!< Uninitialized mode. This mode will always fail
+    MFST_CRYPT_SHA256_ECC_AES128_PSK,  /*!< Manifest is signed with ECDSA. Firmware is encrypted with AES128-CTR, using a
+                                        *   pre-shared key. Firmware plaintext is hashed with SHA256. */
+    MFST_CRYPT_SHA256_ECC,             //!< Manifest is signed with ECDSA. Firmware is hashed with SHA256
+    MFST_CRYPT_SHA256,                 //!< Manifest and firmware are hashed with SHA256. Not recommended for production
+    // MFST_CRYPT_SHA256_HMAC,            //!< Manifest is signed with HMAC. Firmware is hashed with SHA256
+    // MFST_CRYPT_SHA256_HMAC_AES128_PSK, /*!< Manifest is signed with HMAC. Firmware is encrypted with AES128-CTR, using a
+    //                                     *   pre-shared key. Firmware plaintext is hashed with SHA256. */
+    MFST_CRYPT_MAX,
+};
+
+/**
+ * @brief Helper structure
+ * This structure converts the cryptomode to testable flags
+ */
+typedef struct arm_uc_mm_crypto_flags_t {
+    unsigned hash:2;
+    unsigned hmac:1;
+    unsigned rsa:2;
+    unsigned ecc:2;
+    unsigned aes:2;
+    unsigned psk:1;
+} arm_uc_mm_crypto_flags_t;
+
+enum arm_uc_mmCipherMode_t {
+    ARM_UC_MM_CIPHERMODE_NONE,
+    ARM_UC_MM_CIPHERMODE_PSK,
+    ARM_UC_MM_CIPHERMODE_CERT_CIPHERKEY,
+    ARM_UC_MM_CIPHERMODE_CERT_KEYTABLE,
+};
+
+/**
+ * @brief   Firmware Information
+ * @details Contains the details about the firmware image referenced by the manifest
+ */
+struct manifest_firmware_info_t {
+    uint64_t        timestamp;  ///< Root Manifest timestamp.
+    manifest_guid_t format;     /**< The format used for the firmware. This is either an enum when the first 96 bits
+                                 *   are 0. Otherwise, this is a RFC4122 GUID. */
+
+    uint32_t            cryptoMode;
+    uint32_t            size;       ///< The size of the firmware in bytes
+    arm_uc_buffer_t     hash;       ///< The hash of the firmware image
+    arm_uc_buffer_t     uri;        ///< The location of the firmware
+    arm_uc_buffer_t     strgId;     ///< The location of the firmware
+
+    uint32_t            cipherMode;
+    arm_uc_buffer_t     initVector; ///< AES initialization vector. 0 is not permitted.
+    union {
+        struct {
+            arm_uc_buffer_t keyID;      ///< Identifier for a locally stored AES key
+            arm_uc_buffer_t cipherKey;        ///< An encrypted AES key
+        } psk;
+        struct {
+            arm_uc_buffer_t certFingerPrint;
+            arm_uc_buffer_t certURL;
+            arm_uc_buffer_t cipherKey;
+        } certCK;
+        struct {
+            arm_uc_buffer_t certFingerPrint;
+            arm_uc_buffer_t certURL;
+            arm_uc_buffer_t keyTableURL;
+        } certKT;
+    };
+    uint32_t manifestSize;
+    uint8_t  manifestBuffer[640];
+};
+typedef struct manifest_firmware_info_t manifest_firmware_info_t;
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif // UPDATE_CLIENT_MANIFEST_MANAGER_TYPES_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/monitor/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,166 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/monitor/update-client-monitor/arm_uc_monitor.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,203 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __ARM_UPDATE_MONITOR_H__
+#define __ARM_UPDATE_MONITOR_H__
+
+#include "update-client-common/arm_uc_common.h"
+
+#include <stdint.h>
+
+/**
+ * @brief Struct containing the Monitor's capabilities.
+ * @details state: Monitor can report the device's state.
+ *          result: Monitor can report the update result.
+ *          version: Monitor can report the current version.
+ */
+typedef struct _ARM_MONITOR_CAPABILITIES {
+    uint32_t state: 1;
+    uint32_t result: 1;
+    uint32_t version: 1;
+    uint32_t reserved: 30;
+} ARM_MONITOR_CAPABILITIES;
+
+/**
+ *
+ */
+typedef enum {
+    ARM_UC_MONITOR_STATE_FIRST       = 0,
+    ARM_UC_MONITOR_STATE_IDLE        = ARM_UC_MONITOR_STATE_FIRST,
+    ARM_UC_MONITOR_STATE_DOWNLOADING = 1,
+    ARM_UC_MONITOR_STATE_DOWNLOADED  = 2,
+    ARM_UC_MONITOR_STATE_UPDATING    = 3,
+    ARM_UC_MONITOR_STATE_LAST        = ARM_UC_MONITOR_STATE_UPDATING
+} arm_uc_monitor_state_t;
+
+typedef enum {
+    ARM_UC_MONITOR_RESULT_FIRST            = 0,
+    ARM_UC_MONITOR_RESULT_INITIAL          = ARM_UC_MONITOR_RESULT_FIRST,
+    ARM_UC_MONITOR_RESULT_SUCCESS          = 1,
+    ARM_UC_MONITOR_RESULT_ERROR_STORAGE    = 2,
+    ARM_UC_MONITOR_RESULT_ERROR_MEMORY     = 3,
+    ARM_UC_MONITOR_RESULT_ERROR_CONNECTION = 4,
+    ARM_UC_MONITOR_RESULT_ERROR_CRC        = 5,
+    ARM_UC_MONITOR_RESULT_ERROR_TYPE       = 6,
+    ARM_UC_MONITOR_RESULT_ERROR_URI        = 7,
+    ARM_UC_MONITOR_RESULT_ERROR_UPDATE     = 8,
+    ARM_UC_MONITOR_RESULT_ERROR_HASH       = 9,
+    ARM_UC_MONITOR_RESULT_LAST             = ARM_UC_MONITOR_RESULT_ERROR_HASH
+} arm_uc_monitor_result_t;
+
+/**
+ * @brief Structure definition holding API function pointers.
+ */
+typedef struct _ARM_UPDATE_MONITOR {
+
+    /**
+     * @brief Get driver version.
+     * @return Driver version.
+     */
+    uint32_t (*GetVersion)(void);
+
+    /**
+     * @brief Get Source capabilities.
+     * @return Struct containing capabilites. See definition above.
+     */
+    ARM_MONITOR_CAPABILITIES (*GetCapabilities)(void);
+
+    /**
+     * @brief Initialize Monitor.
+     * @return Error code.
+     */
+    arm_uc_error_t (*Initialize)(void (*notification_handler)(void));
+
+    /**
+     * @brief Uninitialized Monitor.
+     * @return Error code.
+     */
+    arm_uc_error_t (*Uninitialize)(void);
+
+    /**
+     * @brief Send Update Client state.
+     * @details From the OMA LWM2M Technical Specification:
+     *
+     *          Indicates current state with respect to this firmware update.
+     *          This value is set by the LWM2M Client.
+     *          0: Idle (before downloading or after successful updating)
+     *          1: Downloading (The data sequence is on the way)
+     *          2: Downloaded
+     *          3: Updating
+     *
+     *          If writing the firmware package to Package Resource is done,
+     *          or, if the device has downloaded the firmware package from the
+     *          Package URI the state changes to Downloaded.
+     *
+     *          If writing an empty string to Package Resource is done or
+     *          writing an empty string to Package URI is done, the state
+     *          changes to Idle.
+     *
+     *          When in Downloaded state, and the executable Resource Update is
+     *          triggered, the state changes to Updating.
+     *          If the Update Resource failed, the state returns at Downloaded.
+     *          If performing the Update Resource was successful, the state
+     *          changes from Updating to Idle.
+     *
+     * @param state Valid states: ARM_UC_MONITOR_STATE_IDLE
+     *                            ARM_UC_MONITOR_STATE_DOWNLOADING
+     *                            ARM_UC_MONITOR_STATE_DOWNLOADED
+     *                            ARM_UC_MONITOR_STATE_UPDATING
+     *
+     * @return Error code.
+     */
+    arm_uc_error_t (*SendState)(arm_uc_monitor_state_t state);
+
+    /**
+     * @brief Send update result.
+     * @details From the OMA LWM2M Technical Specification:
+     *
+     *          Contains the result of downloading or updating the firmware
+     *          0: Initial value. Once the updating process is initiated
+     *             (Download /Update), this Resource MUST be reset to Initial
+     *             value.
+     *          1: Firmware updated successfully,
+     *          2: Not enough storage for the new firmware package.
+     *          3. Out of memory during downloading process.
+     *          4: Connection lost during downloading process.
+     *          5: CRC check failure for new downloaded package.
+     *          6: Unsupported package type.
+     *          7: Invalid URI
+     *          8: Firmware update failed
+     *
+     *          This Resource MAY be reported by sending Observe operation.
+     *
+     * @param result Valid results: ARM_UC_MONITOR_RESULT_INITIAL
+     *                              ARM_UC_MONITOR_RESULT_SUCCESS
+     *                              ARM_UC_MONITOR_RESULT_ERROR_STORAGE
+     *                              ARM_UC_MONITOR_RESULT_ERROR_MEMORY
+     *                              ARM_UC_MONITOR_RESULT_ERROR_CONNECTION
+     *                              ARM_UC_MONITOR_RESULT_ERROR_CRC
+     *                              ARM_UC_MONITOR_RESULT_ERROR_TYPE
+     *                              ARM_UC_MONITOR_RESULT_ERROR_URI
+     *                              ARM_UC_MONITOR_RESULT_ERROR_UPDATE
+     *                              ARM_UC_MONITOR_RESULT_ERROR_HASH
+     *
+     * @return Error code.
+     */
+    arm_uc_error_t (*SendUpdateResult)(arm_uc_monitor_result_t updateResult);
+
+    /**
+     * @brief Send current firmware name.
+     * @details The firmware name is the SHA256 hash.
+     *
+     * @param name Pointer to buffer struct. Hash is stored as byte array.
+     * @return Error code.
+     */
+    arm_uc_error_t (*SendName)(arm_uc_buffer_t* name);
+
+    /**
+     * @brief Send current firmware version.
+     * @details The firmware version is the timestamp from the manifest that
+     *          authorized the firmware.
+     *
+     * @param version Timestamp, 64 bit unsigned integer.
+     * @return Error code.
+     */
+    arm_uc_error_t (*SendVersion)(uint64_t version);
+
+    /**
+     * @brief Set the bootloader hash.
+     * @details The bootloader hash is a hash of the bootloader. This is
+     *          used for tracking the version of the bootloader used.
+     *
+     * @param name Pointer to buffer struct. Hash is stored as byte array.
+     * @return Error code.
+     */
+    arm_uc_error_t (*SetBootloaderHash)(arm_uc_buffer_t* hash);
+
+    /**
+     * @brief Set the OEM bootloader hash.
+     * @details If the end-user has modified the bootloader the hash of the
+     *          modified bootloader can be set here.
+     *
+     * @param name Pointer to buffer struct. Hash is stored as byte array.
+     * @return Error code.
+     */
+    arm_uc_error_t (*SetOEMBootloaderHash)(arm_uc_buffer_t* hash);
+} ARM_UPDATE_MONITOR;
+
+#endif /* __ARM_UPDATE_MONITOR_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/paal/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,166 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/paal/source/arm_uc_paal_update.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,332 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+// fixup the compilation on ARMCC for PRIu32
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include "update-client-paal/arm_uc_paal_update.h"
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+#define TRACE_GROUP "UCPI"
+#include "update-client-common/arm_uc_trace.h"
+
+static const ARM_UC_PAAL_UPDATE* paal_update_implementation = NULL;
+
+/**
+ * @brief Set PAAL Update implementation.
+ *
+ * @param implementation Function pointer struct to implementation.
+ * @return Returns ERR_NONE on accept and ERR_INVALID_PARAMETER otherwise.
+ */
+arm_uc_error_t ARM_UCP_SetPAALUpdate(const ARM_UC_PAAL_UPDATE* implementation)
+{
+    UC_PAAL_TRACE("ARM_UCP_SetPAALUpdate");
+
+    paal_update_implementation = implementation;
+
+    return (arm_uc_error_t){ ERR_NONE };
+}
+
+/**
+ * @brief Initialize the underlying storage and set the callback handler.
+ *
+ * @param callback Function pointer to event handler.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback)
+{
+    UC_PAAL_TRACE("ARM_UCP_Initialize");
+
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (paal_update_implementation)
+    {
+        result = paal_update_implementation->Initialize(callback);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get a bitmap indicating supported features.
+ * @details The bitmap is used in conjunction with the firmware and
+ *          installer details struct to indicate what fields are supported
+ *          and which values are valid.
+ *
+ * @return Capability bitmap.
+ */
+ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UCP_GetCapabilities(void)
+{
+    UC_PAAL_TRACE("ARM_UCP_GetCapabilities");
+
+    ARM_UC_PAAL_UPDATE_CAPABILITIES result = { 0 };
+
+    if (paal_update_implementation)
+    {
+        result = paal_update_implementation->GetCapabilities();
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get maximum number of supported storage locations.
+ *
+ * @return Number of storage locations.
+ */
+uint32_t ARM_UCP_GetMaxID(void)
+{
+    UC_PAAL_TRACE("ARM_UCP_GetMaxID");
+
+    uint32_t result = 0;
+
+    if (paal_update_implementation)
+    {
+        result = paal_update_implementation->GetMaxID();
+    }
+
+    return result;
+}
+
+/**
+ * @brief Prepare the storage layer for a new firmware image.
+ * @details The storage location is set up to receive an image with
+ *          the details passed in the details struct.
+ *
+ * @param location Storage location ID.
+ * @param details Pointer to a struct with firmware details.
+ * @param buffer Temporary buffer for formatting and storing metadata.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_Prepare(uint32_t location,
+                               const arm_uc_firmware_details_t* details,
+                               arm_uc_buffer_t* buffer)
+{
+    UC_PAAL_TRACE("ARM_UCP_Prepare");
+
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (paal_update_implementation && details && buffer)
+    {
+        result = paal_update_implementation->Prepare(location,
+                                                     details,
+                                                     buffer);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Write a fragment to the indicated storage location.
+ * @details The storage location must have been allocated using the Prepare
+ *          call. The call is expected to write the entire fragment before
+ *          signaling completion.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to where the fragment should be written.
+ * @param buffer Pointer to buffer struct with fragment.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_Write(uint32_t location,
+                             uint32_t offset,
+                             const arm_uc_buffer_t* buffer)
+{
+    UC_PAAL_TRACE("ARM_UCP_Write: %p %p", paal_update_implementation, buffer);
+
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (paal_update_implementation && buffer)
+    {
+        result = paal_update_implementation->Write(location, offset, buffer);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Close storage location for writing and flush pending data.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_Finalize(uint32_t location)
+{
+    UC_PAAL_TRACE("ARM_UCP_Finalize");
+
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (paal_update_implementation)
+    {
+        result = paal_update_implementation->Finalize(location);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Read a fragment from the indicated storage location.
+ * @details The function will read until the buffer is full or the end of
+ *          the storage location has been reached. The actual amount of
+ *          bytes read is set in the buffer struct.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to read from.
+ * @param buffer Pointer to buffer struct to store fragment. buffer->size
+ *        contains the intended read size.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ *         buffer->size contains actual bytes read on return.
+ */
+arm_uc_error_t ARM_UCP_Read(uint32_t location,
+                            uint32_t offset,
+                            arm_uc_buffer_t* buffer)
+{
+    UC_PAAL_TRACE("ARM_UCP_Read: %" PRIX32 " %p", offset, buffer);
+
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (paal_update_implementation && buffer)
+    {
+        result = paal_update_implementation->Read(location, offset, buffer);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set the firmware image in the slot to be the new active image.
+ * @details This call is responsible for initiating the process for
+ *          applying a new/different image. Depending on the platform this
+ *          could be:
+ *           * An empty call, if the installer can deduce which slot to
+ *             choose from based on the firmware details.
+ *           * Setting a flag to indicate which slot to use next.
+ *           * Decompressing/decrypting/installing the firmware image on
+ *             top of another.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_Activate(uint32_t location)
+{
+    UC_PAAL_TRACE("ARM_UCP_Activate");
+
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (paal_update_implementation)
+    {
+        result = paal_update_implementation->Activate(location);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get firmware details for the actively running firmware.
+ * @details This call populates the passed details struct with information
+ *          about the currently active firmware image. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_GetActiveFirmwareDetails(arm_uc_firmware_details_t* details)
+{
+    UC_PAAL_TRACE("ARM_UCP_GetActiveFirmwareDetails");
+
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (paal_update_implementation && details)
+    {
+        result = paal_update_implementation->GetActiveFirmwareDetails(details);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get firmware details for the firmware image in the slot passed.
+ * @details This call populates the passed details struct with information
+ *          about the firmware image in the slot passed. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_GetFirmwareDetails(uint32_t location,
+                                          arm_uc_firmware_details_t* details)
+{
+    UC_PAAL_TRACE("ARM_UCP_GetFirmwareDetails");
+
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (paal_update_implementation && details)
+    {
+        result = paal_update_implementation->GetFirmwareDetails(location,
+                                                                details);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get details for the component responsible for installation.
+ * @details This call populates the passed details struct with information
+ *          about the local installer. Only the fields marked as supported
+ *          in the capabilities bitmap will have valid values. The
+ *          installer could be the bootloader, a recovery image, or some
+ *          other component responsible for applying the new firmware
+ *          image.
+ *
+ * @param details Pointer to installer details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_GetInstallerDetails(arm_uc_installer_details_t* details)
+{
+    UC_PAAL_TRACE("ARM_UCP_GetInstallerDetails");
+
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (paal_update_implementation && details)
+    {
+        result = paal_update_implementation->GetInstallerDetails(details);
+    }
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/paal/update-client-paal/arm_uc_paal_update.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,193 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+/* Not including arm_uc_common.h to avoid the scheduler from being
+   included in the mbed-bootloader.
+*/
+#include "update-client-common/arm_uc_error.h"
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Set PAAL Update implementation.
+ *
+ * @param implementation Function pointer struct to implementation.
+ * @return Returns ERR_NONE on accept and ERR_INVALID_PARAMETER otherwise.
+ */
+arm_uc_error_t ARM_UCP_SetPAALUpdate(const ARM_UC_PAAL_UPDATE* implementation);
+
+/**
+ * @brief Initialize the underlying storage and set the callback handler.
+ *
+ * @param callback Function pointer to event handler.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback);
+
+/**
+ * @brief Get a bitmap indicating supported features.
+ * @details The bitmap is used in conjunction with the firmware and
+ *          installer details struct to indicate what fields are supported
+ *          and which values are valid.
+ *
+ * @return Capability bitmap.
+ */
+ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UCP_GetCapabilities(void);
+
+/**
+ * @brief Get maximum number of supported storage locations.
+ *
+ * @return Number of storage locations.
+ */
+uint32_t ARM_UCP_GetMaxID(void);
+
+/**
+ * @brief Prepare the storage layer for a new firmware image.
+ * @details The storage location is set up to receive an image with
+ *          the details passed in the details struct.
+ *
+ * @param location Storage location ID.
+ * @param details Pointer to a struct with firmware details.
+ * @param buffer Temporary buffer for formatting and storing metadata.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_Prepare(uint32_t location,
+                               const arm_uc_firmware_details_t* details,
+                               arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Write a fragment to the indicated storage location.
+ * @details The storage location must have been allocated using the Prepare
+ *          call. The call is expected to write the entire fragment before
+ *          signaling completion.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to where the fragment should be written.
+ * @param buffer Pointer to buffer struct with fragment.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_Write(uint32_t location,
+                             uint32_t offset,
+                             const arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Close storage location for writing and flush pending data.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_Finalize(uint32_t location);
+
+/**
+ * @brief Read a fragment from the indicated storage location.
+ * @details The function will read until the buffer is full or the end of
+ *          the storage location has been reached. The actual amount of
+ *          bytes read is set in the buffer struct.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to read from.
+ * @param buffer Pointer to buffer struct to store fragment. buffer->size
+ *        contains the intended read size.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ *         buffer->size contains actual bytes read on return.
+ */
+arm_uc_error_t ARM_UCP_Read(uint32_t location,
+                            uint32_t offset,
+                            arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Set the firmware image in the slot to be the new active image.
+ * @details This call is responsible for initiating the process for
+ *          applying a new/different image. Depending on the platform this
+ *          could be:
+ *           * An empty call, if the installer can deduce which slot to
+ *             choose from based on the firmware details.
+ *           * Setting a flag to indicate which slot to use next.
+ *           * Decompressing/decrypting/installing the firmware image on
+ *             top of another.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_Activate(uint32_t location);
+
+/**
+ * @brief Get firmware details for the actively running firmware.
+ * @details This call populates the passed details struct with information
+ *          about the currently active firmware image. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_GetActiveFirmwareDetails(arm_uc_firmware_details_t* details);
+
+/**
+ * @brief Get firmware details for the firmware image in the slot passed.
+ * @details This call populates the passed details struct with information
+ *          about the firmware image in the slot passed. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_GetFirmwareDetails(uint32_t location,
+                                          arm_uc_firmware_details_t* details);
+
+/**
+ * @brief Get details for the component responsible for installation.
+ * @details This call populates the passed details struct with information
+ *          about the local installer. Only the fields marked as supported
+ *          in the capabilities bitmap will have valid values. The
+ *          installer could be the bootloader, a recovery image, or some
+ *          other component responsible for applying the new firmware
+ *          image.
+ *
+ * @param details Pointer to installer details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_GetInstallerDetails(arm_uc_installer_details_t* details);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/paal/update-client-paal/arm_uc_paal_update_api.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,238 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAAL_UPDATE_API_H
+#define ARM_UC_PAAL_UPDATE_API_H
+
+/* Not including arm_uc_common.h to avoid the scheduler from being
+   included in the mbed-bootloader.
+*/
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_types.h"
+
+#include <stdint.h>
+
+/**
+ * @brief Prototype for event handler.
+ */
+typedef void (*ARM_UC_PAAL_UPDATE_SignalEvent_t)(uint32_t event);
+
+/**
+ * @brief Asynchronous events.
+ */
+enum
+{
+    ARM_UC_PAAL_EVENT_INITIALIZE_DONE,
+    ARM_UC_PAAL_EVENT_PREPARE_DONE,
+    ARM_UC_PAAL_EVENT_WRITE_DONE,
+    ARM_UC_PAAL_EVENT_FINALIZE_DONE,
+    ARM_UC_PAAL_EVENT_READ_DONE,
+    ARM_UC_PAAL_EVENT_ACTIVATE_DONE,
+    ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE,
+    ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE,
+    ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE,
+    ARM_UC_PAAL_EVENT_INITIALIZE_ERROR,
+    ARM_UC_PAAL_EVENT_PREPARE_ERROR,
+    ARM_UC_PAAL_EVENT_WRITE_ERROR,
+    ARM_UC_PAAL_EVENT_FINALIZE_ERROR,
+    ARM_UC_PAAL_EVENT_READ_ERROR,
+    ARM_UC_PAAL_EVENT_ACTIVATE_ERROR,
+    ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_ERROR,
+    ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_ERROR,
+    ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_ERROR,
+};
+
+/**
+ * @brief Bitmap with supported header features.
+ * @details The PAAL Update implementation indicates what features are
+ *          supported. This can be used after a call to one of the GetDetails
+ *          to see which fields have valid values and what fields should be set
+ *          in the call to Prepare.
+ */
+typedef struct _ARM_UC_PAAL_UPDATE_CAPABILITIES {
+    uint32_t installer_arm_hash: 1;
+    uint32_t installer_oem_hash: 1;
+    uint32_t installer_layout: 1;
+    uint32_t firmware_hash: 1;
+    uint32_t firmware_hmac: 1;
+    uint32_t firmware_campaign: 1;
+    uint32_t firmware_version: 1;
+    uint32_t firmware_size: 1;
+    uint32_t reserved: 24;
+} ARM_UC_PAAL_UPDATE_CAPABILITIES;
+
+/**
+ * @brief Structure definition holding API function pointers.
+ */
+typedef struct _ARM_UC_PAAL_UPDATE {
+
+    /**
+     * @brief Initialize the underlying storage and set the callback handler.
+     *
+     * @param callback Function pointer to event handler.
+     * @return Returns ERR_NONE on accept, and signals the event handler with
+     *         either DONE or ERROR when complete.
+     *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+     */
+    arm_uc_error_t (*Initialize)(ARM_UC_PAAL_UPDATE_SignalEvent_t callback);
+
+    /**
+     * @brief Get a bitmap indicating supported features.
+     * @details The bitmap is used in conjunction with the firmware and
+     *          installer details struct to indicate what fields are supported
+     *          and which values are valid.
+     *
+     * @return Capability bitmap.
+     */
+    ARM_UC_PAAL_UPDATE_CAPABILITIES (*GetCapabilities)(void);
+
+    /**
+     * @brief Get maximum number of supported storage locations.
+     *
+     * @return Number of storage locations.
+     */
+    uint32_t (*GetMaxID)(void);
+
+    /**
+     * @brief Prepare the storage layer for a new firmware image.
+     * @details The storage location is set up to receive an image with
+     *          the details passed in the details struct.
+     *
+     * @param location Storage location ID.
+     * @param details Pointer to a struct with firmware details.
+     * @param buffer Temporary buffer for formatting and storing metadata.
+     * @return Returns ERR_NONE on accept, and signals the event handler with
+     *         either DONE or ERROR when complete.
+     *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+     */
+    arm_uc_error_t (*Prepare)(uint32_t location,
+                              const arm_uc_firmware_details_t* details,
+                              arm_uc_buffer_t* buffer);
+
+    /**
+     * @brief Write a fragment to the indicated storage location.
+     * @details The storage location must have been allocated using the Prepare
+     *          call. The call is expected to write the entire fragment before
+     *          signaling completion.
+     *
+     * @param location Storage location ID.
+     * @param offset Offset in bytes to where the fragment should be written.
+     * @param buffer Pointer to buffer struct with fragment.
+     * @return Returns ERR_NONE on accept, and signals the event handler with
+     *         either DONE or ERROR when complete.
+     *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+     */
+    arm_uc_error_t (*Write)(uint32_t location,
+                            uint32_t offset,
+                            const arm_uc_buffer_t* buffer);
+
+    /**
+     * @brief Close storage location for writing and flush pending data.
+     *
+     * @param location Storage location ID.
+     * @return Returns ERR_NONE on accept, and signals the event handler with
+     *         either DONE or ERROR when complete.
+     *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+     */
+    arm_uc_error_t (*Finalize)(uint32_t location);
+
+    /**
+     * @brief Read a fragment from the indicated storage location.
+     * @details The function will read until the buffer is full or the end of
+     *          the storage location has been reached. The actual amount of
+     *          bytes read is set in the buffer struct.
+     *
+     * @param location Storage location ID.
+     * @param offset Offset in bytes to read from.
+     * @param buffer Pointer to buffer struct to store fragment. buffer->size
+     *        contains the intended read size.
+     * @return Returns ERR_NONE on accept, and signals the event handler with
+     *         either DONE or ERROR when complete.
+     *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+     *         buffer->size contains actual bytes read on return.
+     */
+    arm_uc_error_t (*Read)(uint32_t location,
+                           uint32_t offset,
+                           arm_uc_buffer_t* buffer);
+
+    /**
+     * @brief Set the firmware image in the slot to be the new active image.
+     * @details This call is responsible for initiating the process for
+     *          applying a new/different image. Depending on the platform this
+     *          could be:
+     *           * An empty call, if the installer can deduce which slot to
+     *             choose from based on the firmware details.
+     *           * Setting a flag to indicate which slot to use next.
+     *           * Decompressing/decrypting/installing the firmware image on
+     *             top of another.
+     *
+     * @param location Storage location ID.
+     * @return Returns ERR_NONE on accept, and signals the event handler with
+     *         either DONE or ERROR when complete.
+     *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+     */
+    arm_uc_error_t (*Activate)(uint32_t location);
+
+    /**
+     * @brief Get firmware details for the actively running firmware.
+     * @details This call populates the passed details struct with information
+     *          about the currently active firmware image. Only the fields
+     *          marked as supported in the capabilities bitmap will have valid
+     *          values.
+     *
+     * @param details Pointer to firmware details struct to be populated.
+     * @return Returns ERR_NONE on accept, and signals the event handler with
+     *         either DONE or ERROR when complete.
+     *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+     */
+    arm_uc_error_t (*GetActiveFirmwareDetails)(arm_uc_firmware_details_t* details);
+
+    /**
+     * @brief Get firmware details for the firmware image in the slot passed.
+     * @details This call populates the passed details struct with information
+     *          about the firmware image in the slot passed. Only the fields
+     *          marked as supported in the capabilities bitmap will have valid
+     *          values.
+     *
+     * @param details Pointer to firmware details struct to be populated.
+     * @return Returns ERR_NONE on accept, and signals the event handler with
+     *         either DONE or ERROR when complete.
+     *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+     */
+    arm_uc_error_t (*GetFirmwareDetails)(uint32_t location,
+                                         arm_uc_firmware_details_t* details);
+
+    /**
+     * @brief Get details for the component responsible for installation.
+     * @details This call populates the passed details struct with information
+     *          about the local installer. Only the fields marked as supported
+     *          in the capabilities bitmap will have valid values. The
+     *          installer could be the bootloader, a recovery image, or some
+     *          other component responsible for applying the new firmware
+     *          image.
+     *
+     * @param details Pointer to installer details struct to be populated.
+     * @return Returns ERR_NONE on accept, and signals the event handler with
+     *         either DONE or ERROR when complete.
+     *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+     */
+    arm_uc_error_t (*GetInstallerDetails)(arm_uc_installer_details_t* details);
+
+} ARM_UC_PAAL_UPDATE;
+
+#endif /* ARM_UC_PAAL_UPDATE_API_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+*/test/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/source/arm_uc_pal_blockdevice.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,83 @@
+//----------------------------------------------------------------------------
+//   The confidential and proprietary information contained in this file may
+//   only be used by a person authorised under and to the extent permitted
+//   by a subsisting licensing agreement from ARM Limited or its affiliates.
+//
+//          (C) COPYRIGHT 2016 ARM Limited or its affiliates.
+//              ALL RIGHTS RESERVED
+//
+//   This entire notice must be reproduced on all copies of this file
+//   and copies of this file may only be made by a person if such person is
+//   permitted to do so under the terms of a subsisting license agreement
+//   from ARM Limited or its affiliates.
+//----------------------------------------------------------------------------
+
+#if defined(ARM_UC_USE_PAL_BLOCKDEVICE)
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+#include "update-client-pal-blockdevice/arm_uc_pal_blockdevice_implementation.h"
+#include "update-client-pal-flashiap/arm_uc_pal_flashiap_implementation.h"
+
+/**
+ * @brief Initialize the underlying storage and set the callback handler.
+ *
+ * @param callback Function pointer to event handler.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UCP_FashIAP_BlockDevice_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (callback)
+    {
+        arm_uc_error_t status1 = ARM_UC_PAL_FlashIAP_Initialize(callback);
+        arm_uc_error_t status2 = ARM_UC_PAL_BlockDevice_Initialize(callback);
+
+        if ((status1.error == ERR_NONE) && (status2.error == ERR_NONE))
+        {
+            result.code = ERR_NONE;
+        }
+        else
+        {
+            result.code = ERR_NOT_READY;
+        }
+    }
+
+    return result;
+}
+
+ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UCP_FashIAP_BlockDevice_GetCapabilities(void)
+{
+    ARM_UC_PAAL_UPDATE_CAPABILITIES result = {
+        .installer_arm_hash = 0,
+        .installer_oem_hash = 0,
+        .installer_layout   = 0,
+        .firmware_hash      = 1,
+        .firmware_hmac      = 0,
+        .firmware_campaign  = 0,
+        .firmware_version   = 1,
+        .firmware_size      = 1
+    };
+
+    return result;
+}
+
+const ARM_UC_PAAL_UPDATE ARM_UCP_FLASHIAP_BLOCKDEVICE =
+{
+    .Initialize                 = ARM_UCP_FashIAP_BlockDevice_Initialize,
+    .GetCapabilities            = ARM_UCP_FashIAP_BlockDevice_GetCapabilities,
+    .GetMaxID                   = ARM_UC_PAL_BlockDevice_GetMaxID,
+    .Prepare                    = ARM_UC_PAL_BlockDevice_Prepare,
+    .Write                      = ARM_UC_PAL_BlockDevice_Write,
+    .Finalize                   = ARM_UC_PAL_BlockDevice_Finalize,
+    .Read                       = ARM_UC_PAL_BlockDevice_Read,
+    .Activate                   = ARM_UC_PAL_BlockDevice_Activate,
+    .GetActiveFirmwareDetails   = ARM_UC_PAL_FlashIAP_GetActiveDetails,
+    .GetFirmwareDetails         = ARM_UC_PAL_BlockDevice_GetFirmwareDetails,
+    .GetInstallerDetails        = ARM_UC_PAL_FlashIAP_GetInstallerDetails
+};
+
+#endif // #if defined(ARM_UC_USE_PAL_BLOCKDEVICE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/source/arm_uc_pal_blockdevice_implementation.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,570 @@
+//----------------------------------------------------------------------------
+//   The confidential and proprietary information contained in this file may
+//   only be used by a person authorised under and to the extent permitted
+//   by a subsisting licensing agreement from ARM Limited or its affiliates.
+//
+//          (C) COPYRIGHT 2017 ARM Limited or its affiliates.
+//              ALL RIGHTS RESERVED
+//
+//   This entire notice must be reproduced on all copies of this file
+//   and copies of this file may only be made by a person if such person is
+//   permitted to do so under the terms of a subsisting license agreement
+//   from ARM Limited or its affiliates.
+//----------------------------------------------------------------------------
+
+#if defined(ARM_UC_USE_PAL_BLOCKDEVICE)
+
+#define __STDC_FORMAT_MACROS
+
+#include "update-client-pal-blockdevice/arm_uc_pal_blockdevice.h"
+
+#include "update-client-pal-blockdevice/arm_uc_pal_blockdevice_platform.h"
+
+#include "update-client-common/arm_uc_config.h"
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_types.h"
+#include "update-client-common/arm_uc_metadata_header_v2.h"
+
+#define TRACE_GROUP "UCPI"
+#include "update-client-common/arm_uc_trace.h"
+#include <inttypes.h>
+
+#ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS
+#define MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS 0
+#endif
+
+#ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_SIZE
+#define MBED_CONF_UPDATE_CLIENT_STORAGE_SIZE 0
+#endif
+
+#ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE
+#define MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE 1
+#endif
+
+#ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS
+#define MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS 1
+#endif
+
+/* consistency check */
+#if (MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE == 0)
+#error Update client storage page cannot be zero.
+#endif
+
+#if (MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS == 0)
+#error Update client storage locations must be at least 1.
+#endif
+
+/* Check that the statically allocated buffers are aligned with the block size */
+#define ARM_UC_PAL_ONE_BUFFER (ARM_UC_BUFFER_SIZE / 2)
+#define ARM_UC_PAL_PAGES (ARM_UC_PAL_ONE_BUFFER / MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE)
+
+#if !((ARM_UC_PAL_PAGES * MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE) == ARM_UC_PAL_ONE_BUFFER)
+#error Update client buffer must be divisible by the block page size
+#endif
+
+static ARM_UC_PAAL_UPDATE_SignalEvent_t pal_blockdevice_event_handler = NULL;
+static uint32_t pal_blockdevice_firmware_size = 0;
+static uint32_t pal_blockdevice_page_size = 0;
+static uint32_t pal_blockdevice_sector_size = 0;
+static uint32_t pal_blockdevice_hdr_size =0;
+
+static void pal_blockdevice_signal_internal(uint32_t event)
+{
+    if (pal_blockdevice_event_handler)
+    {
+        pal_blockdevice_event_handler(event);
+    }
+}
+
+/**
+ * @brief Round size up to nearest page
+ *
+ * @param size The size that need to be rounded up
+ * @return Returns the size rounded up to the nearest page
+ */
+static uint32_t pal_blockdevice_round_up_to_page(uint32_t size)
+{
+    return ((size - 1)/pal_blockdevice_page_size + 1) * pal_blockdevice_page_size;
+}
+
+/**
+ * @brief Round size down to nearest page
+ *
+ * @param size The size that need to be rounded up
+ * @return Returns the size rounded up to the nearest page
+ */
+static uint32_t pal_blockdevice_round_down_to_page(uint32_t size)
+{
+    return (size/pal_blockdevice_page_size) * pal_blockdevice_page_size;
+}
+
+/**
+ * @brief Align size up to sector size
+ *
+ * @param size The size that need to be rounded up
+ * @return Returns the size aligned to sector size
+ */
+static uint32_t pal_blockdevice_round_up_to_sector(uint32_t size)
+{
+    return ((size - 1)/pal_blockdevice_sector_size + 1) * pal_blockdevice_sector_size;
+}
+
+/**
+ * @brief Align size down to sector size
+ *
+ * @param size The size that need to be rounded up
+ * @return Returns the size aligned to sector boundary
+ */
+static uint32_t pal_blockdevice_round_down_to_sector(uint32_t size)
+{
+    return (size / pal_blockdevice_sector_size) * pal_blockdevice_sector_size;
+}
+
+/**
+ * @brief Get the physicl slot address and size given slot_id
+ *
+ * @param slot_id Storage location ID.
+ * @param slot_addr the slot address is returned in this pointer
+ * @param slot_size the slot size is returned in this pointer
+ * @return Returns ERR_NONE on success.
+ *         Returns ERR_INVALID_PARAMETER on error.
+ */
+static arm_uc_error_t pal_blockdevice_get_slot_addr_size(uint32_t slot_id,
+                                                         uint32_t* slot_addr,
+                                                         uint32_t* slot_size)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if ((slot_id < MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS) &&
+        (slot_addr != NULL) &&
+        (slot_size != NULL))
+    {
+        /* find the start address of the whole storage area. It needs to be aligned to
+           sector boundary and we cannot go outside user defined storage area, hence
+           rounding up to sector boundary */
+        uint32_t storage_start_addr = pal_blockdevice_round_up_to_sector(
+                                        MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS);
+        /* find the end address of the whole storage area. It needs to be aligned to
+           sector boundary and we cannot go outside user defined storage area, hence
+           rounding down to sector boundary */
+        uint32_t storage_end_addr = pal_blockdevice_round_down_to_sector(
+                                        MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS + \
+                                        MBED_CONF_UPDATE_CLIENT_STORAGE_SIZE);
+        /* find the maximum size each slot can have given the start and end, without
+           considering the alignment of individual slots */
+        uint32_t max_slot_size = (storage_end_addr - storage_start_addr) / \
+                                        MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS;
+        /* find the start address of slot. It needs to align to sector boundary. We
+           choose here to round down at each slot boundary */
+        *slot_addr = storage_start_addr + pal_blockdevice_round_down_to_sector(
+                                        slot_id * max_slot_size);
+        /* Rounding down slot size to sector boundary same as
+           the slot start address so that we make sure two slot don't overlap */
+        *slot_size  = pal_blockdevice_round_down_to_sector(max_slot_size);
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Initialize the underlying storage and set the callback handler.
+ *
+ * @param callback Function pointer to event handler.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (callback)
+    {
+        UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_Initialize");
+
+        int status = arm_uc_blockdevice_init();
+        pal_blockdevice_page_size  = arm_uc_blockdevice_get_program_size();
+        pal_blockdevice_sector_size = arm_uc_blockdevice_get_erase_size();
+        pal_blockdevice_hdr_size   = pal_blockdevice_round_up_to_page(ARM_UC_EXTERNAL_HEADER_SIZE_V2);
+
+        if (status == ARM_UC_BLOCKDEVICE_SUCCESS)
+        {
+            pal_blockdevice_event_handler = callback;
+            pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_INITIALIZE_DONE);
+            result.code = ERR_NONE;
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get maximum number of supported storage locations.
+ *
+ * @return Number of storage locations.
+ */
+uint32_t ARM_UC_PAL_BlockDevice_GetMaxID(void)
+{
+    return MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS;
+}
+
+/**
+ * @brief Prepare the storage layer for a new firmware image.
+ * @details The storage location is set up to receive an image with
+ *          the details passed in the details struct.
+ *
+ * @param slot_id Storage location ID.
+ * @param details Pointer to a struct with firmware details.
+ * @param buffer Temporary buffer for formatting and storing metadata.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_Prepare(uint32_t slot_id,
+                                              const arm_uc_firmware_details_t* details,
+                                              arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details && buffer && buffer->ptr)
+    {
+        UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_Prepare: %" PRIX32 " %" PRIX32,
+                 slot_id, details->size);
+
+        /* encode firmware details in buffer */
+        arm_uc_error_t header_status = arm_uc_create_external_header_v2(details,
+                                                                        buffer);
+        if (header_status.error == ERR_NONE)
+        {
+            /* find the size needed to erase. Header is stored contiguous with firmware */
+            uint32_t erase_size = pal_blockdevice_round_up_to_sector(pal_blockdevice_hdr_size + \
+                                                                details->size);
+
+            /* find address of slot */
+            uint32_t slot_addr = ARM_UC_BLOCKDEVICE_INVALID_SIZE;
+            uint32_t slot_size = ARM_UC_BLOCKDEVICE_INVALID_SIZE;
+            result = pal_blockdevice_get_slot_addr_size(slot_id, &slot_addr, &slot_size);
+
+            UC_PAAL_TRACE("erase: %" PRIX32 " %" PRIX32 " %" PRIX32, slot_addr, erase_size, slot_size);
+
+            int status = ARM_UC_BLOCKDEVICE_FAIL;
+            if (result.error == ERR_NONE)
+            {
+                if (erase_size <= slot_size)
+                {
+                    /* erase */
+                    status = arm_uc_blockdevice_erase(slot_addr, erase_size);
+                }
+                else
+                {
+                    UC_PAAL_ERR_MSG("not enough space for firmware image");
+                    result.code = ERR_INVALID_PARAMETER;
+                }
+            }
+
+            if (status == ARM_UC_BLOCKDEVICE_SUCCESS)
+            {
+                /* write header */
+                status = arm_uc_blockdevice_program(buffer->ptr,
+                                                    slot_addr,
+                                                    pal_blockdevice_hdr_size);
+
+                if (status == ARM_UC_BLOCKDEVICE_SUCCESS)
+                {
+                    /* set return code */
+                    result.code = ERR_NONE;
+
+                    /* store firmware size in global */
+                    pal_blockdevice_firmware_size = details->size;
+
+                    /* signal done */
+                    pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_PREPARE_DONE);
+                }
+                else
+                {
+                    UC_PAAL_ERR_MSG("arm_uc_blockdevice_program failed");
+                }
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("arm_uc_blockdevice_erase failed");
+            }
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("arm_uc_create_external_header_v2 failed");
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Write a fragment to the indicated storage location.
+ * @details The storage location must have been allocated using the Prepare
+ *          call. The call is expected to write the entire fragment before
+ *          signaling completion.
+ *
+ * @param slot_id Storage location ID.
+ * @param offset Offset in bytes to where the fragment should be written.
+ * @param buffer Pointer to buffer struct with fragment.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_Write(uint32_t slot_id,
+                                            uint32_t offset,
+                                            const arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (buffer && buffer->ptr)
+    {
+        UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_Write: %" PRIX32 " %" PRIX32 " %" PRIX32,
+                 slot_id, offset, buffer->size);
+        int status = ARM_UC_BLOCKDEVICE_SUCCESS;
+
+        /* find address of slot */
+        uint32_t slot_addr = ARM_UC_BLOCKDEVICE_INVALID_SIZE;
+        uint32_t slot_size = ARM_UC_BLOCKDEVICE_INVALID_SIZE;
+        result = pal_blockdevice_get_slot_addr_size(slot_id, &slot_addr, &slot_size);
+        uint32_t physical_address = slot_addr + pal_blockdevice_hdr_size + offset;
+
+        /* check that we are not writing too much */
+        uint32_t aligned_size = 0;
+        if (pal_blockdevice_firmware_size < offset + buffer->size)
+        {
+            UC_PAAL_ERR_MSG("programming more than firmware size %" PRIu32
+                            " < %" PRIu32 " + %" PRIu32,
+                            pal_blockdevice_firmware_size, offset, buffer->size);
+        }
+        else if ((pal_blockdevice_firmware_size > offset + buffer->size) &&
+                 (buffer->size % pal_blockdevice_page_size != 0))
+        {
+            UC_PAAL_ERR_MSG("program size %" PRIu32 " does not align to page size %" PRIu32,
+                buffer->size, pal_blockdevice_page_size);
+        }
+        else if(pal_blockdevice_firmware_size == offset + buffer->size)
+        {
+            /* last chunk write page aligned data first */
+            aligned_size = pal_blockdevice_round_down_to_page(buffer->size);
+        }
+        else
+        {
+            aligned_size = buffer->size;
+        }
+
+        /* aligned write */
+        if (result.error == ERR_NONE && aligned_size > 0)
+        {
+            status = arm_uc_blockdevice_program(buffer->ptr,
+                                                physical_address,
+                                                aligned_size);
+            if (status == ARM_UC_BLOCKDEVICE_FAIL)
+            {
+                UC_PAAL_ERR_MSG("arm_uc_blockdevice_program failed");
+            }
+        }
+
+        /* last chunk write remainder */
+        uint32_t remainder_size = buffer->size - aligned_size;
+
+        if ((status == ARM_UC_BLOCKDEVICE_SUCCESS) && (remainder_size > 0))
+        {
+            /* check if it is safe to use buffer, i.e. buffer is larger than a page */
+            if (buffer->size_max >= pal_blockdevice_page_size)
+            {
+                memmove(buffer->ptr, &(buffer->ptr[aligned_size]), remainder_size);
+                status = arm_uc_blockdevice_program(buffer->ptr,
+                                                    physical_address + aligned_size,
+                                                    pal_blockdevice_page_size);
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("arm_uc_blockdevice_program failed");
+
+                status = ARM_UC_BLOCKDEVICE_FAIL;
+            }
+        }
+
+        if (status == ARM_UC_BLOCKDEVICE_SUCCESS)
+        {
+            /* set return code */
+            result.code = ERR_NONE;
+
+            /* signal done */
+            pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_WRITE_DONE);
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("arm_uc_blockdevice_program failed");
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Close storage location for writing and flush pending data.
+ *
+ * @param slot_id Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_Finalize(uint32_t slot_id)
+{
+    arm_uc_error_t result = { .code = ERR_NONE };
+
+    UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_Finalize");
+
+    pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_FINALIZE_DONE);
+
+    return result;
+}
+
+/**
+ * @brief Read a fragment from the indicated storage location.
+ * @details The function will read until the buffer is full or the end of
+ *          the storage location has been reached. The actual amount of
+ *          bytes read is set in the buffer struct.
+ *
+ * @param slot_id Storage location ID.
+ * @param offset Offset in bytes to read from.
+ * @param buffer Pointer to buffer struct to store fragment. buffer->size
+ *        contains the intended read size.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ *         buffer->size contains actual bytes read on return.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_Read(uint32_t slot_id,
+                                           uint32_t offset,
+                                           arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (buffer && buffer->ptr)
+    {
+        UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_Read: %" PRIX32 " %" PRIX32 " %" PRIX32,
+                 slot_id, offset, buffer->size);
+
+        /* find address of slot */
+        uint32_t slot_addr = ARM_UC_BLOCKDEVICE_INVALID_SIZE;
+        uint32_t slot_size = ARM_UC_BLOCKDEVICE_INVALID_SIZE;
+        result = pal_blockdevice_get_slot_addr_size(slot_id,
+                                               &slot_addr,
+                                               &slot_size);
+        uint32_t physical_address = slot_addr + pal_blockdevice_hdr_size + offset;
+        uint32_t read_size = pal_blockdevice_round_up_to_page(buffer->size);
+        int32_t status = ARM_UC_BLOCKDEVICE_FAIL;
+
+        if (read_size <= buffer->size_max)
+        {
+            status = arm_uc_blockdevice_read(buffer->ptr,
+                                             physical_address,
+                                             read_size);
+        }
+
+        if (status == ARM_UC_BLOCKDEVICE_SUCCESS)
+        {
+            /* set return code */
+            result.code = ERR_NONE;
+
+            /* signal done */
+            pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_READ_DONE);
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("arm_uc_blockdevice_read failed");
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set the firmware image in the slot to be the new active image.
+ * @details This call is responsible for initiating the process for
+ *          applying a new/different image. Depending on the platform this
+ *          could be:
+ *           * An empty call, if the installer can deduce which slot to
+ *             choose from based on the firmware details.
+ *           * Setting a flag to indicate which slot to use next.
+ *           * Decompressing/decrypting/installing the firmware image on
+ *             top of another.
+ *
+ * @param slot_id Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_Activate(uint32_t slot_id)
+{
+    arm_uc_error_t result = { .code = ERR_NONE };
+
+    UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_Activate");
+
+    pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_ACTIVATE_DONE);
+
+    return result;
+}
+
+/**
+ * @brief Get firmware details for the firmware image in the slot passed.
+ * @details This call populates the passed details struct with information
+ *          about the firmware image in the slot passed. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param slot_id Storage location ID.
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_GetFirmwareDetails(
+                                        uint32_t slot_id,
+                                        arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        UC_PAAL_TRACE("ARM_UC_PAL_BlockDevice_GetFirmwareDetails");
+
+        /* find address of slot */
+        uint32_t slot_addr = ARM_UC_BLOCKDEVICE_INVALID_SIZE;
+        uint32_t slot_size = ARM_UC_BLOCKDEVICE_INVALID_SIZE;
+        result = pal_blockdevice_get_slot_addr_size(slot_id, &slot_addr, &slot_size);
+        uint8_t buffer[pal_blockdevice_hdr_size];
+
+        int status = arm_uc_blockdevice_read(buffer,
+                                             slot_addr,
+                                             pal_blockdevice_hdr_size);
+
+        if (status == ARM_UC_BLOCKDEVICE_SUCCESS)
+        {
+            result = arm_uc_parse_external_header_v2(buffer, details);
+
+            if (result.error == ERR_NONE)
+            {
+                /* signal done */
+                pal_blockdevice_signal_internal(ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE);
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("arm_uc_parse_external_header_v2 failed");
+            }
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("arm_uc_blockdevice_read failed");
+        }
+    }
+
+    return result;
+}
+
+#endif // #if defined(ARM_UC_USE_PAL_BLOCKDEVICE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/source/arm_uc_pal_blockdevice_mbed.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,56 @@
+//----------------------------------------------------------------------------
+//   The confidential and proprietary information contained in this file may
+//   only be used by a person authorised under and to the extent permitted
+//   by a subsisting licensing agreement from ARM Limited or its affiliates.
+//
+//          (C) COPYRIGHT 2017 ARM Limited or its affiliates.
+//              ALL RIGHTS RESERVED
+//
+//   This entire notice must be reproduced on all copies of this file
+//   and copies of this file may only be made by a person if such person is
+//   permitted to do so under the terms of a subsisting license agreement
+//   from ARM Limited or its affiliates.
+//----------------------------------------------------------------------------
+
+#if defined(TARGET_LIKE_MBED) && defined(ARM_UC_USE_PAL_BLOCKDEVICE)
+
+#include "update-client-pal-blockdevice/arm_uc_pal_blockdevice_platform.h"
+#include "mbed.h"
+
+extern BlockDevice* arm_uc_blockdevice;
+
+int32_t arm_uc_blockdevice_init(void)
+{
+    return arm_uc_blockdevice->init();
+}
+
+uint32_t arm_uc_blockdevice_get_program_size(void)
+{
+    return arm_uc_blockdevice->get_program_size();
+}
+
+uint32_t arm_uc_blockdevice_get_erase_size(void)
+{
+    return arm_uc_blockdevice->get_erase_size();
+}
+
+int32_t arm_uc_blockdevice_erase(uint64_t address, uint64_t size)
+{
+    return arm_uc_blockdevice->erase(address, size);
+}
+
+int32_t arm_uc_blockdevice_program(const uint8_t* buffer,
+                                   uint64_t address,
+                                   uint32_t size)
+{
+    return arm_uc_blockdevice->program(buffer, address, size);
+}
+
+int32_t arm_uc_blockdevice_read(uint8_t* buffer,
+                                uint64_t address,
+                                uint32_t size)
+{
+    return arm_uc_blockdevice->read(buffer, address, size);
+}
+
+#endif // #if defined(TARGET_LIKE_MBED) && defined(ARM_UC_USE_PAL_BLOCKDEVICE)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/update-client-pal-blockdevice/arm_uc_pal_blockdevice.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,22 @@
+//----------------------------------------------------------------------------
+//   The confidential and proprietary information contained in this file may
+//   only be used by a person authorised under and to the extent permitted
+//   by a subsisting licensing agreement from ARM Limited or its affiliates.
+//
+//          (C) COPYRIGHT 2016 ARM Limited or its affiliates.
+//              ALL RIGHTS RESERVED
+//
+//   This entire notice must be reproduced on all copies of this file
+//   and copies of this file may only be made by a person if such person is
+//   permitted to do so under the terms of a subsisting license agreement
+//   from ARM Limited or its affiliates.
+//----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_FLASHIAP_BLOCKDEVICE_H
+#define ARM_UC_PAL_FLASHIAP_BLOCKDEVICE_H
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+extern ARM_UC_PAAL_UPDATE ARM_UCP_FLASHIAP_BLOCKDEVICE;
+
+#endif /* ARM_UC_PAL_FLASHIAP_BLOCKDEVICE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/update-client-pal-blockdevice/arm_uc_pal_blockdevice_implementation.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,142 @@
+//----------------------------------------------------------------------------
+//   The confidential and proprietary information contained in this file may
+//   only be used by a person authorised under and to the extent permitted
+//   by a subsisting licensing agreement from ARM Limited or its affiliates.
+//
+//          (C) COPYRIGHT 2017 ARM Limited or its affiliates.
+//              ALL RIGHTS RESERVED
+//
+//   This entire notice must be reproduced on all copies of this file
+//   and copies of this file may only be made by a person if such person is
+//   permitted to do so under the terms of a subsisting license agreement
+//   from ARM Limited or its affiliates.
+//----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_BLOCKDEVICE_IMPLEMENTATION_H
+#define ARM_UC_PAL_BLOCKDEVICE_IMPLEMENTATION_H
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialize the underlying storage and set the callback handler.
+ *
+ * @param callback Function pointer to event handler.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback);
+
+/**
+ * @brief Get maximum number of supported storage IDs.
+ *
+ * @return Number of storage locations.
+ */
+uint32_t ARM_UC_PAL_BlockDevice_GetMaxID(void);
+
+/**
+ * @brief Prepare the storage layer for a new firmware image.
+ * @details The storage location is set up to receive an image with
+ *          the details passed in the details struct.
+ *
+ * @param slot_id Storage location ID.
+ * @param details Pointer to a struct with firmware details.
+ * @param buffer Temporary buffer for formatting and storing metadata.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_Prepare(uint32_t slot_id,
+                                              const arm_uc_firmware_details_t* details,
+                                              arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Write a fragment to the indicated storage location.
+ * @details The storage location must have been allocated using the Prepare
+ *          call. The call is expected to write the entire fragment before
+ *          signaling completion.
+ *
+ * @param slot_id Storage location ID.
+ * @param offset Offset in bytes to where the fragment should be written.
+ * @param buffer Pointer to buffer struct with fragment.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_Write(uint32_t slot_id,
+                                            uint32_t offset,
+                                            const arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Close storage location for writing and flush pending data.
+ *
+ * @param slot_id Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_Finalize(uint32_t slot_id);
+
+/**
+ * @brief Read a fragment from the indicated storage location.
+ * @details The function will read until the buffer is full or the end of
+ *          the storage location has been reached. The actual amount of
+ *          bytes read is set in the buffer struct.
+ *
+ * @param slot_id Storage location ID.
+ * @param offset Offset in bytes to read from.
+ * @param buffer Pointer to buffer struct to store fragment. buffer->size
+ *        contains the intended read size.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ *         buffer->size contains actual bytes read on return.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_Read(uint32_t slot_id,
+                                           uint32_t offset,
+                                           arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Set the firmware image in the slot to be the new active image.
+ * @details This call is responsible for initiating the process for
+ *          applying a new/different image. Depending on the platform this
+ *          could be:
+ *           * An empty call, if the installer can deduce which slot to
+ *             choose from based on the firmware details.
+ *           * Setting a flag to indicate which slot to use next.
+ *           * Decompressing/decrypting/installing the firmware image on
+ *             top of another.
+ *
+ * @param slot_id Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_Activate(uint32_t slot_id);
+
+/**
+ * @brief Get firmware details for the firmware image in the slot passed.
+ * @details This call populates the passed details struct with information
+ *          about the firmware image in the slot passed. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param slot_id Storage location ID.
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_BlockDevice_GetFirmwareDetails(
+                                        uint32_t slot_id,
+                                        arm_uc_firmware_details_t* details);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ARM_UC_PAL_BLOCKDEVICE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-blockdevice/update-client-pal-blockdevice/arm_uc_pal_blockdevice_platform.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,93 @@
+//----------------------------------------------------------------------------
+//   The confidential and proprietary information contained in this file may
+//   only be used by a person authorised under and to the extent permitted
+//   by a subsisting licensing agreement from ARM Limited or its affiliates.
+//
+//          (C) COPYRIGHT 2017 ARM Limited or its affiliates.
+//              ALL RIGHTS RESERVED
+//
+//   This entire notice must be reproduced on all copies of this file
+//   and copies of this file may only be made by a person if such person is
+//   permitted to do so under the terms of a subsisting license agreement
+//   from ARM Limited or its affiliates.
+//----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_BLOCKDEVICE_PLATFORM_H
+#define ARM_UC_PAL_BLOCKDEVICE_PLATFORM_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+    ARM_UC_BLOCKDEVICE_SUCCESS = 0,
+    ARM_UC_BLOCKDEVICE_FAIL    = -1
+};
+
+#define ARM_UC_BLOCKDEVICE_INVALID_SIZE 0xFFFFFFFF
+
+/** Initialize a block device
+ *
+ *  @return         0 on success or a negative error code on failure
+ */
+int32_t arm_uc_blockdevice_init(void);
+
+/** Erase blocks on a block device
+ *
+ *  The state of an erased block is undefined until it has been programmed
+ *
+ *  @param address  Address of block to begin erasing
+ *  @param size     Size to erase in bytes, must be a multiple of erase block size
+ *  @return         0 on success, negative error code on failure
+ */
+int32_t arm_uc_blockdevice_erase(uint64_t address, uint64_t size);
+
+/** Program blocks to a block device
+ *
+ *  The blocks must have been erased prior to being programmed
+ *
+ *  If a failure occurs, it is not possible to determine how many bytes succeeded
+ *
+ *  @param buffer   Buffer of data to write to blocks
+ *  @param address  Address of block to begin writing to
+ *  @param size     Size to write in bytes, must be a multiple of program block size
+ *  @return         0 on success, negative error code on failure
+ */
+int32_t arm_uc_blockdevice_program(const uint8_t* buffer,
+                                   uint64_t address,
+                                   uint32_t size);
+
+/** Read blocks from a block device
+ *
+ *  If a failure occurs, it is not possible to determine how many bytes succeeded
+ *
+ *  @param buffer   Buffer to write blocks to
+ *  @param address  Address of block to begin reading from
+ *  @param size     Size to read in bytes, must be a multiple of read block size
+ *  @return         0 on success, negative error code on failure
+ */
+int32_t arm_uc_blockdevice_read(uint8_t* buffer,
+                                uint64_t address,
+                                uint32_t size);
+
+/** Get the size of a programable block
+ *
+ *  @return         Size of a programable block in bytes
+ *  @note Must be a multiple of the read size
+ */
+uint32_t arm_uc_blockdevice_get_program_size(void);
+
+/** Get the size of a eraseable block
+ *
+ *  @return         Size of a eraseable block in bytes
+ *  @note Must be a multiple of the program size
+ */
+uint32_t arm_uc_blockdevice_get_erase_size(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ARM_UC_PAL_BLOCKDEVICE_PLATFORM_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,166 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/source/arm_uc_paal_classic_pal.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,583 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+#include "update-client-pal-filesystem/arm_uc_pal_extensions.h"
+#include "update-client-common/arm_uc_utilities.h"
+#include "update-client-common/arm_uc_metadata_header_v2.h"
+#include "arm_uc_pal_filesystem_utils.h"
+
+#include "pal.h"
+
+#include "mbed-trace/mbed_trace.h"
+#define TRACE_GROUP "UCPI"
+
+#include <stdio.h>
+
+#define ARM_UC_FIRMWARE_FOLDER_NAME "firmware"
+
+/* pointer to external callback handler */
+static ARM_UC_PAAL_UPDATE_SignalEvent_t arm_uc_pal_external_callback = NULL;
+
+static void arm_uc_pal_classic_signal_callback(uint32_t event)
+{
+    if (arm_uc_pal_external_callback)
+    {
+        arm_uc_pal_external_callback(event);
+    }
+}
+
+static void arm_uc_pal_classic_callback(palImageEvents_t event)
+{
+    /*
+        ARM_UC_PAAL_EVENT_INITIALIZE_DONE,
+        ARM_UC_PAAL_EVENT_PREPARE_DONE,
+        ARM_UC_PAAL_EVENT_WRITE_DONE,
+        ARM_UC_PAAL_EVENT_FINALIZE_DONE,
+        ARM_UC_PAAL_EVENT_READ_DONE,
+        ARM_UC_PAAL_EVENT_ACTIVATE_DONE,
+        ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE,
+        ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE,
+        ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE,
+        ARM_UC_PAAL_EVENT_INITIALIZE_ERROR,
+        ARM_UC_PAAL_EVENT_PREPARE_ERROR,
+        ARM_UC_PAAL_EVENT_WRITE_ERROR,
+        ARM_UC_PAAL_EVENT_FINALIZE_ERROR,
+        ARM_UC_PAAL_EVENT_READ_ERROR,
+        ARM_UC_PAAL_EVENT_ACTIVATE_ERROR,
+        ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_ERROR,
+        ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_ERROR,
+        ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_ERROR,
+    */
+    tr_debug("arm_uc_pal_classic_callback");
+
+    switch (event)
+    {
+        case PAL_IMAGE_EVENT_INIT:
+            arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_INITIALIZE_DONE);
+            break;
+        case PAL_IMAGE_EVENT_PREPARE:
+            arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_PREPARE_DONE);
+            break;
+        case PAL_IMAGE_EVENT_WRITE:
+            arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_WRITE_DONE);
+            break;
+        case PAL_IMAGE_EVENT_FINALIZE:
+            arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_FINALIZE_DONE);
+            break;
+        case PAL_IMAGE_EVENT_READTOBUFFER:
+            arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_READ_DONE);
+            break;
+        case PAL_IMAGE_EVENT_ACTIVATE:
+            arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_ACTIVATE_DONE);
+            break;
+        default:
+            break;
+    }
+}
+
+/**
+ * @brief Initialize the underlying storage and set the callback handler.
+ *
+ * @param callback Function pointer to event handler.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_Classic_PAL_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (callback)
+    {
+        palStatus_t status1 = pal_imageInitAPI(arm_uc_pal_classic_callback);
+        arm_uc_error_t status2 = pal_ext_imageInitAPI(arm_uc_pal_classic_signal_callback);
+
+        if ((status1 == PAL_SUCCESS) && (status2.error == ERR_NONE))
+        {
+            arm_uc_pal_external_callback = callback;
+            arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_INITIALIZE_DONE);
+
+            result.code = ERR_NONE;
+        }
+        else
+        {
+            result.code = ERR_NOT_READY;
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get a bitmap indicating supported features.
+ * @details The bitmap is used in conjunction with the firmware and
+ *          installer details struct to indicate what fields are supported
+ *          and which values are valid.
+ *
+ * @return Capability bitmap.
+ */
+ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UC_Classic_PAL_GetCapabilities(void)
+{
+    ARM_UC_PAAL_UPDATE_CAPABILITIES result = {
+        .installer_arm_hash = 0,
+        .installer_oem_hash = 0,
+        .installer_layout   = 0,
+        .firmware_hash      = 1,
+        .firmware_hmac      = 0,
+        .firmware_campaign  = 0,
+        .firmware_version   = 1,
+        .firmware_size      = 1
+    };
+
+    return result;
+}
+
+/**
+ * @brief Get maximum number of supported storage locations.
+ *
+ * @return Number of storage locations.
+ */
+uint32_t ARM_UC_Classic_PAL_GetMaxID(void)
+{
+    return 1;
+}
+
+/**
+ * @brief Prepare the storage layer for a new firmware image.
+ * @details The storage location is set up to receive an image with
+ *          the details passed in the details struct.
+ *
+ * @param location Storage location ID.
+ * @param details Pointer to a struct with firmware details.
+ * @param buffer Temporary buffer for formatting and storing metadata.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_Classic_PAL_Prepare(uint32_t location,
+                                          const arm_uc_firmware_details_t* details,
+                                          arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details && buffer)
+    {
+        /* encode firmware details in buffer */
+        arm_uc_error_t header_status = arm_uc_create_external_header_v2(details,
+                                                                        buffer);
+
+        if (header_status.error == ERR_NONE)
+        {
+            /* format file name and path */
+            char file_path[PAL_MAX_FILE_AND_FOLDER_LENGTH] = { 0 };
+
+            result = arm_uc_pal_filesystem_get_path(location,
+                                                    FIRMWARE_IMAGE_ITEM_HEADER,
+                                                    file_path,
+                                                    PAL_MAX_FILE_AND_FOLDER_LENGTH);
+
+            if (result.code == ERR_NONE)
+            {
+                tr_debug("file_path: %s", file_path);
+
+                palFileDescriptor_t file = 0;
+
+                /* open file and get file handler */
+                palStatus_t status = pal_fsFopen(file_path,
+                                                 PAL_FS_FLAG_READWRITETRUNC,
+                                                 &file);
+
+                if (status == PAL_SUCCESS)
+                {
+                    size_t xfer_size = 0;
+
+                    /* write buffer to file */
+                    status = pal_fsFwrite(&file,
+                                          buffer->ptr,
+                                          buffer->size,
+                                          &xfer_size);
+
+                    tr_debug("written: %lu", (unsigned long)xfer_size);
+
+                    /* call event hadnler and set return code if write was successful */
+                    if ((status == PAL_SUCCESS) &&
+                        (xfer_size == buffer->size))
+                    {
+                        result.code = ERR_NONE;
+
+                        arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_PREPARE_DONE);
+                    }
+
+                    /* close file after write */
+                    status = pal_fsFclose(&file);
+
+                    if (status != PAL_SUCCESS)
+                    {
+                        tr_error("pal_fsFclose failed: %" PRId32, status);
+                    }
+                }
+                else
+                {
+                    tr_error("pal_fsFopen failed: %" PRId32, status);
+                }
+            }
+            else
+            {
+                tr_error("file name and path too long");
+            }
+        }
+        else
+        {
+            tr_error("header too large for buffer");
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Write a fragment to the indicated storage location.
+ * @details The storage location must have been allocated using the Prepare
+ *          call. The call is expected to write the entire fragment before
+ *          signaling completion.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to where the fragment should be written.
+ * @param buffer Pointer to buffer struct with fragment.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_Classic_PAL_Write(uint32_t location,
+                                        uint32_t offset,
+                                        const arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (buffer)
+    {
+        palStatus_t status = pal_imageWrite(location,
+                                            offset,
+                                            (palConstBuffer_t*) buffer);
+
+        if (status == PAL_SUCCESS)
+        {
+            result.code = ERR_NONE;
+        }
+        else
+        {
+            result.code = ERR_NOT_READY;
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Close storage location for writing and flush pending data.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_Classic_PAL_Finalize(uint32_t location)
+{
+    arm_uc_error_t result = { .code = ERR_NOT_READY };
+
+    palStatus_t status = pal_imageFinalize(location);
+
+    if (status == PAL_SUCCESS)
+    {
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Read a fragment from the indicated storage location.
+ * @details The function will read until the buffer is full or the end of
+ *          the storage location has been reached. The actual amount of
+ *          bytes read is set in the buffer struct.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to read from.
+ * @param buffer Pointer to buffer struct to store fragment. buffer->size
+ *        contains the intended read size.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ *         buffer->size contains actual bytes read on return.
+ */
+arm_uc_error_t ARM_UC_Classic_PAL_Read(uint32_t location,
+                                       uint32_t offset,
+                                       arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (buffer)
+    {
+        palStatus_t status = pal_imageReadToBuffer(location,
+                                                   offset,
+                                                   (palBuffer_t*) buffer);
+
+        if (status == PAL_SUCCESS)
+        {
+            tr_debug("pal_imageReadToBuffer succeeded: %" PRIX32, buffer->size);
+            result.code = ERR_NONE;
+        }
+        else
+        {
+            tr_error("pal_imageReadToBuffer failed");
+            result.code = ERR_NOT_READY;
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set the firmware image in the slot to be the new active image.
+ * @details This call is responsible for initiating the process for
+ *          applying a new/different image. Depending on the platform this
+ *          could be:
+ *           * An empty call, if the installer can deduce which slot to
+ *             choose from based on the firmware details.
+ *           * Setting a flag to indicate which slot to use next.
+ *           * Decompressing/decrypting/installing the firmware image on
+ *             top of another.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_Classic_PAL_Activate(uint32_t location)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    result = pal_ext_imageActivate(location);
+
+    return result;
+}
+
+/**
+ * @brief Get firmware details for the actively running firmware.
+ * @details This call populates the passed details struct with information
+ *          about the currently active firmware image. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_Classic_PAL_GetActiveFirmwareDetails(arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        result = pal_ext_imageGetActiveDetails(details);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get firmware details for the firmware image in the slot passed.
+ * @details This call populates the passed details struct with information
+ *          about the firmware image in the slot passed. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_Classic_PAL_GetFirmwareDetails(uint32_t location,
+                                                     arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        char file_path[PAL_MAX_FILE_AND_FOLDER_LENGTH+1] = { 0 };
+
+        palStatus_t status = pal_fsGetMountPoint(PAL_FS_PARTITION_PRIMARY,
+                                                 PAL_MAX_FILE_AND_FOLDER_LENGTH,
+                                                 file_path);
+
+        if (status == PAL_SUCCESS)
+        {
+            /* keep track of file and folder length */
+            /* add mount point name length */
+            int length = arm_uc_strnlen((const uint8_t *)file_path, PAL_MAX_FILE_AND_FOLDER_LENGTH);
+
+            /* add slash if needed */
+            if (( length == 0) || 
+                ((length < PAL_MAX_FILE_AND_FOLDER_LENGTH) &&
+                    (file_path[length - 1] != '/')))
+            {
+                file_path[length] = '/';
+                file_path[++length] = 0;
+            }
+            
+
+            /* check that path didn't overrun */
+            if (length < PAL_MAX_FILE_AND_FOLDER_LENGTH)
+            {
+                /* start snprintf after the mount point name and add length */
+                length += snprintf(&file_path[length],
+                                   PAL_MAX_FILE_AND_FOLDER_LENGTH - length,
+                                   ARM_UC_FIRMWARE_FOLDER_NAME "/header_%" PRIu32 ".bin",
+                                   location);
+
+                /* check that file path didn't overrun */
+                if (length < PAL_MAX_FILE_AND_FOLDER_LENGTH)
+                {
+                    tr_debug("file_path: %d %s", length, file_path);
+
+                    palFileDescriptor_t file = 0;
+
+                    /* open metadata header file if it exists */
+                    palStatus_t pal_rc = pal_fsFopen(file_path,
+                                                     PAL_FS_FLAG_READONLY,
+                                                     &file);
+
+                    if (pal_rc == PAL_SUCCESS)
+                    {
+                        size_t xfer_size = 0;
+
+                        /* read metadata header */
+                        uint8_t read_buffer[ARM_UC_EXTERNAL_HEADER_SIZE_V2] = { 0 };
+
+                        pal_rc = pal_fsFread(&file,
+                                             read_buffer,
+                                             ARM_UC_EXTERNAL_HEADER_SIZE_V2,
+                                             &xfer_size);
+
+                        /* check return code */
+                        if ((pal_rc == PAL_SUCCESS) &&
+                            (xfer_size == ARM_UC_EXTERNAL_HEADER_SIZE_V2))
+                        {
+                            tr_debug("read bytes: %lu", (unsigned long)xfer_size);
+
+                            /* read out header magic */
+                            uint32_t headerMagic = arm_uc_parse_uint32(&read_buffer[0]);
+
+                            /* read out header magic */
+                            uint32_t headerVersion = arm_uc_parse_uint32(&read_buffer[4]);
+
+                            /* choose version to decode */
+                            if ((headerMagic == ARM_UC_EXTERNAL_HEADER_MAGIC_V2) &&
+                                (headerVersion == ARM_UC_EXTERNAL_HEADER_VERSION_V2))
+                            {
+                                result = arm_uc_parse_external_header_v2(read_buffer, details);
+
+                                tr_debug("version: %" PRIu64, details->version);
+                                tr_debug("size: %"PRIu64, details->size);
+
+                                if (result.error == ERR_NONE)
+                                {
+                                    arm_uc_pal_classic_signal_callback(ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE);
+                                }
+                            }
+                            else
+                            {
+                                /* invalid header format */
+                                tr_error("invalid header in slot %" PRIu32, location);
+                            }
+                        }
+                        else if (xfer_size != ARM_UC_EXTERNAL_HEADER_SIZE_V2)
+                        {
+                            /* invalid header format */
+                            tr_error("invalid header in slot %" PRIu32, location);
+                        }
+                        else
+                        {
+                            /* unsuccessful read */
+                            tr_error("pal_fsFread returned 0x%" PRIX32, (uint32_t) pal_rc);
+                        }
+
+                        /* close file after use */
+                        pal_rc = pal_fsFclose(&file);
+
+                        if (pal_rc != PAL_SUCCESS)
+                        {
+                            tr_error("pal_fsFclose failed: %" PRId32, pal_rc);
+                        }
+                    }
+                    else
+                    {
+                        /* header file not present, slot is either invalid or unused. */
+                        result.code = ERR_NOT_READY;
+                    }
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get details for the component responsible for installation.
+ * @details This call populates the passed details struct with information
+ *          about the local installer. Only the fields marked as supported
+ *          in the capabilities bitmap will have valid values. The
+ *          installer could be the bootloader, a recovery image, or some
+ *          other component responsible for applying the new firmware
+ *          image.
+ *
+ * @param details Pointer to installer details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_Classic_PAL_GetInstallerDetails(arm_uc_installer_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        result = pal_ext_installerGetDetails(details);
+    }
+
+    return result;
+}
+
+const ARM_UC_PAAL_UPDATE ARM_UCP_FILESYSTEM =
+{
+    .Initialize                 = ARM_UC_Classic_PAL_Initialize,
+    .GetCapabilities            = ARM_UC_Classic_PAL_GetCapabilities,
+    .GetMaxID                   = ARM_UC_Classic_PAL_GetMaxID,
+    .Prepare                    = ARM_UC_Classic_PAL_Prepare,
+    .Write                      = ARM_UC_Classic_PAL_Write,
+    .Finalize                   = ARM_UC_Classic_PAL_Finalize,
+    .Read                       = ARM_UC_Classic_PAL_Read,
+    .Activate                   = ARM_UC_Classic_PAL_Activate,
+    .GetActiveFirmwareDetails   = ARM_UC_Classic_PAL_GetActiveFirmwareDetails,
+    .GetFirmwareDetails         = ARM_UC_Classic_PAL_GetFirmwareDetails,
+    .GetInstallerDetails        = ARM_UC_Classic_PAL_GetInstallerDetails
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/source/arm_uc_pal_filesystem_utils.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,82 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "arm_uc_pal_filesystem_utils.h"
+#include "update-client-common/arm_uc_utilities.h"
+
+#include "pal.h"
+
+#include "mbed-trace/mbed_trace.h"
+#define TRACE_GROUP "UCPI"
+
+#include <stdio.h>
+
+/**
+ * @brief Get the path of the specified item (header or file) for a firmware image
+ * @details This call populates the passed details struct with information
+ *          about the firmware image in the slot passed. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param location Index of the firmware image in storage.
+ * @param what 'FIRMWARE_IMAGE_ITEM_HEADER' to return the path to the image
+ *        header, or 'FIRMWARE_IMAGE_ITEM_DATA' to return the path to the
+ *        actual image data.
+ * @param dest Where to write the path.
+ * @param dest_size Size of the 'dest' array above. It should be at least
+ *        PAL_MAX_FILE_AND_FOLDER_LENGTH.
+ * @return ERR_INVALID_PARAMETER if an error occured, ERR_NONE otherwise.
+ */
+arm_uc_error_t arm_uc_pal_filesystem_get_path(uint32_t location,
+                                              firmwareImageItemType what,
+                                              char *dest,
+                                              uint32_t dest_size)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (dest && dest_size > 0)
+    {
+        /* copy the base directory of firmware into dest */
+        int length = snprintf(dest, dest_size, "%s", pal_imageGetFolder());
+
+        if (length > 0)
+        {
+            /* add missing slash at end if needed */
+            if (((uint32_t)length < dest_size) && (dest[length - 1] != '/'))
+            {
+                dest[length] = '/';
+                length++;
+            }
+
+            /* start snprintf after the mount point name and add length */
+            length += snprintf(&dest[length],
+                               dest_size - length,
+                               "%s_%" PRIu32 ".bin",
+                               what == FIRMWARE_IMAGE_ITEM_HEADER ? "header" : "image",
+                               location);
+
+            /* check that file path didn't overrun */
+            if ((uint32_t)length < dest_size)
+            {
+                result.code = ERR_NONE;
+            }
+        }
+    }
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/source/arm_uc_pal_filesystem_utils.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,40 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_FILESYSTEM_UTILS
+#define ARM_UC_PAL_FILESYSTEM_UTILS
+
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+   FIRMWARE_IMAGE_ITEM_HEADER = 0,
+   FIRMWARE_IMAGE_ITEM_DATA
+} firmwareImageItemType;
+
+arm_uc_error_t arm_uc_pal_filesystem_get_path(uint32_t location, firmwareImageItemType what, char *dest, uint32_t dest_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ARM_UC_PAL_FILESYSTEM_UTILS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/source/arm_uc_pal_linux_extensions.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,177 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(TARGET_IS_PC_LINUX)
+
+#include "update-client-pal-filesystem/arm_uc_pal_extensions.h"
+
+#include "update-client-common/arm_uc_metadata_header_v2.h"
+#include "update-client-common/arm_uc_types.h"
+#include "update-client-common/arm_uc_utilities.h"
+#include "arm_uc_pal_filesystem_utils.h"
+
+#include "pal.h"
+
+#include "mbed-trace/mbed_trace.h"
+#define TRACE_GROUP "update-client-extensions"
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+
+#ifndef MBED_CONF_UPDATE_CLIENT_APPLICATION_DETAILS
+#define MBED_CONF_UPDATE_CLIENT_APPLICATION_DETAILS 0
+#endif
+
+#ifndef MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS
+#define MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS 0
+#endif
+
+static void (*arm_ucex_linux_callback)(uint32_t) = NULL;
+static palImageId_t arm_ucex_activate_image_id;
+
+#ifndef PAL_UPDATE_ACTIVATE_SCRIPT
+#define PAL_UPDATE_ACTIVATE_SCRIPT "./activate_script"
+#endif
+
+arm_uc_error_t pal_ext_imageInitAPI(void (*callback)(uint32_t))
+{
+    arm_uc_error_t result = { .code = ERR_NONE };
+
+    arm_ucex_linux_callback = callback;
+
+    return result;
+}
+
+arm_uc_error_t pal_ext_imageGetActiveDetails(arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        /* dummy implementation, return 0 */
+        memset(details, 0, sizeof(arm_uc_firmware_details_t));
+
+        result.code = ERR_NONE;
+
+        if (arm_ucex_linux_callback)
+        {
+            arm_ucex_linux_callback(ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE);
+        }
+    }
+
+    return result;
+}
+
+arm_uc_error_t pal_ext_installerGetDetails(arm_uc_installer_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        /* dummy implementation, return 0 */
+        memset(details, 0, sizeof(arm_uc_installer_details_t));
+
+        result.code = ERR_NONE;
+
+        if (arm_ucex_linux_callback)
+        {
+            arm_ucex_linux_callback(ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE);
+        }
+    }
+
+    return result;
+}
+
+static void pal_ext_imageActivationWorker(void* location)
+{
+    char cmd_buf[sizeof(PAL_UPDATE_ACTIVATE_SCRIPT) + 1 + PAL_MAX_FILE_AND_FOLDER_LENGTH + 1];
+    char path_buf[PAL_MAX_FILE_AND_FOLDER_LENGTH];
+
+    arm_uc_error_t result = arm_uc_pal_filesystem_get_path(*(palImageId_t*)location, FIRMWARE_IMAGE_ITEM_DATA,
+                                                           path_buf, PAL_MAX_FILE_AND_FOLDER_LENGTH);
+    palStatus_t rc = PAL_ERR_GENERIC_FAILURE;
+
+    if (result.code == ERR_NONE)
+    {
+        int err = snprintf(cmd_buf, sizeof(cmd_buf), "%s %s",
+                           PAL_UPDATE_ACTIVATE_SCRIPT, path_buf);
+        if (err > 0)
+        {
+            rc = PAL_SUCCESS;
+        }
+        else
+        {
+            tr_err("snprintf failed with err %i", err);
+            rc = PAL_ERR_GENERIC_FAILURE;
+        }
+    }
+
+
+    if (rc == PAL_SUCCESS)
+    {
+        tr_debug("Activate by executing %s", cmd_buf);
+        int err = system(cmd_buf);
+        err = WEXITSTATUS(err);
+
+        if (err != -1)
+        {
+            tr_debug("Activate completed with %" PRId32, err);
+            rc = PAL_SUCCESS;
+        }
+        else
+        {
+            tr_err("system call failed with err %" PRId32, err);
+            rc = PAL_ERR_GENERIC_FAILURE;
+        }
+    }
+    fflush(stdout);
+    sleep(1);
+
+    if (arm_ucex_linux_callback)
+    {
+        uint32_t event = (rc == PAL_SUCCESS? ARM_UC_PAAL_EVENT_ACTIVATE_DONE : ARM_UC_PAAL_EVENT_ACTIVATE_ERROR);
+        arm_ucex_linux_callback(event);
+    }
+}
+
+arm_uc_error_t pal_ext_imageActivate(uint32_t location)
+{
+    arm_uc_error_t err = { .code = ERR_INVALID_PARAMETER };
+
+    memcpy(&arm_ucex_activate_image_id, &location, sizeof(palImageId_t));
+
+    palThreadID_t thread_id = 0;
+    palStatus_t rc = pal_osThreadCreateWithAlloc(pal_ext_imageActivationWorker, &arm_ucex_activate_image_id,
+                                                 PAL_osPriorityBelowNormal, PTHREAD_STACK_MIN, NULL, &thread_id);
+    if (rc != PAL_SUCCESS)
+    {
+        tr_err("Thread creation failed with %x", rc);
+        err.code = ERR_INVALID_PARAMETER;
+    }
+    else
+    {
+        tr_debug("Activation thread created, thread ID: %" PRIu32, thread_id);
+        err.code = ERR_NONE;
+    }
+
+    return err;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/source/arm_uc_pal_mbed_extensions.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,54 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(TARGET_LIKE_MBED)
+
+#include "update-client-pal-filesystem/arm_uc_pal_extensions.h"
+
+#include "update-client-pal-flashiap/arm_uc_pal_flashiap_implementation.h"
+
+static void (*arm_ucex_mbed_callback)(uint32_t) = 0;
+
+arm_uc_error_t pal_ext_imageInitAPI(void (*callback)(uint32_t))
+{
+    arm_ucex_mbed_callback = callback;
+
+    return ARM_UC_PAL_FlashIAP_Initialize(callback);
+}
+
+arm_uc_error_t pal_ext_imageGetActiveDetails(arm_uc_firmware_details_t* details)
+{
+    return ARM_UC_PAL_FlashIAP_GetActiveDetails(details);
+}
+
+arm_uc_error_t pal_ext_installerGetDetails(arm_uc_installer_details_t* details)
+{
+    return ARM_UC_PAL_FlashIAP_GetInstallerDetails(details);
+}
+
+arm_uc_error_t pal_ext_imageActivate(uint32_t location)
+{
+    arm_uc_error_t result = { .code = ERR_NONE };
+
+    /* pal_imageActivate not implemented */
+    arm_ucex_mbed_callback(ARM_UC_PAAL_EVENT_ACTIVATE_DONE);
+
+    return result;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/update-client-pal-filesystem/arm_uc_pal_extensions.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,42 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_EXTENSIONS
+#define ARM_UC_PAL_EXTENSIONS
+
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_types.h"
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+arm_uc_error_t pal_ext_imageInitAPI(ARM_UC_PAAL_UPDATE_SignalEvent_t callback);
+
+arm_uc_error_t pal_ext_imageGetActiveDetails(arm_uc_firmware_details_t* details);
+
+arm_uc_error_t pal_ext_installerGetDetails(arm_uc_installer_details_t* details);
+
+arm_uc_error_t pal_ext_imageActivate(uint32_t location);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ARM_UC_PAL_EXTENSIONS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-filesystem/update-client-pal-filesystem/arm_uc_pal_filesystem.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,26 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_CLASSIC_H
+#define ARM_UC_PAL_CLASSIC_H
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+extern ARM_UC_PAAL_UPDATE ARM_UCP_FILESYSTEM;
+
+#endif // ARM_UC_PAL_CLASSIC_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,166 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/source/arm_uc_pal_flashiap.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,52 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+#include "update-client-pal-flashiap/arm_uc_pal_flashiap_implementation.h"
+
+ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UC_PAL_FlashIAP_GetCapabilities(void)
+{
+    ARM_UC_PAAL_UPDATE_CAPABILITIES result = {
+        .installer_arm_hash = 0,
+        .installer_oem_hash = 0,
+        .installer_layout   = 0,
+        .firmware_hash      = 1,
+        .firmware_hmac      = 0,
+        .firmware_campaign  = 0,
+        .firmware_version   = 1,
+        .firmware_size      = 1
+    };
+
+    return result;
+}
+
+const ARM_UC_PAAL_UPDATE ARM_UCP_FLASHIAP =
+{
+    .Initialize                 = ARM_UC_PAL_FlashIAP_Initialize,
+    .GetCapabilities            = ARM_UC_PAL_FlashIAP_GetCapabilities,
+    .GetMaxID                   = ARM_UC_PAL_FlashIAP_GetMaxID,
+    .Prepare                    = ARM_UC_PAL_FlashIAP_Prepare,
+    .Write                      = ARM_UC_PAL_FlashIAP_Write,
+    .Finalize                   = ARM_UC_PAL_FlashIAP_Finalize,
+    .Read                       = ARM_UC_PAL_FlashIAP_Read,
+    .Activate                   = ARM_UC_PAL_FlashIAP_Activate,
+    .GetActiveFirmwareDetails   = ARM_UC_PAL_FlashIAP_GetActiveDetails,
+    .GetFirmwareDetails         = ARM_UC_PAL_FlashIAP_GetFirmwareDetails,
+    .GetInstallerDetails        = ARM_UC_PAL_FlashIAP_GetInstallerDetails
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/source/arm_uc_pal_flashiap_implementation.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,773 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(TARGET_LIKE_MBED)
+
+#define __STDC_FORMAT_MACROS
+
+#include "update-client-pal-flashiap/arm_uc_pal_flashiap.h"
+
+#include "update-client-pal-flashiap/arm_uc_pal_flashiap_platform.h"
+
+#include "update-client-common/arm_uc_metadata_header_v2.h"
+#include "update-client-common/arm_uc_types.h"
+#include "update-client-common/arm_uc_utilities.h"
+
+#define TRACE_GROUP "UCPI"
+#include "update-client-common/arm_uc_trace.h"
+#include <inttypes.h>
+#include <stddef.h>
+
+#ifndef MBED_CONF_UPDATE_CLIENT_APPLICATION_DETAILS
+#define MBED_CONF_UPDATE_CLIENT_APPLICATION_DETAILS 0
+#endif
+
+#ifndef MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS
+#define MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS 0
+#endif
+
+#ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS
+#define MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS 0
+#endif
+
+#ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE
+#define MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE 1
+#endif
+
+#ifndef MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS
+#define MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS 1
+#endif
+
+/* consistency check */
+#if (MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE == 0)
+#error Update client storage page cannot be zero.
+#endif
+
+#if (MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS == 0)
+#error Update client storage locations must be at least 1.
+#endif
+
+/* Check that the statically allocated buffers are aligned with the block size */
+#define ARM_UC_PAL_ONE_BUFFER (ARM_UC_BUFFER_SIZE / 2)
+#define ARM_UC_PAL_PAGES (ARM_UC_PAL_ONE_BUFFER / MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE)
+
+#if !((ARM_UC_PAL_PAGES * MBED_CONF_UPDATE_CLIENT_STORAGE_PAGE) == ARM_UC_PAL_ONE_BUFFER)
+#error Update client buffer must be divisible by the block page size
+#endif
+
+/* Use internal header format because we are using internal flash and
+   is assumed to be trusted */
+#define ARM_UC_PAL_HEADER_SIZE (uint32_t) ARM_UC_INTERNAL_HEADER_SIZE_V2
+
+static uint64_t arm_uc_pal_flashiap_firmware_size = 0;
+
+static void (*arm_uc_pal_flashiap_callback)(uint32_t) = NULL;
+
+static void arm_uc_pal_flashiap_signal_internal(uint32_t event)
+{
+    if (arm_uc_pal_flashiap_callback)
+    {
+        arm_uc_pal_flashiap_callback(event);
+    }
+}
+
+/**
+ * @brief Align address up/down to sector boundary
+ *
+ * @param addr The address that need to be rounded up
+ * @param round_down if the value is 1, will align down to sector
+                     boundary otherwise align up.
+ * @return Returns the address aligned to sector boundary
+ */
+static uint32_t arm_uc_pal_flashiap_align_to_sector(uint32_t addr, int8_t round_down)
+{
+    uint32_t sector_start_addr = arm_uc_flashiap_get_flash_start();
+
+    /* check the address is pointing to internal flash */
+    if ((addr > sector_start_addr + arm_uc_flashiap_get_flash_size()) ||
+        (addr < sector_start_addr))
+    {
+        return ARM_UC_FLASH_INVALID_SIZE;
+    }
+
+    /* add sectors from start of flash until exeeced the required address
+       we cannot assume uniform sector size as in some mcu sectors have
+       drastically different sizes */
+    uint32_t sector_size = ARM_UC_FLASH_INVALID_SIZE;
+    while(sector_start_addr < addr)
+    {
+        sector_size = arm_uc_flashiap_get_sector_size(sector_start_addr);
+        if (sector_size != ARM_UC_FLASH_INVALID_SIZE)
+        {
+            sector_start_addr += sector_size;
+        }
+        else
+        {
+            return ARM_UC_FLASH_INVALID_SIZE;
+        }
+    }
+
+    /* if round down to nearest section, remove the last sector from addr */
+    if (round_down != 0 && sector_start_addr > addr)
+    {
+        sector_start_addr -= sector_size;
+    }
+
+    return sector_start_addr;
+}
+
+/**
+ * @brief Round size up to nearest page
+ *
+ * @param size The size that need to be rounded up
+ * @return Returns the size rounded up to the nearest page
+ */
+static uint32_t arm_uc_pal_flashiap_round_up_to_page_size(uint32_t size)
+{
+    uint32_t page_size = arm_uc_flashiap_get_page_size();
+
+    if (size != 0)
+    {
+        size = ((size - 1)/page_size + 1) * page_size;
+    }
+
+    return size;
+}
+
+/**
+ * @brief Get the physicl slot address and size given slot_id
+ *
+ * @param slot_id Storage location ID.
+ * @param slot_addr the slot address is returned in this pointer
+ * @param slot_size the slot size is returned in this pointer
+ * @return Returns ERR_NONE on success.
+ *         Returns ERR_INVALID_PARAMETER on error.
+ */
+static arm_uc_error_t arm_uc_pal_flashiap_get_slot_addr_size(uint32_t slot_id,
+                                                             uint32_t* slot_addr,
+                                                             uint32_t* slot_size)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+    /* find the start address of the whole storage area. It needs to be aligned to
+       sector boundary and we cannot go outside user defined storage area, hence
+       rounding up to sector boundary */
+    uint32_t storage_start_addr = arm_uc_pal_flashiap_align_to_sector(
+                                    MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS, 0);
+    /* find the end address of the whole storage area. It needs to be aligned to
+       sector boundary and we cannot go outside user defined storage area, hence
+       rounding down to sector boundary */
+    uint32_t storage_end_addr = arm_uc_pal_flashiap_align_to_sector(
+                                    MBED_CONF_UPDATE_CLIENT_STORAGE_ADDRESS + \
+                                    MBED_CONF_UPDATE_CLIENT_STORAGE_SIZE, 1);
+    /* find the maximum size each slot can have given the start and end, without
+       considering the alignment of individual slots */
+    uint32_t max_slot_size = (storage_end_addr - storage_start_addr) / \
+                                    MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS;
+    /* find the start address of slot. It needs to align to sector boundary. We
+       choose here to round down at each slot boundary */
+    uint32_t slot_start_addr = arm_uc_pal_flashiap_align_to_sector(
+                                    storage_start_addr + \
+                                    slot_id * max_slot_size, 1);
+    /* find the end address of the slot, rounding down to sector boundary same as
+       the slot start address so that we make sure two slot don't overlap */
+    uint32_t slot_end_addr = arm_uc_pal_flashiap_align_to_sector(
+                                    slot_start_addr + \
+                                    max_slot_size, 1);
+
+    /* Any calculation above might result in an invalid address. */
+    if ((storage_start_addr == ARM_UC_FLASH_INVALID_SIZE) ||
+        (storage_end_addr == ARM_UC_FLASH_INVALID_SIZE) ||
+        (slot_start_addr == ARM_UC_FLASH_INVALID_SIZE) ||
+        (slot_end_addr == ARM_UC_FLASH_INVALID_SIZE) ||
+        (slot_id >= MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS))
+    {
+        UC_PAAL_ERR_MSG("Aligning fw storage slot to erase sector failed"
+                " storage_start_addr %" PRIX32 " slot_start_addr %" PRIX32
+                " max_slot_size %" PRIX32, storage_start_addr, slot_start_addr,
+                max_slot_size);
+        *slot_addr = ARM_UC_FLASH_INVALID_SIZE;
+        *slot_size = ARM_UC_FLASH_INVALID_SIZE;
+    }
+    else
+    {
+        *slot_addr = slot_start_addr;
+        *slot_size = slot_end_addr - slot_start_addr;
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Initialise the flash IAP API
+ *
+ * @param callback function pointer to the PAAL event handler
+ * @return Returns ERR_NONE on success.
+ *         Returns ERR_INVALID_PARAMETER on error.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_Initialize(void (*callback)(uint32_t))
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    int32_t status = arm_uc_flashiap_init();
+
+    if (status == ARM_UC_FLASHIAP_SUCCESS)
+    {
+        arm_uc_pal_flashiap_callback = callback;
+        arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_INITIALIZE_DONE);
+
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get maximum number of supported storage locations.
+ *
+ * @return Number of storage locations.
+ */
+uint32_t ARM_UC_PAL_FlashIAP_GetMaxID(void)
+{
+    return MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS;
+}
+
+/**
+ * @brief Prepare the storage layer for a new firmware image.
+ * @details The storage location is set up to receive an image with
+ *          the details passed in the details struct.
+ *
+ * @param slot_id Storage location ID.
+ * @param details Pointer to a struct with firmware details.
+ * @param buffer Temporary buffer for formatting and storing metadata.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_Prepare(uint32_t slot_id,
+                                           const arm_uc_firmware_details_t* details,
+                                           arm_uc_buffer_t* buffer)
+{
+    UC_PAAL_TRACE("ARM_UC_PAL_FlashIAP_Prepare slot_id %" PRIu32 " details %p buffer %p",
+                  slot_id, details, buffer);
+
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+    uint32_t slot_addr = ARM_UC_FLASH_INVALID_SIZE;
+    uint32_t slot_size = ARM_UC_FLASH_INVALID_SIZE;
+    uint32_t erase_size = ARM_UC_FLASH_INVALID_SIZE;
+
+    /* validate input */
+    if (details && buffer && buffer->ptr && \
+        slot_id < MBED_CONF_UPDATE_CLIENT_STORAGE_LOCATIONS)
+    {
+        UC_PAAL_TRACE("FW size %" PRIu64, details->size);
+        result.error = ERR_NONE;
+    }
+    else
+    {
+        UC_PAAL_TRACE("Input validation failed");
+    }
+
+    /* calculate space for new firmware */
+    if (result.error == ERR_NONE)
+    {
+        /* find slot start address */
+        result = arm_uc_pal_flashiap_get_slot_addr_size(slot_id, &slot_addr, &slot_size);
+
+        /* find the amount of space that need to be erased */
+        erase_size = arm_uc_pal_flashiap_align_to_sector(
+                        slot_addr + \
+                        arm_uc_pal_flashiap_round_up_to_page_size(details->size) + \
+                        arm_uc_pal_flashiap_round_up_to_page_size(ARM_UC_PAL_HEADER_SIZE),
+                        0) - slot_addr;
+
+        if ((result.error == ERR_NONE) && (erase_size > slot_size))
+        {
+            result.code = ERR_INVALID_PARAMETER;
+            UC_PAAL_ERR_MSG("Firmware too large! required %" PRIX32 " available: %" PRIX32,
+                            erase_size, slot_size);
+        }
+    }
+
+    /* erase space for new firmware */
+    if (result.error == ERR_NONE)
+    {
+        uint32_t erase_addr = slot_addr;
+        while (erase_addr < slot_addr + erase_size)
+        {
+            uint32_t sector_size = arm_uc_flashiap_get_sector_size(erase_addr);
+            UC_PAAL_TRACE("erase: addr %" PRIX32 " size %" PRIX32,
+                          erase_addr, sector_size);
+            if (sector_size != ARM_UC_FLASH_INVALID_SIZE)
+            {
+                int32_t status = arm_uc_flashiap_erase(erase_addr, sector_size);
+                if (status == ARM_UC_FLASHIAP_SUCCESS)
+                {
+                    erase_addr += sector_size;
+                }
+                else
+                {
+                    UC_PAAL_ERR_MSG("Flash erase failed with status %" PRIi32, status);
+                    result.code = ERR_INVALID_PARAMETER;
+                    break;
+                }
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("Get sector size for addr %" PRIX32 " failed", erase_addr);
+                result.code = ERR_INVALID_PARAMETER;
+                break;
+            }
+        }
+    }
+
+    /* generate header blob */
+    if (result.error == ERR_NONE)
+    {
+        result  = arm_uc_create_internal_header_v2(details, buffer);
+        if (result.error != ERR_NONE)
+        {
+            UC_PAAL_ERR_MSG("arm_uc_create_internal_header_v2 failed");
+        }
+    }
+
+    /* write header blob */
+    if (result.error == ERR_NONE)
+    {
+        uint32_t hdr_size = arm_uc_pal_flashiap_round_up_to_page_size(ARM_UC_PAL_HEADER_SIZE);
+        UC_PAAL_TRACE("program: %" PRIX32 " %" PRIX32,
+                      slot_addr, hdr_size);
+
+        /* write header */
+        int32_t status = arm_uc_flashiap_program((const uint8_t*) buffer->ptr,
+                                                 slot_addr,
+                                                 hdr_size);
+        if (status != ARM_UC_FLASHIAP_SUCCESS)
+        {
+            /* set return code */
+            result.code = ERR_INVALID_PARAMETER;
+        }
+    }
+
+    if (result.error == ERR_NONE)
+    {
+        /* store firmware size in global */
+        arm_uc_pal_flashiap_firmware_size = details->size;
+
+        /* signal done */
+        arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_PREPARE_DONE);
+    }
+
+    return result;
+}
+
+/**
+ * @brief Write a fragment to the indicated storage location.
+ * @details The storage location must have been allocated using the Prepare
+ *          call. The call is expected to write the entire fragment before
+ *          signaling completion.
+ *
+ * @param slot_id Storage location ID.
+ * @param offset Offset in bytes to where the fragment should be written.
+ * @param buffer Pointer to buffer struct with fragment.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_Write(uint32_t slot_id,
+                                         uint32_t offset,
+                                         const arm_uc_buffer_t* buffer)
+{
+    /* find slot address and size */
+    uint32_t slot_addr = ARM_UC_FLASH_INVALID_SIZE;
+    uint32_t slot_size = ARM_UC_FLASH_INVALID_SIZE;
+    arm_uc_error_t result = arm_uc_pal_flashiap_get_slot_addr_size(slot_id,
+                                                                   &slot_addr,
+                                                                   &slot_size);
+
+    if (buffer && buffer->ptr && result.error == ERR_NONE)
+    {
+        UC_PAAL_TRACE("ARM_UC_PAL_FlashIAP_Write: %p %" PRIX32 " %" PRIX32 " %" PRIX32,
+                 buffer->ptr, buffer->size, slot_addr, offset);
+
+        /* set default error */
+        result.code = ERR_INVALID_PARAMETER;
+
+        /* find physical address of the write */
+        uint32_t page_size = arm_uc_flashiap_get_page_size();
+        uint32_t hdr_size = arm_uc_pal_flashiap_round_up_to_page_size(ARM_UC_PAL_HEADER_SIZE);
+        uint32_t physical_address = slot_addr + hdr_size + offset;
+        uint32_t write_size = buffer->size;
+
+        /* if last chunk, pad out to page_size aligned size */
+        if ((buffer->size % page_size != 0) &&
+            ((offset + buffer->size) >= arm_uc_pal_flashiap_firmware_size) &&
+            (arm_uc_pal_flashiap_round_up_to_page_size(buffer->size) <= buffer->size_max))
+        {
+            write_size = arm_uc_pal_flashiap_round_up_to_page_size(buffer->size);
+        }
+
+        /* check page alignment of the program address and size */
+        if ((write_size % page_size == 0) && (physical_address % page_size == 0))
+        {
+            UC_PAAL_TRACE("programming addr %" PRIX32 " size %" PRIX32,
+                          physical_address, write_size);
+            int status = arm_uc_flashiap_program((const uint8_t*) buffer->ptr,
+                                                 physical_address,
+                                                 write_size);
+            if (status != ARM_UC_FLASHIAP_SUCCESS)
+            {
+                UC_PAAL_ERR_MSG("arm_uc_flashiap_program failed");
+            }
+            else
+            {
+                result.code = ERR_NONE;
+                arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_WRITE_DONE);
+            }
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("program size %" PRIX32 " or address %" PRIX32
+                            " not aligned to page size %" PRIX32, buffer->size,
+                            physical_address, page_size);
+        }
+    }
+    else
+    {
+        result.code = ERR_INVALID_PARAMETER;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Close storage location for writing and flush pending data.
+ *
+ * @param slot_id Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_Finalize(uint32_t slot_id)
+{
+    arm_uc_error_t result = { .code = ERR_NONE };
+
+    UC_PAAL_TRACE("ARM_UC_PAL_FlashIAP_Finalize");
+
+    arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_FINALIZE_DONE);
+
+    return result;
+}
+
+/**
+ * @brief Read a fragment from the indicated storage location.
+ * @details The function will read until the buffer is full or the end of
+ *          the storage location has been reached. The actual amount of
+ *          bytes read is set in the buffer struct.
+ *
+ * @param slot_id Storage location ID.
+ * @param offset Offset in bytes to read from.
+ * @param buffer Pointer to buffer struct to store fragment. buffer->size
+ *        contains the intended read size.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ *         buffer->size contains actual bytes read on return.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_Read(uint32_t slot_id,
+                                        uint32_t offset,
+                                        arm_uc_buffer_t* buffer)
+{
+    /* find slot address and size */
+    uint32_t slot_addr = ARM_UC_FLASH_INVALID_SIZE;
+    uint32_t slot_size = ARM_UC_FLASH_INVALID_SIZE;
+    arm_uc_error_t result = arm_uc_pal_flashiap_get_slot_addr_size(slot_id,
+                                                                   &slot_addr,
+                                                                   &slot_size);
+
+    if (buffer && buffer->ptr && result.error == ERR_NONE)
+    {
+        UC_PAAL_TRACE("ARM_UC_PAL_FlashIAP_Read: %" PRIX32 " %" PRIX32 " %" PRIX32,
+                slot_id, offset, buffer->size);
+
+        /* find physical address of the read */
+        uint32_t read_size = buffer->size;
+        uint32_t hdr_size = arm_uc_pal_flashiap_round_up_to_page_size(ARM_UC_PAL_HEADER_SIZE);
+        uint32_t physical_address = slot_addr + hdr_size + offset;
+
+        UC_PAAL_TRACE("reading addr %" PRIX32 " size %" PRIX32,
+                      physical_address, read_size);
+
+        int status = arm_uc_flashiap_read(buffer->ptr,
+                                          physical_address,
+                                          read_size);
+
+        if (status == ARM_UC_FLASHIAP_SUCCESS)
+        {
+            result.code = ERR_NONE;
+            arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_READ_DONE);
+        }
+        else
+        {
+            result.code = ERR_INVALID_PARAMETER;
+            UC_PAAL_ERR_MSG("arm_uc_flashiap_read failed");
+        }
+    }
+    else
+    {
+        result.code = ERR_INVALID_PARAMETER;
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set the firmware image in the slot to be the new active image.
+ * @details This call is responsible for initiating the process for
+ *          applying a new/different image. Depending on the platform this
+ *          could be:
+ *           * An empty call, if the installer can deduce which slot to
+ *             choose from based on the firmware details.
+ *           * Setting a flag to indicate which slot to use next.
+ *           * Decompressing/decrypting/installing the firmware image on
+ *             top of another.
+ *
+ * @param slot_id Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_Activate(uint32_t slot_id)
+{
+    arm_uc_error_t result = { .code = ERR_NONE };
+
+    UC_PAAL_TRACE("ARM_UC_PAL_FlashIAP_Activate");
+
+    arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_ACTIVATE_DONE);
+
+    return result;
+}
+
+/**
+ * @brief Get firmware details for the firmware image in the slot passed.
+ * @details This call populates the passed details struct with information
+ *          about the firmware image in the slot passed. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_GetFirmwareDetails(
+                                        uint32_t slot_id,
+                                        arm_uc_firmware_details_t* details)
+{
+    UC_PAAL_TRACE("ARM_UC_PAL_FlashIAP_GetFirmwareDetails");
+
+    /* find slot address and size */
+    uint32_t slot_addr = ARM_UC_FLASH_INVALID_SIZE;
+    uint32_t slot_size = ARM_UC_FLASH_INVALID_SIZE;
+    arm_uc_error_t result = arm_uc_pal_flashiap_get_slot_addr_size(slot_id,
+                                                                   &slot_addr,
+                                                                   &slot_size);
+
+    if (details && result.error == ERR_NONE)
+    {
+        uint8_t buffer[ARM_UC_PAL_HEADER_SIZE] = { 0 };
+
+        int status = arm_uc_flashiap_read(buffer,
+                                          slot_addr,
+                                          ARM_UC_PAL_HEADER_SIZE);
+
+        if (status == ARM_UC_FLASHIAP_SUCCESS)
+        {
+            result = arm_uc_parse_internal_header_v2(buffer, details);
+
+            if (result.error == ERR_NONE)
+            {
+                /* signal done */
+                arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE);
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("arm_uc_parse_internal_header_v2 failed");
+            }
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("arm_uc_flashiap_read failed");
+        }
+    }
+
+    return result;
+}
+
+/*****************************************************************************/
+
+arm_uc_error_t ARM_UC_PAL_FlashIAP_GetActiveDetails(arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        /* read details from memory if offset is set */
+        if (MBED_CONF_UPDATE_CLIENT_APPLICATION_DETAILS)
+        {
+            /* set default error code */
+            result.code = ERR_NOT_READY;
+
+            /* Use flash driver eventhough we are reading from internal flash.
+               This will make it easier to use with uVisor.
+             */
+            uint8_t version_buffer[8] = { 0 };
+
+            /* read metadata magic and version from flash */
+            int rc = arm_uc_flashiap_read(version_buffer,
+                                          MBED_CONF_UPDATE_CLIENT_APPLICATION_DETAILS,
+                                          8);
+
+            if (rc == ARM_UC_FLASHIAP_SUCCESS)
+            {
+                /* read out header magic */
+                uint32_t headerMagic = arm_uc_parse_uint32(&version_buffer[0]);
+
+                /* read out header magic */
+                uint32_t headerVersion = arm_uc_parse_uint32(&version_buffer[4]);
+
+                /* choose version to decode */
+                switch(headerVersion)
+                {
+                    case ARM_UC_INTERNAL_HEADER_VERSION_V2:
+                    {
+                        result.code = ERR_NONE;
+                        /* Check the header magic */
+                        if (headerMagic != ARM_UC_INTERNAL_HEADER_MAGIC_V2)
+                        {
+                            UC_PAAL_ERR_MSG("firmware header is v2, but does not contain v2 magic");
+                            result.code = ERR_NOT_READY;
+                        }
+
+                        uint8_t read_buffer[ARM_UC_INTERNAL_HEADER_SIZE_V2] = { 0 };
+                        /* Read the rest of the header */
+                        if (result.error == ERR_NONE)
+                        {
+                            rc = arm_uc_flashiap_read(read_buffer,
+                                                      MBED_CONF_UPDATE_CLIENT_APPLICATION_DETAILS,
+                                                      ARM_UC_INTERNAL_HEADER_SIZE_V2);
+                            if (rc != 0)
+                            {
+                                result.code = ERR_NOT_READY;
+                                UC_PAAL_ERR_MSG("failed to read v2 header");
+                            }
+                        }
+                        /* Parse the header */
+                        if (result.error == ERR_NONE)
+                        {
+                            result = arm_uc_parse_internal_header_v2(read_buffer, details);
+                            if (result.error != ERR_NONE)
+                            {
+                                UC_PAAL_ERR_MSG("failed to parse v2 header");
+                            }
+                        }
+                        break;
+                    }
+                    /*
+                     * Other firmware header versions can be supported here.
+                     */
+                    default:
+                    {
+                        UC_PAAL_ERR_MSG("unrecognized firmware header version");
+                        result.code = ERR_NOT_READY;
+                    }
+                }
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("flash read failed");
+            }
+        }
+        else
+        {
+            /* offset not set - zero out struct */
+            memset(details, 0, sizeof(arm_uc_firmware_details_t));
+
+            result.code = ERR_NONE;
+        }
+
+        /* signal event if operation was successful */
+        if (result.error == ERR_NONE)
+        {
+            UC_PAAL_TRACE("callback");
+
+            arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE);
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get details for the firmware installer.
+ * @details This call populates the passed details struct with information
+ *          about the firmware installer.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_GetInstallerDetails(arm_uc_installer_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        /* only read from memory if offset is set */
+        if (MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS)
+        {
+            uint8_t* arm = (uint8_t*) (MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS +
+                offsetof(arm_uc_installer_details_t, arm_hash));
+
+            uint8_t* oem = (uint8_t*) (MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS +
+                offsetof(arm_uc_installer_details_t, oem_hash));
+
+            uint8_t* layout = (uint8_t*) (MBED_CONF_UPDATE_CLIENT_BOOTLOADER_DETAILS +
+                offsetof(arm_uc_installer_details_t, layout));
+
+            /* populate installer details struct */
+            memcpy(&details->arm_hash, arm, ARM_UC_SHA256_SIZE);
+            memcpy(&details->oem_hash, oem, ARM_UC_SHA256_SIZE);
+            details->layout = arm_uc_parse_uint32(layout);
+        }
+        else
+        {
+            /* offset not set, zero details struct */
+            memset(details, 0, sizeof(arm_uc_installer_details_t));
+        }
+
+        arm_uc_pal_flashiap_signal_internal(ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE);
+
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/source/arm_uc_pal_flashiap_mbed.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,90 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(TARGET_LIKE_MBED)
+
+#include "update-client-pal-flashiap/arm_uc_pal_flashiap_platform.h"
+#include "mbed.h"
+
+static FlashIAP flash;
+
+int32_t arm_uc_flashiap_init(void)
+{
+    /* Workaround for https://github.com/ARMmbed/mbed-os/issues/4967
+     * pal_init calls flash.init() before here. Second call to flash.init() will
+     * return -1 error state. Hence we ignore the result of flash.init here.
+     */
+    flash.init();
+    return 0;
+}
+
+int32_t arm_uc_flashiap_erase(uint32_t address, uint32_t size)
+{
+    return flash.erase(address, size);
+}
+
+int32_t arm_uc_flashiap_program(const uint8_t* buffer, uint32_t address, uint32_t size)
+{
+    uint32_t page_size = flash.get_page_size();
+    int status = ARM_UC_FLASHIAP_FAIL;
+
+    for (uint32_t i = 0; i < size; i += page_size)
+    {
+        status = flash.program(buffer+i, address+i, page_size);
+        if (status != ARM_UC_FLASHIAP_SUCCESS)
+        {
+            break;
+        }
+    }
+
+    return status;
+}
+
+int32_t arm_uc_flashiap_read(uint8_t* buffer, uint32_t address, uint32_t size)
+{
+    return flash.read(buffer, address, size);
+}
+
+uint32_t arm_uc_flashiap_get_page_size(void)
+{
+    return flash.get_page_size();
+}
+
+uint32_t arm_uc_flashiap_get_sector_size(uint32_t address)
+{
+    uint32_t sector_size = flash.get_sector_size(address);
+    if (sector_size == ARM_UC_FLASH_INVALID_SIZE || sector_size == 0)
+    {
+        return ARM_UC_FLASH_INVALID_SIZE;
+    }
+    else
+    {
+        return sector_size;
+    }
+}
+
+uint32_t arm_uc_flashiap_get_flash_size(void)
+{
+    return flash.get_flash_size();
+}
+
+uint32_t arm_uc_flashiap_get_flash_start(void)
+{
+    return flash.get_flash_start();
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/update-client-pal-flashiap/arm_uc_pal_flashiap.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,26 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_FLASHIAP_H
+#define ARM_UC_PAL_FLASHIAP_H
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+extern ARM_UC_PAAL_UPDATE ARM_UCP_FLASHIAP;
+
+#endif /* ARM_UC_PAL_FLASHIAP_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/update-client-pal-flashiap/arm_uc_pal_flashiap_implementation.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,145 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_FLASHIAP_IMPLEMENTATION_H
+#define ARM_UC_PAL_FLASHIAP_IMPLEMENTATION_H
+
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_types.h"
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+arm_uc_error_t ARM_UC_PAL_FlashIAP_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback);
+
+/**
+ * @brief Get maximum number of supported storage locations.
+ *
+ * @return Number of storage locations.
+ */
+uint32_t ARM_UC_PAL_FlashIAP_GetMaxID(void);
+
+/**
+ * @brief Prepare the storage layer for a new firmware image.
+ * @details The storage location is set up to receive an image with
+ *          the details passed in the details struct.
+ *
+ * @param location Storage location ID.
+ * @param details Pointer to a struct with firmware details.
+ * @param buffer Temporary buffer for formatting and storing metadata.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_Prepare(uint32_t location,
+                                           const arm_uc_firmware_details_t* details,
+                                           arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Write a fragment to the indicated storage location.
+ * @details The storage location must have been allocated using the Prepare
+ *          call. The call is expected to write the entire fragment before
+ *          signaling completion.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to where the fragment should be written.
+ * @param buffer Pointer to buffer struct with fragment.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_Write(uint32_t location,
+                                         uint32_t offset,
+                                         const arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Close storage location for writing and flush pending data.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_Finalize(uint32_t location);
+
+/**
+ * @brief Read a fragment from the indicated storage location.
+ * @details The function will read until the buffer is full or the end of
+ *          the storage location has been reached. The actual amount of
+ *          bytes read is set in the buffer struct.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to read from.
+ * @param buffer Pointer to buffer struct to store fragment. buffer->size
+ *        contains the intended read size.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ *         buffer->size contains actual bytes read on return.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_Read(uint32_t location,
+                                        uint32_t offset,
+                                        arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Set the firmware image in the slot to be the new active image.
+ * @details This call is responsible for initiating the process for
+ *          applying a new/different image. Depending on the platform this
+ *          could be:
+ *           * An empty call, if the installer can deduce which slot to
+ *             choose from based on the firmware details.
+ *           * Setting a flag to indicate which slot to use next.
+ *           * Decompressing/decrypting/installing the firmware image on
+ *             top of another.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_Activate(uint32_t location);
+
+/**
+ * @brief Get firmware details for the firmware image in the slot passed.
+ * @details This call populates the passed details struct with information
+ *          about the firmware image in the slot passed. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_FlashIAP_GetFirmwareDetails(
+                                        uint32_t location,
+                                        arm_uc_firmware_details_t* details);
+
+/*****************************************************************************/
+
+arm_uc_error_t ARM_UC_PAL_FlashIAP_GetActiveDetails(arm_uc_firmware_details_t* details);
+
+arm_uc_error_t ARM_UC_PAL_FlashIAP_GetInstallerDetails(arm_uc_installer_details_t* details);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ARM_UC_PAL_FLASHIAP_IMPLEMENTATION_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-flashiap/update-client-pal-flashiap/arm_uc_pal_flashiap_platform.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,110 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_FLASHIAP_PLATFORM_H
+#define ARM_UC_PAL_FLASHIAP_PLATFORM_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+    ARM_UC_FLASHIAP_SUCCESS = 0,
+    ARM_UC_FLASHIAP_FAIL    = -1
+};
+
+#define ARM_UC_FLASH_INVALID_SIZE 0xFFFFFFFF
+
+/** Initialize a flash IAP device
+ *
+ *  Should be called once per lifetime of the object.
+ *  @return 0 on success or a negative error code on failure
+ */
+int32_t arm_uc_flashiap_init(void);
+
+/** Erase sectors
+ *
+ *  The state of an erased sector is undefined until it has been programmed
+ *
+ *  @param address  Address of a sector to begin erasing, must be a multiple of the sector size
+ *  @param size     Size to erase in bytes, must be a multiple of the sector size
+ *  @return         0 on success, negative error code on failure
+ */
+int32_t arm_uc_flashiap_erase(uint32_t address, uint32_t size);
+
+/** Program data to pages
+ *
+ *  The sectors must have been erased prior to being programmed
+ *
+ *  @param buffer   Buffer of data to be written
+ *  @param address  Address of a page to begin writing to, must be a multiple of program and sector sizes
+ *  @param size     Size to write in bytes, must be a multiple of program and sector sizes
+ *  @return         0 on success, negative error code on failure
+ */
+int32_t arm_uc_flashiap_program(const uint8_t* buffer,
+                                uint32_t address,
+                                uint32_t size);
+
+/** Read data from a flash device.
+ *
+ *  This method invokes memcpy - reads number of bytes from the address
+ *
+ *  @param buffer   Buffer to write to
+ *  @param address  Flash address to begin reading from
+ *  @param size     Size to read in bytes
+ *  @return         0 on success, negative error code on failure
+ */
+int32_t arm_uc_flashiap_read(uint8_t* buffer,
+                             uint32_t address,
+                             uint32_t size);
+
+/** Get the program page size
+ *
+ *  @return Size of a program page in bytes
+ */
+uint32_t arm_uc_flashiap_get_page_size(void);
+
+/** Get the sector size at the defined address
+ *
+ *  Sector size might differ at address ranges.
+ *  An example <0-0x1000, sector size=1024; 0x10000-0x20000, size=2048>
+ *
+ *  @param address  Address of or inside the sector to query
+ *  @return         Size of a sector in bytes
+ */
+uint32_t arm_uc_flashiap_get_sector_size(uint32_t address);
+
+/** Get the flash size
+ *
+ *  @return         Size of the flash in bytes
+ */
+uint32_t arm_uc_flashiap_get_flash_size(void);
+
+
+/** Get the flash start address
+ *
+ *  @return         Start address of the flash
+ */
+uint32_t arm_uc_flashiap_get_flash_start(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,166 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/arm_update_cmdline.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,61 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# default values
+LOCATION=0
+OFFSET=0
+SIZE=0
+
+# parse command line arguments
+while [ $# -gt 1 ]
+do
+key="$1"
+case $key in
+    -h|--header)
+    HEADER="$2"
+    shift # past argument=value
+    ;;
+    -f|--firmware)
+    FIRMWARE="$2"
+    shift # past argument=value
+    ;;
+    -l|--location)
+    LOCATION="$2"
+    shift # past argument=value
+    ;;
+    -o|--offset)
+    OFFSET="$2"
+    shift # past argument=value
+    ;;
+    -s|--size)
+    SIZE="$2"
+    shift # past argument=value
+    ;;
+    *)
+            # unknown option
+    ;;
+esac
+shift
+done
+
+# echo "header:   ${HEADER}"
+# echo "firmware: ${FIRMWARE}"
+# echo "location: ${LOCATION}"
+# echo "offset:   ${OFFSET}"
+# echo "size:     ${SIZE}"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_activate.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,35 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. ../../../arm_update_cmdline.sh
+
+mkdir -p /tmp/extended
+
+# copy header to store
+VALUE=$(cp $HEADER /tmp/extended/header.bin)
+
+exit $VALUE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_active_details.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,34 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. ../../../arm_update_cmdline.sh
+
+# copy stored header to expected location
+VALUE=$(cp /tmp/extended/header.bin $HEADER)
+
+echo $HEADER
+
+exit $VALUE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_details.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,34 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. ../../../arm_update_cmdline.sh
+
+VALUE=$(cp "/tmp/extended/header_${LOCATION}.bin" $HEADER)
+
+echo $HEADER
+
+exit $VALUE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_finalize.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,33 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. ../../../arm_update_cmdline.sh
+
+# This script is called after the last firmware fragment is written
+# and before the firmware is read back for verification.
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_initialize.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,30 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. ../../../arm_update_cmdline.sh
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_installer.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,30 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. ../../../arm_update_cmdline.sh
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_prepare.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,37 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. ../../../arm_update_cmdline.sh
+
+# create directory to store header and firmware
+mkdir -p /tmp/extended
+
+# move header and firmeware to extended directory for local control
+cp $HEADER "/tmp/extended/header_${LOCATION}.bin"
+cp $FIRMWARE "/tmp/extended/firmware_${LOCATION}.bin"
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_read.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,36 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. ../../../arm_update_cmdline.sh
+
+# copy fragment from stored firmware to temporary file
+VALUE=$(dd if="/tmp/extended/firmware_${LOCATION}.bin" of=/tmp/firmware_fragment.bin count=$SIZE ibs=1 skip=$OFFSET 2>/dev/null)
+
+# indicate to Update client where to read fragment from
+echo "/tmp/firmware_fragment.bin"
+
+exit $VALUE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/generic/arm_update_write.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,39 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. ../../../arm_update_cmdline.sh
+
+# get size of pre-allocated binary file
+FILESIZE="$(wc -c <"/tmp/extended/firmware_${LOCATION}.bin")"
+
+# insert firmware fragment into binary file
+VALUE=$(dd if=$FIRMWARE of="/tmp/extended/firmware_${LOCATION}.bin" ibs=1 obs=1 count="${FILESIZE}" seek="${OFFSET}")
+
+# clean up
+rm $FIRMWARE
+
+exit $VALUE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/openwrt/arm_update_activate.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,121 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# This script takes two parameters: -f|--firmware and -h|--header
+# Parameters are parsed by arm_update_cmdline.sh
+#
+# It uses arm_update_kernel.sh to parse the the kernel commandline passed to
+# the kernel by U-Boot. This command line contains two parameters:
+# mbed.root : identifier for the active partition
+# mbed.boot : boot loader identifier
+#
+# If both the firmware and header exists, the script will overwrite the update
+# partition with the firmware and write the header to the update flags partition.
+# If both operations are successful, the active flags partition is erased.
+#
+# Boot order:
+# <slot 0><slot 1> : boot
+# empty - empty : slot 0
+# empty - valid : slot 1
+# valid - valid : slot 0
+# valid - empty : slot 0
+
+# Find mtd partitions
+#
+# ACTIVE_SLOT
+# ACTIVE_SLOT_MTD
+# ACTIVE_FLAGS_MTD
+# UPDATE_SLOT
+# UPDATE_SLOT_MTD
+# UPDATE_FLAGS_MTD
+#
+. arm_update_kernel.sh
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. arm_update_cmdline.sh
+
+#
+# Check that header and firmware are set and exist
+#
+if [ ! -f $HEADER ] || [ -z $HEADER ]; then
+    echo "header doesn't exists";
+    exit 1;
+fi
+
+if [ ! -f $FIRMWARE ] || [ -z $FIRMWARE ]; then
+    echo "firmware doesn't exists"
+    exit 1;
+fi
+
+# write firmware to ubi partition
+ubiformat "/dev/${UPDATE_SLOT_MTD}" -f $FIRMWARE --yes
+VALUE=$?
+
+# exit if return code is not zero
+if [ $VALUE -ne 0 ]; then
+    echo "failed to format new image"
+    exit $VALUE
+fi
+
+# Check if mtd-utils-flash-erase and mtd-utils-nandwrite are installed
+if ! which "nandwrite" &>/dev/null || ! which "flash_erase" &>/dev/null; then
+    echo "Either nandwrite or flash_erase tools are missing"
+    exit 1
+fi
+
+# erase sector
+flash_erase "/dev/${UPDATE_FLAGS_MTD}" 0 1
+VALUE=$?
+
+# exit if return code is not zero
+if [ $VALUE -ne 0 ]; then
+    echo "failed to erase update flags"
+    exit $VALUE
+fi
+
+# write header to update partition
+# if this is the default partition, this will activate it
+nandwrite -p -s 0 "/dev/${UPDATE_FLAGS_MTD}" $HEADER
+VALUE=$?
+
+# exit if return code is not zero
+if [ $VALUE -ne 0 ]; then
+    echo "failed to write new header"
+    exit $VALUE
+fi
+
+# erase active header
+# if this is the default partition, this will activate the update partition
+flash_erase "/dev/${ACTIVE_FLAGS_MTD}" 0 1
+VALUE=$?
+
+# exit if return code is not zero
+if [ $VALUE -ne 0 ]; then
+    echo "failed to erase active header"
+    exit $VALUE
+fi
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/openwrt/arm_update_active_details.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,70 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# header name (not prefix)
+HEADER_NAME="header"
+
+# header size
+HEADER_SIZE=112
+
+# Find mtd partitions
+#
+# ACTIVE_SLOT_MTD
+# ACTIVE_FLAGS_MTD
+# UPDATE_SLOT_MTD
+# UPDATE_FLAGS_MTD
+#
+. arm_update_kernel.sh
+
+#
+# get active flags
+#
+
+# expected location for header
+echo "/tmp/${HEADER_NAME}.bin"
+
+# dump to temporary file
+nanddump -f "/tmp/${HEADER_NAME}.tmp" "/dev/${ACTIVE_FLAGS_MTD}" 2>/dev/null
+VALUE=$?
+
+# exit if return code is not zero
+if [ $VALUE -ne 0 ]; then
+    exit $VALUE
+fi
+
+# truncate file to only contain header
+dd if=/tmp/${HEADER_NAME}.tmp of=/tmp/${HEADER_NAME}.bin ibs=1 count=${HEADER_SIZE} 2>/dev/null
+VALUE=$?
+
+# exit if return code is not zero
+if [ $VALUE -ne 0 ]; then
+    exit $VALUE
+fi
+
+# clean up
+rm -f /tmp/${HEADER_NAME}.tmp 2>/dev/null
+VALUE=$?
+
+# exit if return code is not zero
+if [ $VALUE -ne 0 ]; then
+    exit $VALUE
+fi
+
+# success
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/openwrt/arm_update_kernel.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,95 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# Parse kernel command line to find:
+#
+# Active no.:   ${ACTIVE_SLOT}
+# Active slot:  ${ACTIVE_SLOT_MTD}
+# Active flags: ${ACTIVE_FLAGS_MTD}
+#
+# Update no.:   ${UPDATE_SLOT}
+# Update slot:  ${UPDATE_SLOT_MTD}
+# Update flags: ${UPDATE_FLAGS_MTD}
+#
+
+# /proc/cmdline parameter that holds the active slot name
+KERNEL_PREFIX="ubi.mtd"
+
+# firmware prefix
+FIRMWARE_PREFIX="ROOT_"
+
+# flags prefix
+FLAGS_PREFIX="FLAGS_"
+
+#
+# parse /proc/cmdline and read the active slot
+#
+
+# get parameter
+for x in $(cat /proc/cmdline); do
+    case "$x" in
+        $KERNEL_PREFIX=*)
+        LINUX="${x#*=}"
+        ;;
+    esac
+done
+
+# read active slot number
+ACTIVE_SLOT=$(echo "${LINUX}" | sed -e "s/${FIRMWARE_PREFIX}//")
+
+# deduce alternate, update slot
+if [ "$ACTIVE_SLOT" -eq 0 ]; then
+    UPDATE_SLOT=1
+else
+    UPDATE_SLOT=0
+fi
+
+#
+# get active mtd for slot and flags
+#
+ACTIVE_NAME_MTD="${FIRMWARE_PREFIX}${ACTIVE_SLOT}"
+ACTIVE_LINE_MTD=$(cat /proc/mtd | grep "${ACTIVE_NAME_MTD}")
+ACTIVE_SLOT_MTD=${ACTIVE_LINE_MTD%:*}
+
+ACTIVE_NAME_MTD="${FLAGS_PREFIX}${ACTIVE_SLOT}"
+ACTIVE_LINE_MTD=$(cat /proc/mtd | grep "${ACTIVE_NAME_MTD}")
+ACTIVE_FLAGS_MTD=${ACTIVE_LINE_MTD%:*}
+
+#
+# get update mtd for slot and flags
+#
+UPDATE_NAME_MTD="${FIRMWARE_PREFIX}${UPDATE_SLOT}"
+UPDATE_LINE_MTD=$(cat /proc/mtd | grep ${UPDATE_NAME_MTD})
+UPDATE_SLOT_MTD=${UPDATE_LINE_MTD%:*}
+
+UPDATE_NAME_MTD="${FLAGS_PREFIX}${UPDATE_SLOT}"
+UPDATE_LINE_MTD=$(cat /proc/mtd | grep ${UPDATE_NAME_MTD})
+UPDATE_FLAGS_MTD=${UPDATE_LINE_MTD%:*}
+
+#
+# result
+#
+# echo "Active no.:   ${ACTIVE_SLOT}"
+# echo "Active slot:  ${ACTIVE_SLOT_MTD}"
+# echo "Active flags: ${ACTIVE_FLAGS_MTD}"
+#
+# echo "Update no.:   ${UPDATE_SLOT}"
+# echo "Update slot:  ${UPDATE_SLOT_MTD}"
+# echo "Update flags: ${UPDATE_FLAGS_MTD}"
+#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/yocto_generic/arm_update_activate.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,163 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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 - exit codes 1-20 come from arm_udpate_common.sh.
+
+set -x
+# Write a partition image file to a partition and set the boot flags.
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. /opt/arm/arm_update_cmdline.sh
+. /opt/arm/arm_update_common.sh
+
+if [ -n "$ARM_UPDATE_ACTIVATE_LOG_PATH" ]; then
+    # Redirect stdout and stderr to the log file
+    exec >"$ARM_UPDATE_ACTIVATE_LOG_PATH" 2>&1
+fi
+
+# Returns successfully if the given path is a directory and is empty (except
+# for maybe a 'lost+found' directory).
+#
+# $1: path of the directory to check
+is_empty_directory() {
+iedDirectory="$1"
+
+    [ -d "$iedDirectory" ] || return 1
+
+    iedContents=$(ls -A -1 "$iedDirectory" | grep -v 'lost+found')
+    [ -z "$iedContents" ]
+}
+
+# Format and mount a root partition
+# Exits on errors.
+#
+# $1: Path to the device file for the partition
+# $2: Label to give the new partition
+# $3: Mountpoint to use when mounting after formatting
+format_and_mount_root_partition_or_die() {
+famrpodPart="$1"
+famrpodLabel="$2"
+famrpodMountpoint="$3"
+
+    ensure_not_mounted_or_die "$famrpodPart"
+
+    # Create the file system on the next partition
+    if ! mkfs -t "$ROOTFS_TYPE" -L "$famrpodLabel" -F "$famrpodPart"; then
+        echo "mkfs failed on the new root partition"
+        exit 22
+    fi
+
+    ensure_mounted_or_die "$famrpodPart" "$famrpodMountpoint" "$ROOTFS_TYPE"
+}
+
+# Formats and populates a new root partition
+# Exits on errors.
+#
+# $1: Path to the device file for the new root partition
+# $2: Label for the new root partition
+# $3: Image file (compressed tar file) with which to populate the new
+#     partition. Trial and error is used to determine the compression algorithm
+create_root_partition_or_die() {
+crpodPart="$1"
+crpodLabel="$2"
+crpodImageFile="$3"
+
+    crpodMountpoint=/mnt/root
+
+    format_and_mount_root_partition_or_die "$crpodPart" "$crpodLabel" "$crpodMountpoint"
+
+    for crpodDecompressFlag in -z -j -J; do
+        # If a previous decompression failed then we might end up with some
+        # stray content in our mountpoint. Reformat if that is the case.
+        if ! is_empty_directory "$crpodMountpoint"; then
+            format_and_mount_root_partition_or_die "$crpodPart" "$crpodLabel" "$crpodMountpoint"
+        fi
+
+        echo "Trying decompression flag \"${crpodDecompressFlag}\"..."
+        if EXTRACT_UNSAFE_SYMLINKS=1 tar -x "$crpodDecompressFlag" -f "$crpodImageFile" -C "$crpodMountpoint"; then
+            echo "Unarchiving with decompression flag \"${crpodDecompressFlag}\" succeeded"
+            return 0
+        fi
+        echo "Unarchiving with decompression flag \"${crpodDecompressFlag}\" failed"
+    done
+
+    echo "Failed to find working decompression flag for image"
+    exit 23
+}
+
+# Detect root partitions
+root1=$(get_device_for_label rootfs1)
+exit_on_error "$?"
+
+root2=$(get_device_for_label rootfs2)
+exit_on_error "$?"
+
+FLAGS=$(get_device_for_label bootflags)
+exit_on_error "$?"
+
+# Find the partition that is currently mounted to /
+activePartition=$(get_active_root_device)
+
+if [ "$activePartition" = "$root1" ]; then
+    activePartitionLabel=rootfs1
+    nextPartition="$root2"
+    nextPartitionLabel=rootfs2
+elif [ "$activePartition" = "$root2" ]; then
+    activePartitionLabel=rootfs2
+    nextPartition="$root1"
+    nextPartitionLabel="rootfs1"
+else
+    echo "Current root partition does not have a \"rootfs1\" or \"rootfs2\" label"
+    exit 21
+fi
+
+create_root_partition_or_die "$nextPartition" "$nextPartitionLabel" "$FIRMWARE"
+ensure_not_mounted_or_die "$nextPartition"
+
+ensure_mounted_or_die "${FLAGS}" /mnt/flags "$FLAGSFS_TYPE"
+
+if ! cp "$HEADER" "/mnt/flags/${nextPartitionLabel}_header"; then
+    echo "Failed to copy image header"
+    exit 24
+fi
+sync
+
+if [ -e "/mnt/flags/${activePartitionLabel}" ]; then
+    if ! mv "/mnt/flags/${activePartitionLabel}" "/mnt/flags/${nextPartitionLabel}"; then
+        echo "Failed to rename boot flag file";
+        exit 25
+    fi
+else
+    if ! touch "/mnt/flags/${nextPartitionLabel}"; then
+        echo "Failed to create new boot flag file";
+        exit 26
+    fi
+fi
+sync
+
+ensure_not_mounted_or_die "$FLAGS"
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/yocto_generic/arm_update_active_details.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,85 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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 - exit codes 1-20 come from arm_udpate_common.sh.
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. /opt/arm/arm_update_cmdline.sh
+. /opt/arm/arm_update_common.sh
+
+if [ -n "$ARM_UPDATE_ACTIVE_DETAILS_LOG_PATH" ]; then
+    # Redirect stdout and stderr to the log file
+    exec >"$ARM_UPDATE_ACTIVE_DETAILS_LOG_PATH" 2>&1
+fi
+
+# header directory
+HEADER_DIR=$(dirname "${HEADER}")
+
+# header name (not prefix)
+HEADER_NAME="header"
+
+# location where the update client will find the header
+HEADER_PATH="${HEADER_DIR}/${HEADER_NAME}.bin"
+
+set -x
+
+# Detect root partitions
+root1=$(get_device_for_label rootfs1)
+exit_on_error "$?"
+
+root2=$(get_device_for_label rootfs2)
+exit_on_error "$?"
+
+# Flag partition
+FLAGS=$(get_device_for_label bootflags)
+exit_on_error "$?"
+
+# Find the partition that is currently mounted to /
+activePartition=$(get_active_root_device)
+
+if [ "$activePartition" = "$root1" ]; then
+    activePartitionLabel=rootfs1
+elif [ "$activePartition" = "$root2" ]; then
+    activePartitionLabel=rootfs2
+else
+    echo "Current root partition does not have a \"rootfs1\" or \"rootfs2\" label"
+    exit 21
+fi
+
+ensure_mounted_or_die "$FLAGS" /mnt/flags "$FLAGSFS_TYPE"
+
+# Boot Flags
+if [ -e "/mnt/flags/${activePartitionLabel}_header" ]; then
+    if ! cp "/mnt/flags/${activePartitionLabel}_header" "$HEADER_PATH"; then
+        echo "Failed to copy image header"
+        exit 22
+    fi
+else
+    echo "Warning: No active firmware header found!"
+    exit 23
+fi
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/yocto_generic/arm_update_common.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,134 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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 library file uses return and exit codes 1-20 to indicate errors.
+#
+
+LOCAL_CONFIG_PATH=/opt/arm/arm_update_local_config.sh
+ROOTFS_TYPE="ext4"
+FLAGSFS_TYPE="ext4"
+
+# Given an exit status, exits with that status if it is non-zero, otherwise
+# does nothing
+#
+# $1: exit status to check
+exit_on_error() {
+eoeStatus="$1"
+    if [ "$eoeStatus" -ne 0 ]; then
+        exit "$eoeStatus"
+    fi
+}
+
+# Get the path to the device file for the partition with the given label.⏎
+#
+# $1: the partition label
+get_device_for_label() {
+gdflLabel="$1"
+
+    gdflDev=$(readlink -f "/dev/disk/by-label/${gdflLabel}")
+    if [ "$?" -ne 0 ]; then
+        echo "Failed to find device file for partition with label \"${gdflLabel}\""
+        return 1;
+    fi
+    if [ ! -b "$gdflDev" ]; then
+        echo "Device with label \"${gdflLabel}\" is not a block device"
+        return 2;
+    fi
+    printf "%s" "$gdflDev"
+}
+
+# Get the mountpoint for a device.
+# If the device is not mounted then a mountpoint is not printed but the
+# function still returns successfully.
+#
+# $1: path to the device file
+get_mountpoint() {
+gmDevice="$1"
+    lsblk -nro MOUNTPOINT "$gmDevice"
+    if [ "$?" -ne 0 ]; then
+        echo "Unable to determine mountpoint (if any) of device \"${gmDevice}\""
+        return 3
+    fi
+}
+
+# Do whatever is required so that the given device is not mounted.
+# Errors cause an exit.
+#
+# $1: path to device to unmount (if mounted).
+ensure_not_mounted_or_die() {
+enmodDevice="$1"
+
+    enmodMountpoint=$(get_mountpoint "$enmodDevice")
+    exit_on_error "$?"
+
+    if [ "$enmodMountpoint" = "" ]; then
+        return 4
+    fi
+
+    if ! umount "$enmodDevice"; then
+        echo "Unable to unmount device \"${enmodDevice}\""
+        exit 5
+    fi
+}
+
+# Do whatever is required so that the given device is mounted at the given
+# mountpoint, including creating the mountpoint if necessary.
+# Errors cause an exit.
+#
+# $1: path to the device to mount
+# $2: the mountpoint for the device
+ensure_mounted_or_die() {
+emodDevice="$1"
+emodMountpoint="$2"
+emodFsType="$3"
+
+    emodCurrMountpoint=$(get_mountpoint "$emodDevice")
+    exit_on_error "$?"
+
+    case  "$emodCurrMountpoint" in
+        "$emodMountpoint")
+            return 6
+            ;;
+        "")
+            ;;
+        *)
+            if ! umount "$emodDevice"; then
+                echo "Unable to unmount device \"${emodDevice}\""
+                exit 7
+            fi
+            ;;
+    esac
+
+    if ! mkdir -p "$emodMountpoint"; then
+        echo "Unable to create mountpoint \"${emodMountpoint}\""
+        exit 8
+    fi
+
+    if ! mount -t "$emodFsType" "$emodDevice" "$emodMountpoint"; then
+        echo "Unable to mount device \"${emodDevice}\" at \"${emodMountpoint}\""
+        exit 9
+    fi
+}
+
+# Find the device that is currently mounted to /
+get_active_root_device() {
+    lsblk -nrpo NAME,MOUNTPOINT | grep -e ".* /$" | cut -d ' ' -f1
+}
+
+[ -e "$LOCAL_CONFIG_PATH" ] && . "$LOCAL_CONFIG_PATH"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/yocto_rpi/arm_update_activate.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,143 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+set -x
+# Write a partition image file to a partition and set the boot flags.
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. /opt/arm/arm_update_cmdline.sh
+
+# Return the number of the partition with the given label (in $1)
+# Exit with error if the partition can't be found
+getpart() {
+    res=$(readlink -f "/dev/disk/by-label/$1")
+    if [ "$(echo "${res}" | cut -c1-13)x"  = "/dev/mmcblk0px" ]; then
+        echo "$(echo $res | cut -d'p' -f2)"
+    fi
+}
+
+# Detect root partitions
+root1=$(getpart "rootfs1")
+if [ "${root1}"x = "x" ]; then
+    echo "Unable to find partition with label 'rootfs1'"
+    exit 9
+fi
+root2=$(getpart "rootfs2")
+if [ "${root2}"x = "x" ]; then
+    echo "Unable to find partition with label 'rootfs2'"
+    exit 9
+fi
+ROOTS="$root1 $root2"
+
+# Flag partition
+FLAGS=$(getpart "bootflags")
+if [ "${FLAGS}"x = "x" ]; then
+    echo "Unable to find partition with label 'bootflags'"
+    exit 9
+fi
+
+# Find the partition that is currently mounted to /
+activePartition=$(lsblk -nro NAME,MOUNTPOINT | grep -e ".* /$" | cut -d ' ' -f1)
+# Find the disk that contains the current root
+activeDisk=$(lsblk -nro pkname "/dev/${activePartition}")
+# Get the format of the partition name
+partitionPrefix=$(echo ${activePartition} | sed -e "s|^\([a-z0-9]*[a-z]\)[0-9]$|\1|")
+
+nextPartition=""
+nextPartitionLabel=""
+nextRoot=""
+# Find the other root partition by listing both root partitions and filtering out the active partition
+for pNum in ${ROOTS} ; do
+    if [ "${partitionPrefix}${pNum}" != "$activePartition" ]; then
+        nextPartition="${partitionPrefix}${pNum}"
+        nextRoot=${pNum}
+        break
+    fi
+done
+
+if [ -z "${nextPartition}" ]; then
+    exit 1
+fi
+
+# Make sure that nextPartition exists in the disk
+if ! lsblk -nr "/dev/${nextPartition}" > /dev/null ; then
+    exit 2
+fi
+
+# Make sure the next partition isn't mounted.
+umount "/dev/${nextPartition}" > /dev/null
+# Set next partition label based on whether it is first or second root
+if [ "${nextRoot}" = "5" ]; then
+    nextPartitionLabel="rootfs1"
+fi
+if [ "${nextRoot}" = "6" ]; then
+    nextPartitionLabel="rootfs2"
+fi
+# Create the file system on the next partition
+if ! mkfs -t ext4 -L ${nextPartitionLabel} -F "/dev/${nextPartition}"; then
+    echo "mkfs failed on the new root partition"
+    exit 3
+fi
+# Mount the next partition
+if ! mount "/dev/${nextPartition}" /mnt/root; then
+    echo "Unable to mount the new root partition"
+    exit 4
+fi
+# Uncompress the image
+if ! tar xvjf $FIRMWARE -C /mnt/root; then
+    echo "Image copy failed"
+    exit 5
+fi
+umount /mnt/root
+
+if ! mkdir -p /mnt/flags ; then
+    exit 6
+fi
+
+# Make sure flags partition isn't mounted.
+umount "/dev/${partitionPrefix}${FLAGS}" > /dev/null
+if ! mount "/dev/${partitionPrefix}${FLAGS}" /mnt/flags ; then
+    exit 7
+fi
+
+# Boot Flags
+if [ "${nextRoot}" = "5" ]; then
+    cp $HEADER /mnt/flags/five
+    sync
+    rm -f /mnt/flags/six
+    sync
+elif [ "${nextRoot}" = "6" ]; then
+    cp $HEADER /mnt/flags/six
+    sync
+    rm -f /mnt/flags/five
+    sync
+fi
+
+if ! umount /mnt/flags ; then
+    exit 8
+fi
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/yocto_rpi/arm_update_active_details.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,86 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# Parse command line
+#
+# HEADER
+# FIRMWARE
+# LOCATION
+# OFFSET
+# SIZE
+#
+. /opt/arm/arm_update_cmdline.sh
+
+# header directory
+HEADER_DIR=$(dirname "${HEADER}")
+
+# header name (not prefix)
+HEADER_NAME="header"
+
+# location where the update client will find the header
+HEADER_PATH="${HEADER_DIR}/${HEADER_NAME}.bin"
+
+# header size
+HEADER_SIZE=112
+
+set -x
+# Return the number of the partition with the given label (in $1)
+# Exit with error if the partition can't be found
+getpart() {
+    res=$(readlink -f "/dev/disk/by-label/$1")
+    if [ "$(echo "${res}" | cut -c1-13)x"  = "/dev/mmcblk0px" ]; then
+        echo "$(echo $res | cut -d'p' -f2)"
+    fi
+}
+
+# Flag partition
+FLAGS=$(getpart "bootflags")
+if [ "${FLAGS}"x = "x" ]; then
+    echo "Unable to find partition with label 'bootflags'"
+    exit 9
+fi
+
+# Find the partition that is currently mounted to /
+activePartition=$(lsblk -nro NAME,MOUNTPOINT | grep -e ".* /$" | cut -d ' ' -f1)
+activePartitionNum=$(echo "${activePartition}" | grep -Eo '[0-9]+$')
+
+# Get the format of the partition name
+partitionPrefix=$(echo "${activePartition}" | sed -e "s|^\([a-z0-9]*[a-z]\)[0-9]$|\1|")
+
+# Make sure flags partition isn't mounted.
+umount "/dev/${partitionPrefix}${FLAGS}" > /dev/null
+
+# mount flags partition
+if ! mount "/dev/${partitionPrefix}${FLAGS}" /mnt/flags ; then
+    exit 7
+fi
+
+# Boot Flags
+if [ "${activePartitionNum}" = "5" ] && [ -e "/mnt/flags/five" ]; then
+    cp /mnt/flags/five $HEADER_PATH
+    sync
+elif [ "${activePartitionNum}" = "6" ] && [ -e "/mnt/flags/six" ]; then
+    cp /mnt/flags/six $HEADER_PATH
+    sync
+else
+    echo "Warning: No active firmware header found!"
+    exit 9
+fi
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/scripts/yotta_install.sh	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,22 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Copyright 2016-2017 ARM Ltd.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# 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.
+# ----------------------------------------------------------------------------
+
+# Copy generic scripts to top level application so the test app can find them
+cp scripts/generic/arm_* ../../
+cp scripts/arm_update_cmdline.sh ../../
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/source/arm_uc_pal_linux_generic.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,191 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(TARGET_IS_PC_LINUX)
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+#include "update-client-pal-linux/arm_uc_pal_linux_implementation.h"
+#include "update-client-pal-linux/arm_uc_pal_linux_implementation_internal.h"
+
+/**
+ * @brief Get a bitmap indicating supported features.
+ * @details The bitmap is used in conjunction with the firmware and
+ *          installer details struct to indicate what fields are supported
+ *          and which values are valid.
+ *
+ * @return Capability bitmap.
+ */
+ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UC_PAL_Linux_GetCapabilities_Generic(void)
+{
+    const ARM_UC_PAAL_UPDATE_CAPABILITIES result = {
+        .installer_arm_hash = 0,
+        .installer_oem_hash = 0,
+        .installer_layout   = 0,
+        .firmware_hash      = 1,
+        .firmware_hmac      = 0,
+        .firmware_campaign  = 0,
+        .firmware_version   = 1,
+        .firmware_size      = 1
+    };
+
+    return result;
+}
+
+arm_ucp_worker_t arm_uc_worker_parameters_initialize = {
+    .command  = "../../../arm_update_initialize.sh",
+    .header   = 0,
+    .firmware = 0,
+    .location = 0,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_INITIALIZE_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_INITIALIZE_ERROR,
+    .post_runner = NULL
+};
+
+arm_ucp_worker_t arm_uc_worker_parameters_prepare = {
+    .command  = "../../../arm_update_prepare.sh",
+    .header   = 1,
+    .firmware = 1,
+    .location = 1,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_PREPARE_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_PREPARE_ERROR,
+    .post_runner = NULL
+};
+
+arm_ucp_worker_t arm_uc_worker_parameters_read = {
+    .command = "../../../arm_update_read.sh",
+    .header   = 0,
+    .firmware = 0,
+    .location = 1,
+    .offset   = 1,
+    .size     = 1,
+    .success_event = ARM_UC_PAAL_EVENT_READ_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_READ_ERROR,
+    .post_runner = NULL
+};
+
+arm_ucp_worker_t arm_uc_worker_parameters_write = {
+    .command = "../../../arm_update_write.sh",
+    .header   = 0,
+    .firmware = 1,
+    .location = 1,
+    .offset   = 1,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_WRITE_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_WRITE_ERROR,
+    .post_runner = NULL
+};
+
+arm_ucp_worker_t arm_uc_worker_parameters_finalize = {
+    .command = "../../../arm_update_finalize.sh",
+    .header   = 1,
+    .firmware = 1,
+    .location = 1,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_FINALIZE_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_FINALIZE_ERROR,
+    .post_runner = NULL
+};
+
+arm_ucp_worker_t arm_uc_worker_parameters_details = {
+    .command = "../../../arm_update_details.sh",
+    .header   = 1,
+    .firmware = 0,
+    .location = 1,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_ERROR,
+    .post_runner = NULL
+};
+
+arm_ucp_worker_t arm_uc_worker_parameters_active_details = {
+    .command = "../../../arm_update_active_details.sh",
+    .header   = 1,
+    .firmware = 0,
+    .location = 0,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_ERROR,
+    .post_runner = NULL
+};
+
+arm_ucp_worker_t arm_uc_worker_parameters_activate = {
+    .command = "../../../arm_update_activate.sh",
+    .header   = 1,
+    .firmware = 1,
+    .location = 0,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_ACTIVATE_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_ACTIVATE_ERROR,
+    .post_runner = NULL
+};
+
+arm_ucp_worker_t arm_uc_worker_parameters_installer = {
+    .command = "../../../arm_update_installer.sh",
+    .header   = 1,
+    .firmware = 0,
+    .location = 0,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_ERROR,
+    .post_runner = NULL
+};
+
+arm_uc_error_t ARM_UC_PAL_Linux_Initialize_Generic(ARM_UC_PAAL_UPDATE_SignalEvent_t callback)
+{
+#if 1
+    extern arm_ucp_worker_config_t arm_uc_worker_parameters;
+
+    arm_uc_worker_parameters.activate       = &arm_uc_worker_parameters_activate;
+    arm_uc_worker_parameters.active_details = &arm_uc_worker_parameters_active_details;
+    arm_uc_worker_parameters.details        = &arm_uc_worker_parameters_details;
+    arm_uc_worker_parameters.finalize       = &arm_uc_worker_parameters_finalize;
+    arm_uc_worker_parameters.initialize     = &arm_uc_worker_parameters_initialize;
+    arm_uc_worker_parameters.installer      = &arm_uc_worker_parameters_installer;
+    arm_uc_worker_parameters.prepare        = &arm_uc_worker_parameters_prepare;
+//    arm_uc_worker_parameters.read           = &arm_uc_worker_parameters_read;
+//    arm_uc_worker_parameters.write          = &arm_uc_worker_parameters_write;
+#endif
+
+    return ARM_UC_PAL_Linux_Initialize(callback);
+}
+
+const ARM_UC_PAAL_UPDATE ARM_UCP_LINUX_GENERIC =
+{
+    .Initialize                 = ARM_UC_PAL_Linux_Initialize_Generic,
+    .GetCapabilities            = ARM_UC_PAL_Linux_GetCapabilities_Generic,
+    .GetMaxID                   = ARM_UC_PAL_Linux_GetMaxID,
+    .Prepare                    = ARM_UC_PAL_Linux_Prepare,
+    .Write                      = ARM_UC_PAL_Linux_Write,
+    .Finalize                   = ARM_UC_PAL_Linux_Finalize,
+    .Read                       = ARM_UC_PAL_Linux_Read,
+    .Activate                   = ARM_UC_PAL_Linux_Activate,
+    .GetActiveFirmwareDetails   = ARM_UC_PAL_Linux_GetActiveFirmwareDetails,
+    .GetFirmwareDetails         = ARM_UC_PAL_Linux_GetFirmwareDetails,
+    .GetInstallerDetails        = ARM_UC_PAL_Linux_GetInstallerDetails
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/source/arm_uc_pal_linux_implementation.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,747 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(TARGET_IS_PC_LINUX)
+
+#include "update-client-pal-linux/arm_uc_pal_linux_implementation_internal.h"
+#include "update-client-pal-linux/arm_uc_pal_linux_implementation.h"
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+#include "update-client-common/arm_uc_trace.h"
+#include "update-client-common/arm_uc_utilities.h"
+#include "update-client-common/arm_uc_metadata_header_v2.h"
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <stdio.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+extern linux_worker_thread_info_t linux_worker_thread;
+
+/* worker struct, must be accessible externally */
+arm_ucp_worker_config_t arm_uc_worker_parameters = { 0 };
+
+static FILE* arm_uc_firmware_descriptor = NULL;
+
+static arm_uc_error_t spawn_thread(void *(*start_routine) (void *), void *arg)
+{
+    arm_uc_error_t result = {ERR_NONE};
+
+    /* Get the thread mutex. This prevents another thread from being spawned until this one completes.
+       There should only ever be one thread at a time, since they are spawned via a single-threaded
+       state machine, but this guarantees that there will only be one. */
+    int status = pthread_mutex_trylock(&linux_worker_thread.mutex);
+    if (status == EBUSY) {
+        ARM_UC_SET_ERROR(result, ERR_NOT_READY);
+    }
+    else if (status != 0) {
+        uint32_t code = (TWO_CC('P', 'T') << 16) | (status & 0xFFFF);
+        ARM_UC_SET_ERROR(result, code);
+    }
+    /* Create "detached thread" attribute only once */
+    if (result.error == ERR_NONE && linux_worker_thread.attr_initialized == 0)
+    {
+        if ((status = pthread_attr_init(&linux_worker_thread.attr)) != 0)
+        {
+            result.error = ERR_INVALID_PARAMETER;
+            pthread_mutex_unlock(&linux_worker_thread.mutex);
+        }
+        else
+        {
+            if ((status = pthread_attr_setdetachstate(&linux_worker_thread.attr, PTHREAD_CREATE_DETACHED)) != 0)
+            {
+                result.error = ERR_INVALID_PARAMETER;
+                pthread_mutex_unlock(&linux_worker_thread.mutex);
+            }
+            else
+            {
+                linux_worker_thread.attr_initialized = 1;
+            }
+        }
+    }
+    if (result.error == ERR_NONE) {
+        /* create a detached thread to execute the supplied routine */
+        int status = pthread_create(&linux_worker_thread.thread,
+                                    &linux_worker_thread.attr,
+                                    start_routine,
+                                    arg);
+
+        /* check if thread was created successfully */
+        if (status != 0)
+        {
+            result.code = ERR_INVALID_PARAMETER;
+            pthread_mutex_unlock(&linux_worker_thread.mutex);
+        }
+    }
+    return result;
+}
+
+/**
+ * @brief Initialize the underlying storage and set the callback handler.
+ *
+ * @param callback Function pointer to event handler.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (callback)
+    {
+        arm_uc_pal_linux_internal_set_callback(callback);
+
+        /* create folder for headers if it does not already exist */
+        errno = 0;
+        int status = mkdir(ARM_UC_HEADER_FOLDER_PATH, 0700);
+
+        if ((status == 0) || (errno == EEXIST))
+        {
+            /* create folder for firmwares if it does not already exist */
+            errno = 0;
+            status = mkdir(ARM_UC_FIRMWARE_FOLDER_PATH, 0700);
+
+            if ((status == 0) || (errno == EEXIST))
+            {
+                /* set return code on success */
+                result.code = ERR_NONE;
+            }
+        }
+
+        /* signal completion or perform extended preparation */
+        if (result.error == ERR_NONE)
+        {
+            /* set explicit ERR_NONE upon success */
+            result.code = ERR_NONE;
+
+            if (arm_uc_worker_parameters.initialize)
+            {
+                /* use extended prepare, invoke script from worker thread */
+
+                /* create a second thread which executes worker_parameters_prepare */
+                result = spawn_thread(arm_uc_pal_linux_extended_post_worker,
+                                      arm_uc_worker_parameters.initialize);
+            }
+            else
+            {
+                /* call event handler */
+                arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_INITIALIZE_DONE, false);
+            }
+        }
+
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get maximum number of supported storage locations.
+ *
+ * @return Number of storage locations.
+ */
+uint32_t ARM_UC_PAL_Linux_GetMaxID(void)
+{
+    return 1;
+}
+
+/**
+ * @brief Prepare the storage layer for a new firmware image.
+ * @details The storage location is set up to receive an image with
+ *          the details passed in the details struct.
+ *
+ * @param location Storage location ID.
+ * @param details Pointer to a struct with firmware details.
+ * @param buffer Temporary buffer for formatting and storing metadata.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_Prepare(uint32_t location,
+                                        const arm_uc_firmware_details_t* details,
+                                        arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details && buffer)
+    {
+        UC_PAAL_TRACE("details size: %" PRIu64, details->size);
+
+        /* write header */
+        result = arm_uc_pal_linux_internal_write_header(&location, details);
+
+        /* allocate space for firmware */
+        if (result.error == ERR_NONE)
+        {
+            char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
+
+            /* construct header file path */
+            result = arm_uc_pal_linux_internal_file_path(file_path,
+                                                         ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH,
+                                                         ARM_UC_FIRMWARE_FOLDER_PATH,
+                                                         "firmware",
+                                                         &location);
+
+            UC_PAAL_TRACE("file path: %s", file_path);
+
+            if (result.error == ERR_NONE)
+            {
+                /* open file */
+                errno = 0;
+                FILE* descriptor = fopen(file_path, "wb");
+
+                if (descriptor != NULL)
+                {
+                    /* allocate space by writing empty file */
+                    memset(buffer->ptr, 0, buffer->size_max);
+                    buffer->size = buffer->size_max;
+
+                    uint64_t index = 0;
+                    while (index < details->size)
+                    {
+                        /* calculate write size to handle overspill */
+                        size_t actual_size = details->size - index;
+
+                        if (actual_size > buffer->size)
+                        {
+                            actual_size = buffer->size;
+                        }
+
+                        /* write buffer */
+                        size_t xfer_size = fwrite(buffer->ptr,
+                                                  sizeof(uint8_t),
+                                                  actual_size,
+                                                  descriptor);
+
+                        /* break out if write failed */
+                        if (xfer_size == actual_size)
+                        {
+                            index += actual_size;
+                        }
+                        else
+                        {
+                            result.code = ERR_INVALID_PARAMETER;
+                            break;
+                        }
+                    }
+
+                    /* close file after write */
+                    int status = fclose(descriptor);
+
+                    if (status == EOF)
+                    {
+                        UC_PAAL_ERR_MSG("failed to allocate space for firmware");
+                        result.code = ERR_INVALID_PARAMETER;
+                    }
+                }
+                else
+                {
+                    UC_PAAL_ERR_MSG("failed to open file: %s", strerror(errno));
+                }
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("file name and path too long");
+            }
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("could not write header");
+        }
+
+        /* signal completion or perform extended preparation */
+        if (result.error == ERR_NONE)
+        {
+            /* set explicit ERR_NONE upon success */
+            result.code = ERR_NONE;
+
+            if (arm_uc_worker_parameters.prepare)
+            {
+                /* use extended prepare, invoke script from worker thread */
+                /* export location */
+                arm_uc_pal_linux_internal_set_location(&location);
+
+                /* create a second thread which executes worker_parameters_prepare */
+                result = spawn_thread(arm_uc_pal_linux_extended_post_worker,
+                                      arm_uc_worker_parameters.prepare);
+            }
+            else
+            {
+                /* call event handler */
+                arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_PREPARE_DONE, false);
+            }
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Write a fragment to the indicated storage location.
+ * @details The storage location must have been allocated using the Prepare
+ *          call. The call is expected to write the entire fragment before
+ *          signaling completion.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to where the fragment should be written.
+ * @param buffer Pointer to buffer struct with fragment.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_Write(uint32_t location,
+                                      uint32_t offset,
+                                      const arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (buffer)
+    {
+        /* reverse default error code */
+        result.code = ERR_NONE;
+
+        /* open file if descriptor is not set */
+        if (arm_uc_firmware_descriptor == NULL)
+        {
+            char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
+
+            /* construct firmware file path */
+            result = arm_uc_pal_linux_internal_file_path(file_path,
+                                                         ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH,
+                                                         ARM_UC_FIRMWARE_FOLDER_PATH,
+                                                         "firmware",
+                                                         &location);
+
+            if (result.error == ERR_NONE)
+            {
+                /* open file */
+                if (arm_uc_worker_parameters.write)
+                {
+                    /* in extended write, each fragment is stored in its own file */
+                    arm_uc_firmware_descriptor = fopen(file_path, "w+b");
+
+                    /* export offset before resetting it */
+                    arm_uc_pal_linux_internal_set_offset(offset);
+                    offset = 0;
+                }
+                else
+                {
+                    /* in normal write, each fragment is added to an existing file */
+                    arm_uc_firmware_descriptor = fopen(file_path, "r+b");
+                }
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("firmware file name and path too long");
+            }
+        }
+
+        /* continue if file is open */
+        if (arm_uc_firmware_descriptor != NULL)
+        {
+            /* set write position */
+            int status = fseek(arm_uc_firmware_descriptor,
+                               offset,
+                               SEEK_SET);
+
+            /* continue if position is set */
+            if (status == 0)
+            {
+                /* write buffer */
+                size_t xfer_size = fwrite(buffer->ptr,
+                                          sizeof(uint8_t),
+                                          buffer->size,
+                                          arm_uc_firmware_descriptor);
+
+                /* set error code if write failed */
+                if (xfer_size != buffer->size)
+                {
+                    UC_PAAL_ERR_MSG("failed to write firmware");
+                    result.code = ERR_INVALID_PARAMETER;
+                }
+
+                /* if using extended write */
+                if (arm_uc_worker_parameters.write)
+                {
+                    /* close file after write */
+                    int status = fclose(arm_uc_firmware_descriptor);
+                    arm_uc_firmware_descriptor = NULL;
+
+                    if (status == EOF)
+                    {
+                        UC_PAAL_ERR_MSG("failed to close firmware file");
+                        result.code = ERR_INVALID_PARAMETER;
+                    }
+                }
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("failed to seek in firmware");
+                result.code = ERR_INVALID_PARAMETER;
+            }
+        }
+
+        /* signal completion or perform extended write */
+        if (result.error == ERR_NONE)
+        {
+            /* set explicit ERR_NONE */
+            result.code = ERR_NONE;
+
+            if (arm_uc_worker_parameters.write)
+            {
+                /* use extended write, invoke script from worker thread */
+                /* export location */
+                arm_uc_pal_linux_internal_set_location(&location);
+
+                /* create a second thread which executes worker_parameters_write */
+                result = spawn_thread(arm_uc_pal_linux_extended_post_worker,
+                                      arm_uc_worker_parameters.write);
+            }
+            else
+            {
+                /* call event handler */
+                arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_WRITE_DONE, false);
+            }
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Close storage location for writing and flush pending data.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_Finalize(uint32_t location)
+{
+    arm_uc_error_t result = { .code = ERR_NONE };
+
+    /* only close firmware file if descriptor is not NULL */
+    if (arm_uc_firmware_descriptor != NULL)
+    {
+        /* close file */
+        int status = fclose(arm_uc_firmware_descriptor);
+        arm_uc_firmware_descriptor = NULL;
+
+        if (status == EOF)
+        {
+            UC_PAAL_ERR_MSG("failed to close firmware file");
+            result.code = ERR_INVALID_PARAMETER;
+        }
+    }
+
+    /* signal completion or perform extended finalization */
+    if (result.error == ERR_NONE)
+    {
+        /* explicitly set code to ERR_NONE */
+        result.code = ERR_NONE;
+
+        /* use extended finalize, invoke script from worker thread */
+        if (arm_uc_worker_parameters.finalize)
+        {
+            /* export location */
+            arm_uc_pal_linux_internal_set_location(&location);
+
+            /* create a second thread which executes worker_parameters_finalize */
+            result = spawn_thread(arm_uc_pal_linux_extended_post_worker,
+                                  arm_uc_worker_parameters.finalize);
+        }
+        else
+        {
+            /* call event handler */
+            arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_FINALIZE_DONE, false);
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Read a fragment from the indicated storage location.
+ * @details The function will read until the buffer is full or the end of
+ *          the storage location has been reached. The actual amount of
+ *          bytes read is set in the buffer struct.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to read from.
+ * @param buffer Pointer to buffer struct to store fragment. buffer->size
+ *        contains the intended read size.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ *         buffer->size contains actual bytes read on return.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_Read(uint32_t location,
+                                     uint32_t offset,
+                                     arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (buffer)
+    {
+        /* use extended finalize, invoke script from worker thread */
+        if (arm_uc_worker_parameters.read)
+        {
+            /* export location, offset and buffer */
+            arm_uc_pal_linux_internal_set_location(&location);
+            arm_uc_pal_linux_internal_set_offset(offset);
+            arm_uc_pal_linux_internal_set_buffer(buffer);
+
+            /* create a second thread which executes worker_parameters_read */
+            result = spawn_thread(arm_uc_pal_linux_extended_pre_worker,
+                                  arm_uc_worker_parameters.read);
+        }
+        else
+        {
+            /* normal read */
+            char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
+
+            /* construct firmware file path */
+            result = arm_uc_pal_linux_internal_file_path(file_path,
+                                                         ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH,
+                                                         ARM_UC_FIRMWARE_FOLDER_PATH,
+                                                         "firmware",
+                                                         &location);
+
+            /* file path is valid */
+            if (result.error == ERR_NONE)
+            {
+                result = arm_uc_pal_linux_internal_read(file_path, offset, buffer);
+
+                /* signal completion */
+                if (result.error == ERR_NONE)
+                {
+                    /* call event handler */
+                    arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_READ_DONE, false);
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set the firmware image in the slot to be the new active image.
+ * @details This call is responsible for initiating the process for
+ *          applying a new/different image. Depending on the platform this
+ *          could be:
+ *           * An empty call, if the installer can deduce which slot to
+ *             choose from based on the firmware details.
+ *           * Setting a flag to indicate which slot to use next.
+ *           * Decompressing/decrypting/installing the firmware image on
+ *             top of another.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_Activate(uint32_t location)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    /* read firmware details from location */
+    arm_uc_firmware_details_t details = { 0 };
+    result = arm_uc_pal_linux_internal_read_header(&location, &details);
+
+    if (result.error == ERR_NONE)
+    {
+        UC_PAAL_TRACE("version: %" PRIu64, details.version);
+        UC_PAAL_TRACE("size: %"PRIu64, details.size);
+
+        /* write details to active location */
+        result = arm_uc_pal_linux_internal_write_header(NULL, &details);
+
+        if (result.error == ERR_NONE)
+        {
+            /* explicitly set code to ERR_NONE */
+            result.code = ERR_NONE;
+
+            /* use extended activate, invoke script from worker thread */
+            if (arm_uc_worker_parameters.activate)
+            {
+                /* export location */
+                arm_uc_pal_linux_internal_set_location(&location);
+
+                /* create a second thread which executes worker_parameters_read */
+                result = spawn_thread(arm_uc_pal_linux_extended_post_worker,
+                                      arm_uc_worker_parameters.activate);
+            }
+            else
+            {
+                arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_ACTIVATE_DONE, false);
+            }
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get firmware details for the actively running firmware.
+ * @details This call populates the passed details struct with information
+ *          about the currently active firmware image. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_GetActiveFirmwareDetails(arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        /* use extended get firmware details, invoke script from worker thread */
+        if (arm_uc_worker_parameters.active_details)
+        {
+            /* export details */
+            arm_uc_pal_linux_internal_set_details(details);
+
+            /* create a second thread which executes worker_parameters_read */
+            result = spawn_thread(arm_uc_pal_linux_extended_pre_worker,
+                                  arm_uc_worker_parameters.active_details);
+
+        }
+        else
+        {
+            /* normal read */
+            result = arm_uc_pal_linux_internal_read_header(NULL, details);
+
+            if (result.error == ERR_NONE)
+            {
+                UC_PAAL_TRACE("version: %" PRIu64, details->version);
+                UC_PAAL_TRACE("size: %"PRIu64, details->size);
+
+                if (result.error == ERR_NONE)
+                {
+                    arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE, false);
+                }
+            }
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get firmware details for the firmware image in the slot passed.
+ * @details This call populates the passed details struct with information
+ *          about the firmware image in the slot passed. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_GetFirmwareDetails(uint32_t location,
+                                                   arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        /* use extended get firmware details, invoke script from worker thread */
+        if (arm_uc_worker_parameters.details)
+        {
+            /* export location and details */
+            arm_uc_pal_linux_internal_set_location(&location);
+            arm_uc_pal_linux_internal_set_details(details);
+
+            /* create a second thread which executes worker_parameters_read */
+            result = spawn_thread(arm_uc_pal_linux_extended_pre_worker,
+                                  arm_uc_worker_parameters.details);
+        }
+        else
+        {
+            /* normal read */
+            result = arm_uc_pal_linux_internal_read_header(&location, details);
+
+            if (result.error == ERR_NONE)
+            {
+                UC_PAAL_TRACE("version: %" PRIu64, details->version);
+                UC_PAAL_TRACE("size: %"PRIu64, details->size);
+
+                arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_GET_FIRMWARE_DETAILS_DONE, false);
+            }
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get details for the component responsible for installation.
+ * @details This call populates the passed details struct with information
+ *          about the local installer. Only the fields marked as supported
+ *          in the capabilities bitmap will have valid values. The
+ *          installer could be the bootloader, a recovery image, or some
+ *          other component responsible for applying the new firmware
+ *          image.
+ *
+ * @param details Pointer to installer details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_GetInstallerDetails(arm_uc_installer_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        /* use extended installer details, invoke script from worker thread */
+        if (arm_uc_worker_parameters.installer)
+        {
+            /* export installer details */
+            arm_uc_pal_linux_internal_set_installer(details);
+
+            /* create a second thread which executes worker_parameters_read */
+            result = spawn_thread(arm_uc_pal_linux_extended_pre_worker,
+                                  arm_uc_worker_parameters.installer);
+        }
+        else
+        {
+            /* normal read */
+            result = arm_uc_pal_linux_internal_read_installer(details);
+
+            if (result.error == ERR_NONE)
+            {
+                arm_uc_pal_linux_signal_callback(ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE, false);
+            }
+        }
+    }
+
+    return result;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/source/arm_uc_pal_linux_implementation_internal.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,785 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(TARGET_IS_PC_LINUX)
+
+#include "update-client-pal-linux/arm_uc_pal_linux_implementation_internal.h"
+
+#include "update-client-common/arm_uc_trace.h"
+#include "update-client-common/arm_uc_utilities.h"
+#include "update-client-common/arm_uc_metadata_header_v2.h"
+#include "update-client-common/arm_uc_scheduler.h"
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <stdio.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+/* pointer to external callback handler */
+static ARM_UC_PAAL_UPDATE_SignalEvent_t arm_uc_pal_external_callback = NULL;
+
+linux_worker_thread_info_t linux_worker_thread = {0, PTHREAD_MUTEX_INITIALIZER};
+
+// storage set aside for adding event_cb to the event queue
+static arm_uc_callback_t event_cb_storage = { 0 };
+
+void arm_uc_pal_linux_signal_callback(uint32_t event, bool from_thread)
+{
+    if (arm_uc_pal_external_callback)
+    {
+        if (from_thread) {
+            /* Run given callback in the update client's thread */
+            ARM_UC_PostCallback(&event_cb_storage, arm_uc_pal_external_callback, event);
+        } else {
+            arm_uc_pal_external_callback(event);
+        }
+    }
+    if (from_thread) {
+        /* The last thing that the thread does is call arm_uc_pal_linux_signal_callback(),
+         * so unlock the thread mutex so that another thread can be created if needed */
+        pthread_mutex_unlock(&linux_worker_thread.mutex);
+    }
+}
+
+void arm_uc_pal_linux_internal_set_callback(ARM_UC_PAAL_UPDATE_SignalEvent_t callback)
+{
+    arm_uc_pal_external_callback = callback;
+}
+
+static uint32_t arm_uc_offset = 0;
+static arm_uc_buffer_t* arm_uc_buffer = NULL;
+static arm_uc_firmware_details_t* arm_uc_details = NULL;
+static arm_uc_installer_details_t* arm_uc_installer = NULL;
+static uint32_t* arm_uc_location = NULL;
+static uint32_t arm_uc_location_buffer = 0;
+
+void arm_uc_pal_linux_internal_set_offset(uint32_t offset)
+{
+    arm_uc_offset = offset;
+}
+
+void arm_uc_pal_linux_internal_set_buffer(arm_uc_buffer_t* buffer)
+{
+    arm_uc_buffer = buffer;
+}
+
+void arm_uc_pal_linux_internal_set_details(arm_uc_firmware_details_t* details)
+{
+    arm_uc_details = details;
+}
+
+void arm_uc_pal_linux_internal_set_installer(arm_uc_installer_details_t* details)
+{
+    arm_uc_installer = details;
+}
+
+void arm_uc_pal_linux_internal_set_location(uint32_t* location)
+{
+    if (location)
+    {
+        arm_uc_location_buffer = *location;
+        arm_uc_location = &arm_uc_location_buffer;
+    }
+    else
+    {
+        arm_uc_location = NULL;
+    }
+}
+
+arm_uc_error_t arm_uc_pal_linux_internal_file_path(char* buffer,
+                                                   size_t buffer_length,
+                                                   const char* folder,
+                                                   const char* type,
+                                                   uint32_t* location)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (buffer && folder && type)
+    {
+        int actual_length = 0;
+
+        if (location)
+        {
+            /* construct file path using location */
+            actual_length = snprintf(buffer, buffer_length,
+                                     "%s/%s_%" PRIu32 ".bin", folder, type, *location);
+        }
+        else
+        {
+            /* construct file path without location */
+            actual_length = snprintf(buffer, buffer_length,
+                                     "%s/%s.bin", folder, type);
+        }
+
+        /* check that the buffer is large enough */
+        if (actual_length < buffer_length)
+        {
+            result.code = ERR_NONE;
+        }
+    }
+
+    return result;
+}
+
+static bool arm_uc_pal_linux_internal_command(arm_ucp_worker_t* parameters,
+                                              char* command,
+                                              size_t command_length)
+{
+    /* default to failed */
+    bool valid = false;
+
+    if (parameters && command)
+    {
+        /* invert status */
+        valid = true;
+
+        int length = snprintf(command,
+                              command_length,
+                              "%s ",
+                              parameters->command);
+
+        /* initialize remaining */
+        int remaining = command_length - length;
+
+        /* add header parameter if requested */
+        if ((remaining > 0) && (parameters->header))
+        {
+            char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
+
+            /* construct header file path */
+            arm_uc_error_t result =
+                arm_uc_pal_linux_internal_file_path(file_path,
+                                                    sizeof(file_path),
+                                                    ARM_UC_HEADER_FOLDER_PATH,
+                                                    "header",
+                                                    arm_uc_location);
+
+            /* generated valid file path */
+            if (result.error == ERR_NONE)
+            {
+                /* add parameter to command line */
+                length += snprintf(&command[length],
+                                   remaining,
+                                   "-h %s ",
+                                   file_path);
+            }
+
+            /* update remaining */
+            remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length;
+
+            /* check validity */
+            valid = ((result.error == ERR_NONE) && (remaining > 0));
+        }
+
+        /* add firmware parameter if requested */
+        if ((valid) && (parameters->firmware))
+        {
+            char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
+
+            /* construct firmware file path */
+            arm_uc_error_t result =
+                arm_uc_pal_linux_internal_file_path(file_path,
+                                                    sizeof(file_path),
+                                                    ARM_UC_FIRMWARE_FOLDER_PATH,
+                                                    "firmware",
+                                                    arm_uc_location);
+
+            /* generated valid file path */
+            if (result.error == ERR_NONE)
+            {
+                /* add parameter to command line */
+                length += snprintf(&command[length],
+                                   remaining,
+                                   "-f %s ",
+                                   file_path);
+            }
+
+            /* update remaining */
+            remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length;
+
+            /* check validity */
+            valid = ((result.error == ERR_NONE) && (remaining > 0));
+        }
+
+        /* add location parameter if requested */
+        if ((valid) && (parameters->location))
+        {
+            /* add parameter to command line */
+            length += snprintf(&command[length],
+                               remaining,
+                               "-l %" PRIu32 " ",
+                               *arm_uc_location);
+
+            /* update remaining */
+            remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length;
+
+            /* check validity */
+            valid = (remaining > 0);
+        }
+
+        /* add offset parameter if requested */
+        if ((valid) && (parameters->offset))
+        {
+            /* add parameter to command line */
+            length += snprintf(&command[length],
+                               remaining,
+                               "-o %" PRIu32 " ",
+                               arm_uc_offset);
+
+            /* update remaining */
+            remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length;
+
+            /* check validity */
+            valid = (remaining > 0);
+        }
+
+        /* add size parameter if requested */
+        if ((valid) && (parameters->size))
+        {
+            if (arm_uc_buffer)
+            {
+                /* add parameter to command line */
+                length += snprintf(&command[length],
+                                   remaining,
+                                   "-s %" PRIu32 " ",
+                                   arm_uc_buffer->size_max);
+
+                /* update remaining */
+                remaining = ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH - length;
+
+                /* check validity */
+                valid = (remaining > 0);
+            }
+            else
+            {
+                valid = false;
+            }
+        }
+    }
+
+    return valid;
+}
+
+arm_uc_error_t arm_uc_pal_linux_internal_read(const char* file_path,
+                                              uint32_t offset,
+                                              arm_uc_buffer_t* buffer)
+{
+    /* default to failure result */
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (file_path && buffer)
+    {
+        /* open file */
+        errno = 0;
+        FILE* descriptor = fopen(file_path, "rb");
+
+        /* continue if file is open */
+        if (descriptor != NULL)
+        {
+            /* set read position */
+            int status = fseek(descriptor, offset, SEEK_SET);
+
+            /* continue if position is set */
+            if (status == 0)
+            {
+                /* read buffer */
+                errno = 0;
+                size_t xfer_size = fread(buffer->ptr,
+                                         sizeof(uint8_t),
+                                         buffer->size,
+                                         descriptor);
+
+                /* set buffer size if read succeeded */
+                status = ferror(descriptor);
+
+                if (status == 0)
+                {
+                    buffer->size = xfer_size;
+
+                    /* set successful result */
+                    result.code = ERR_NONE;
+                }
+                else
+                {
+                    /* set error code if read failed */
+                    UC_PAAL_ERR_MSG("failed to read %s: %s", file_path, strerror(errno));
+                    buffer->size = 0;
+                }
+
+                /* close file after read */
+                fclose(descriptor);
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("failed to seek in: %s", file_path);
+            }
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("failed to open %s: %s", file_path, strerror(errno));
+        }
+    }
+
+    return result;
+}
+
+arm_uc_error_t arm_uc_pal_linux_internal_read_header(uint32_t* location,
+                                                     arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        /* construct header file path */
+        char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
+
+        result = arm_uc_pal_linux_internal_file_path(file_path,
+                                                     ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH,
+                                                     ARM_UC_HEADER_FOLDER_PATH,
+                                                     "header",
+                                                     location);
+
+        /* file path is valid */
+        if (result.error == ERR_NONE)
+        {
+            /* allocate external header sized read buffer since it will be
+               large enough to hold either an internal or external header.
+             */
+            uint8_t read_buffer[ARM_UC_EXTERNAL_HEADER_SIZE_V2] = { 0 };
+
+            arm_uc_buffer_t buffer = {
+                .size_max = sizeof(read_buffer),
+                .size     = sizeof(read_buffer),
+                .ptr      = read_buffer
+            };
+
+            /* read metadata header */
+            result = arm_uc_pal_linux_internal_read(file_path, 0, &buffer);
+
+            /* check return code */
+            if (result.error == ERR_NONE)
+            {
+                UC_PAAL_TRACE("header bytes: %u", buffer.size);
+
+                /* read out header magic */
+                uint32_t headerMagic = arm_uc_parse_uint32(&read_buffer[0]);
+
+                /* read out header magic */
+                uint32_t headerVersion = arm_uc_parse_uint32(&read_buffer[4]);
+
+                /* choose version to decode */
+                if ((headerMagic == ARM_UC_INTERNAL_HEADER_MAGIC_V2) &&
+                    (headerVersion == ARM_UC_INTERNAL_HEADER_VERSION_V2) &&
+                    (buffer.size == ARM_UC_INTERNAL_HEADER_SIZE_V2))
+                {
+                    result = arm_uc_parse_internal_header_v2(read_buffer, details);
+                }
+                else if ((headerMagic == ARM_UC_EXTERNAL_HEADER_MAGIC_V2) &&
+                         (headerVersion == ARM_UC_EXTERNAL_HEADER_VERSION_V2) &&
+                         (buffer.size == ARM_UC_EXTERNAL_HEADER_SIZE_V2))
+                {
+                    result = arm_uc_parse_external_header_v2(read_buffer, details);
+                }
+                else
+                {
+                    UC_PAAL_ERR_MSG("invalid header in slot %" PRIu32, location);
+
+                    /* invalid header format */
+                    result.code = ERR_INVALID_PARAMETER;
+                }
+            }
+            else
+            {
+                /* unsuccessful read */
+                UC_PAAL_ERR_MSG("unable to read header in slot %" PRIX32, location);
+            }
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("header file name and path too long");
+        }
+    }
+
+    return result;
+}
+
+arm_uc_error_t arm_uc_pal_linux_internal_read_installer(arm_uc_installer_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        /* construct file path */
+        char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
+
+        result = arm_uc_pal_linux_internal_file_path(file_path,
+                                                     ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH,
+                                                     ARM_UC_INSTALLER_FOLDER_PATH,
+                                                     "installer",
+                                                     NULL);
+
+        /* file path is valid */
+        if (result.error == ERR_NONE)
+        {
+            uint8_t read_buffer[2 * sizeof(arm_uc_hash_t) + sizeof(uint32_t)] = { 0 };
+
+            arm_uc_buffer_t buffer = {
+                .size_max = sizeof(read_buffer),
+                .size     = 0,
+                .ptr      = read_buffer
+            };
+
+            /* read installer details */
+            result = arm_uc_pal_linux_internal_read(file_path, 0, &buffer);
+
+            UC_PAAL_TRACE("installer bytes: %u", buffer.size);
+
+            /* check return code */
+            if ((result.error == ERR_NONE) &&
+                (buffer.size == sizeof(read_buffer)))
+            {
+                memcpy(details->arm_hash,
+                       buffer.ptr,
+                       sizeof(arm_uc_hash_t));
+
+                memcpy(details->oem_hash,
+                       &buffer.ptr[sizeof(arm_uc_hash_t)],
+                       sizeof(arm_uc_hash_t));
+
+                details->layout = arm_uc_parse_uint32(&buffer.ptr[2 * sizeof(arm_uc_hash_t)]);
+            }
+            else
+            {
+                /* unsuccessful read */
+                UC_PAAL_ERR_MSG("unable to read installer details");
+            }
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("installer file name and path too long");
+        }
+    }
+
+    return result;
+}
+
+arm_uc_error_t arm_uc_pal_linux_internal_write_header(uint32_t* location,
+                                                      const arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        /* allocate external header sized buffer since it will be
+           large enough to hold either an internal or external header.
+         */
+        uint8_t temp_buffer[ARM_UC_EXTERNAL_HEADER_SIZE_V2] = { 0 };
+
+        arm_uc_buffer_t buffer = {
+            .size_max = sizeof(temp_buffer),
+            .size     = 0,
+            .ptr      = temp_buffer
+        };
+
+        /* encode firmware details in buffer */
+#if ARM_UC_USE_EXTERNAL_HEADER
+        result = arm_uc_create_external_header_v2(details, &buffer);
+#else
+        result = arm_uc_create_internal_header_v2(details, &buffer);
+#endif
+
+        /* write header file */
+        if (result.error == ERR_NONE)
+        {
+            char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
+
+            /* construct header file path */
+            result = arm_uc_pal_linux_internal_file_path(file_path,
+                                                         ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH,
+                                                         ARM_UC_HEADER_FOLDER_PATH,
+                                                         "header",
+                                                         location);
+
+            if (result.error == ERR_NONE)
+            {
+                /* inverse result */
+                result.code = ERR_INVALID_PARAMETER;
+
+                /* open file and get file handler */
+                errno = 0;
+                FILE* file = fopen(file_path, "wb");
+
+                if (file != NULL)
+                {
+                    /* write buffer to file */
+                    size_t xfer_size = fwrite(buffer.ptr,
+                                              sizeof(uint8_t),
+                                              buffer.size,
+                                              file);
+
+                    UC_PAAL_TRACE("written: %u", xfer_size);
+
+                    /* close file after write */
+                    int status = fclose(file);
+
+                    if ((xfer_size == buffer.size) &&
+                        (status != EOF))
+                    {
+                        /* set return code if write was successful */
+                        result.code = ERR_NONE;
+                    }
+                    else
+                    {
+                        UC_PAAL_ERR_MSG("failed to write header");
+                    }
+                }
+                else
+                {
+                    UC_PAAL_ERR_MSG("file open failed: %s", strerror(errno));
+                }
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("header file name and path too long");
+            }
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("header too large for buffer");
+        }
+
+    }
+
+    return result;
+}
+
+/**
+ * @brief Function to run script in a worker thread before file operations.
+ *
+ * @param params Pointer to arm_ucp_worker_t struct.
+ */
+void* arm_uc_pal_linux_extended_pre_worker(void* params)
+{
+    /* default to failure */
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    /* get parameters */
+    arm_ucp_worker_t* parameters = (arm_ucp_worker_t*) params;
+
+    /* file path to script result */
+    char file_path[ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH] = { 0 };
+
+    /* construct script command */
+    char command[ARM_UC_MAXIMUM_COMMAND_LENGTH] = { 0 };
+
+    int error = 0;
+    int valid = arm_uc_pal_linux_internal_command(parameters,
+                                                  command,
+                                                  ARM_UC_MAXIMUM_COMMAND_LENGTH);
+
+    /* command is valid */
+    if (valid)
+    {
+        UC_PAAL_TRACE("Extended pre-script command: %s", command);
+
+        /* execute script */
+        errno = 0;
+        FILE* pipe = popen(command, "r");
+
+        if (pipe)
+        {
+            /* read pipe */
+            size_t xfer_size = fread(file_path,
+                                     sizeof(uint8_t),
+                                     ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH,
+                                     pipe);
+
+            /* trim non-printable characters */
+            for (size_t index = 0; index < xfer_size; index++)
+            {
+                /* space is the first printable character */
+                if (file_path[index] < ' ')
+                {
+                    /* truncate string */
+                    file_path[index] = '\0';
+                    break;
+                }
+            }
+
+            int status = 0;
+
+            /* check fread error status */
+            status = ferror(pipe);
+            if (status == 0)
+            {
+                /* Wait for child thread termination and check exit status */
+                status = pclose(pipe);
+
+                /* make sure child thread terminated correctly and scirpt exit status is 0 */
+                if (status != -1 && WIFEXITED(status))
+                {
+                    if (WEXITSTATUS(status) == 0)
+                    {
+                        /* switch from boolean result to arm_uc_error_t */
+                        result.code = ERR_NONE;
+                    }
+                    else
+                    {
+                        UC_PAAL_ERR_MSG("Script exited with non-zero status %" PRId32, status);
+                    }
+                }
+                else
+                {
+                    UC_PAAL_ERR_MSG("pipe terminated incorrectly %" PRId32, status);
+                }
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("failed to read pipe: %" PRId32, status);
+            }
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("failed to execute script: %" PRId32, errno);
+        }
+    }
+
+    /* file path is valid */
+    if (result.error == ERR_NONE)
+    {
+        /* invert status */
+        result.code = ERR_INVALID_PARAMETER;
+
+        extern arm_ucp_worker_config_t arm_uc_worker_parameters;
+
+        /* perform read operation */
+        if ((parameters == arm_uc_worker_parameters.read) &&
+            (arm_uc_buffer != NULL))
+        {
+            result = arm_uc_pal_linux_internal_read(file_path, 0, arm_uc_buffer);
+
+            /* reset global buffer */
+            arm_uc_buffer = NULL;
+        }
+
+        /* read details */
+        if ((parameters == arm_uc_worker_parameters.details) &&
+                 (arm_uc_details != NULL))
+        {
+            result = arm_uc_pal_linux_internal_read_header(arm_uc_location,
+                                                           arm_uc_details);
+
+            /* reset global details pointer */
+            arm_uc_details = NULL;
+        }
+
+        /* read active details */
+        if ((parameters == arm_uc_worker_parameters.active_details) &&
+                 (arm_uc_details != NULL))
+        {
+            result = arm_uc_pal_linux_internal_read_header(NULL,
+                                                           arm_uc_details);
+
+            /* reset global details pointer */
+            arm_uc_details = NULL;
+        }
+
+        /* read installer details */
+        if ((parameters == arm_uc_worker_parameters.installer) &&
+                 (arm_uc_installer != NULL))
+        {
+            result = arm_uc_pal_linux_internal_read_installer(arm_uc_installer);
+
+            /* reset global installer pointer */
+            arm_uc_installer = NULL;
+        }
+    }
+
+    if (result.error == ERR_NONE)
+    {
+        UC_PAAL_TRACE("pre-script complete");
+
+        arm_uc_pal_linux_signal_callback(parameters->success_event, true);
+    }
+    else
+    {
+        UC_PAAL_ERR_MSG("pre-script failed");
+
+        arm_uc_pal_linux_signal_callback(parameters->failure_event, true);
+    }
+}
+
+/**
+ * @brief Function to run script in a worker thread before file operations.
+ *
+ * @param params Pointer to arm_ucp_worker_t struct.
+ */
+void* arm_uc_pal_linux_extended_post_worker(void* params)
+{
+    /* get parameters */
+    arm_ucp_worker_t* parameters = (arm_ucp_worker_t*) params;
+
+    /* construct script command */
+    char command[ARM_UC_MAXIMUM_COMMAND_LENGTH] = { 0 };
+
+    int error = 0;
+    int32_t event = 0;
+    int valid = arm_uc_pal_linux_internal_command(parameters,
+                                                  command,
+                                                  ARM_UC_MAXIMUM_COMMAND_LENGTH);
+
+    if (valid)
+    {
+        UC_PAAL_TRACE("Extended post-script command: %s", command);
+
+        /* execute script command */
+        error = system(command);
+        error = WEXITSTATUS(error);
+
+        /* update valid flag */
+        valid = (error == 0);
+    }
+
+    if (valid)
+    {
+        UC_PAAL_TRACE("post-script completed");
+
+        event = parameters->success_event;
+
+        /* execute the post runner if it exists and the script succeeded */
+        if (parameters->post_runner)
+        {
+            event = parameters->post_runner();
+            UC_PAAL_TRACE("post runner returned event %" PRId32, event);
+        }
+    }
+    else
+    {
+        UC_PAAL_ERR_MSG("post-script failed: %" PRId32, error);
+
+        event = parameters->failure_event;
+    }
+
+    arm_uc_pal_linux_signal_callback(event, true);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/source/arm_uc_pal_linux_openwrt.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,107 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(TARGET_IS_PC_LINUX)
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+#include "update-client-pal-linux/arm_uc_pal_linux_implementation.h"
+#include "update-client-pal-linux/arm_uc_pal_linux_implementation_internal.h"
+#include "update-client-common/arm_uc_common.h"
+#include <unistd.h>
+
+/**
+ * @brief Get a bitmap indicating supported features.
+ * @details The bitmap is used in conjunction with the firmware and
+ *          installer details struct to indicate what fields are supported
+ *          and which values are valid.
+ *
+ * @return Capability bitmap.
+ */
+ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UC_PAL_Linux_GetCapabilities_OpenWRT(void)
+{
+    const ARM_UC_PAAL_UPDATE_CAPABILITIES result = {
+        .installer_arm_hash = 0,
+        .installer_oem_hash = 0,
+        .installer_layout   = 0,
+        .firmware_hash      = 1,
+        .firmware_hmac      = 0,
+        .firmware_campaign  = 0,
+        .firmware_version   = 1,
+        .firmware_size      = 1
+    };
+
+    return result;
+}
+
+arm_ucp_worker_t arm_uc_worker_parameters_active_details = {
+    .command = "/usr/sbin/arm_update_active_details.sh",
+    .header   = 1,
+    .firmware = 0,
+    .location = 0,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_ERROR,
+    .post_runner = NULL
+};
+
+arm_ucp_worker_t arm_uc_worker_parameters_activate = {
+    .command = "/usr/sbin/arm_update_activate.sh",
+    .header   = 1,
+    .firmware = 1,
+    .location = 0,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_ACTIVATE_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_ACTIVATE_ERROR,
+    .post_runner = NULL
+};
+
+arm_uc_error_t ARM_UC_PAL_Linux_Initialize_OpenWRT(ARM_UC_PAAL_UPDATE_SignalEvent_t callback)
+{
+    extern arm_ucp_worker_config_t arm_uc_worker_parameters;
+
+    arm_uc_worker_parameters.activate       = &arm_uc_worker_parameters_activate;
+    arm_uc_worker_parameters.active_details = &arm_uc_worker_parameters_active_details;
+    arm_uc_worker_parameters.details        = NULL;
+    arm_uc_worker_parameters.finalize       = NULL;
+    arm_uc_worker_parameters.initialize     = NULL;
+    arm_uc_worker_parameters.installer      = NULL;
+    arm_uc_worker_parameters.prepare        = NULL;
+    arm_uc_worker_parameters.read           = NULL;
+    arm_uc_worker_parameters.write          = NULL;
+
+    return ARM_UC_PAL_Linux_Initialize(callback);
+}
+
+const ARM_UC_PAAL_UPDATE ARM_UCP_LINUX_OPENWRT =
+{
+    .Initialize                 = ARM_UC_PAL_Linux_Initialize_OpenWRT,
+    .GetCapabilities            = ARM_UC_PAL_Linux_GetCapabilities_OpenWRT,
+    .GetMaxID                   = ARM_UC_PAL_Linux_GetMaxID,
+    .Prepare                    = ARM_UC_PAL_Linux_Prepare,
+    .Write                      = ARM_UC_PAL_Linux_Write,
+    .Finalize                   = ARM_UC_PAL_Linux_Finalize,
+    .Read                       = ARM_UC_PAL_Linux_Read,
+    .Activate                   = ARM_UC_PAL_Linux_Activate,
+    .GetActiveFirmwareDetails   = ARM_UC_PAL_Linux_GetActiveFirmwareDetails,
+    .GetFirmwareDetails         = ARM_UC_PAL_Linux_GetFirmwareDetails,
+    .GetInstallerDetails        = ARM_UC_PAL_Linux_GetInstallerDetails
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/source/arm_uc_pal_linux_yocto_generic.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,105 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(TARGET_IS_PC_LINUX)
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+#include "update-client-pal-linux/arm_uc_pal_linux_implementation.h"
+#include "update-client-pal-linux/arm_uc_pal_linux_implementation_internal.h"
+
+/**
+ * @brief Get a bitmap indicating supported features.
+ * @details The bitmap is used in conjunction with the firmware and
+ *          installer details struct to indicate what fields are supported
+ *          and which values are valid.
+ *
+ * @return Capability bitmap.
+ */
+static ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UC_PAL_Linux_GetCapabilities_Yocto_Generic(void)
+{
+    const ARM_UC_PAAL_UPDATE_CAPABILITIES result = {
+        .installer_arm_hash = 0,
+        .installer_oem_hash = 0,
+        .installer_layout   = 0,
+        .firmware_hash      = 1,
+        .firmware_hmac      = 0,
+        .firmware_campaign  = 0,
+        .firmware_version   = 1,
+        .firmware_size      = 1
+    };
+
+    return result;
+}
+
+static arm_ucp_worker_t arm_uc_worker_parameters_active_details = {
+    .command = "/opt/arm/arm_update_active_details.sh",
+    .header   = 1,
+    .firmware = 0,
+    .location = 0,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_ERROR,
+    .post_runner = NULL
+};
+
+static arm_ucp_worker_t arm_uc_worker_parameters_activate = {
+    .command = "/opt/arm/arm_update_activate.sh",
+    .header   = 1,
+    .firmware = 1,
+    .location = 0,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_ACTIVATE_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_ACTIVATE_ERROR,
+    .post_runner = NULL
+};
+
+static arm_uc_error_t ARM_UC_PAL_Linux_Initialize_Yocto_Generic(ARM_UC_PAAL_UPDATE_SignalEvent_t callback)
+{
+    extern arm_ucp_worker_config_t arm_uc_worker_parameters;
+
+    arm_uc_worker_parameters.activate       = &arm_uc_worker_parameters_activate;
+    arm_uc_worker_parameters.active_details = &arm_uc_worker_parameters_active_details;
+    arm_uc_worker_parameters.details        = NULL;
+    arm_uc_worker_parameters.finalize       = NULL;
+    arm_uc_worker_parameters.initialize     = NULL;
+    arm_uc_worker_parameters.installer      = NULL;
+    arm_uc_worker_parameters.prepare        = NULL;
+    arm_uc_worker_parameters.read           = NULL;
+    arm_uc_worker_parameters.write          = NULL;
+
+    return ARM_UC_PAL_Linux_Initialize(callback);
+}
+
+const ARM_UC_PAAL_UPDATE ARM_UCP_LINUX_YOCTO_GENERIC =
+{
+    .Initialize                 = ARM_UC_PAL_Linux_Initialize_Yocto_Generic,
+    .GetCapabilities            = ARM_UC_PAL_Linux_GetCapabilities_Yocto_Generic,
+    .GetMaxID                   = ARM_UC_PAL_Linux_GetMaxID,
+    .Prepare                    = ARM_UC_PAL_Linux_Prepare,
+    .Write                      = ARM_UC_PAL_Linux_Write,
+    .Finalize                   = ARM_UC_PAL_Linux_Finalize,
+    .Read                       = ARM_UC_PAL_Linux_Read,
+    .Activate                   = ARM_UC_PAL_Linux_Activate,
+    .GetActiveFirmwareDetails   = ARM_UC_PAL_Linux_GetActiveFirmwareDetails,
+    .GetFirmwareDetails         = ARM_UC_PAL_Linux_GetFirmwareDetails,
+    .GetInstallerDetails        = ARM_UC_PAL_Linux_GetInstallerDetails
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/source/arm_uc_pal_linux_yocto_rpi.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,105 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(TARGET_IS_PC_LINUX)
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+#include "update-client-pal-linux/arm_uc_pal_linux_implementation.h"
+#include "update-client-pal-linux/arm_uc_pal_linux_implementation_internal.h"
+
+/**
+ * @brief Get a bitmap indicating supported features.
+ * @details The bitmap is used in conjunction with the firmware and
+ *          installer details struct to indicate what fields are supported
+ *          and which values are valid.
+ *
+ * @return Capability bitmap.
+ */
+ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UC_PAL_Linux_GetCapabilities_Yocto_RPi(void)
+{
+    const ARM_UC_PAAL_UPDATE_CAPABILITIES result = {
+        .installer_arm_hash = 0,
+        .installer_oem_hash = 0,
+        .installer_layout   = 0,
+        .firmware_hash      = 1,
+        .firmware_hmac      = 0,
+        .firmware_campaign  = 0,
+        .firmware_version   = 1,
+        .firmware_size      = 1
+    };
+
+    return result;
+}
+
+arm_ucp_worker_t arm_uc_worker_parameters_active_details = {
+    .command = "/opt/arm/arm_update_active_details.sh",
+    .header   = 1,
+    .firmware = 0,
+    .location = 0,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_ERROR,
+    .post_runner = NULL
+};
+
+arm_ucp_worker_t arm_uc_worker_parameters_activate = {
+    .command = "/opt/arm/arm_update_activate.sh",
+    .header   = 1,
+    .firmware = 1,
+    .location = 0,
+    .offset   = 0,
+    .size     = 0,
+    .success_event = ARM_UC_PAAL_EVENT_ACTIVATE_DONE,
+    .failure_event = ARM_UC_PAAL_EVENT_ACTIVATE_ERROR,
+    .post_runner = NULL
+};
+
+arm_uc_error_t ARM_UC_PAL_Linux_Initialize_Yocto_RPi(ARM_UC_PAAL_UPDATE_SignalEvent_t callback)
+{
+    extern arm_ucp_worker_config_t arm_uc_worker_parameters;
+
+    arm_uc_worker_parameters.activate       = &arm_uc_worker_parameters_activate;
+    arm_uc_worker_parameters.active_details = &arm_uc_worker_parameters_active_details;
+    arm_uc_worker_parameters.details        = NULL;
+    arm_uc_worker_parameters.finalize       = NULL;
+    arm_uc_worker_parameters.initialize     = NULL;
+    arm_uc_worker_parameters.installer      = NULL;
+    arm_uc_worker_parameters.prepare        = NULL;
+    arm_uc_worker_parameters.read           = NULL;
+    arm_uc_worker_parameters.write          = NULL;
+
+    return ARM_UC_PAL_Linux_Initialize(callback);
+}
+
+const ARM_UC_PAAL_UPDATE ARM_UCP_LINUX_YOCTO_RPI =
+{
+    .Initialize                 = ARM_UC_PAL_Linux_Initialize_Yocto_RPi,
+    .GetCapabilities            = ARM_UC_PAL_Linux_GetCapabilities_Yocto_RPi,
+    .GetMaxID                   = ARM_UC_PAL_Linux_GetMaxID,
+    .Prepare                    = ARM_UC_PAL_Linux_Prepare,
+    .Write                      = ARM_UC_PAL_Linux_Write,
+    .Finalize                   = ARM_UC_PAL_Linux_Finalize,
+    .Read                       = ARM_UC_PAL_Linux_Read,
+    .Activate                   = ARM_UC_PAL_Linux_Activate,
+    .GetActiveFirmwareDetails   = ARM_UC_PAL_Linux_GetActiveFirmwareDetails,
+    .GetFirmwareDetails         = ARM_UC_PAL_Linux_GetFirmwareDetails,
+    .GetInstallerDetails        = ARM_UC_PAL_Linux_GetInstallerDetails
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/update-client-pal-linux/arm_uc_pal_linux_generic.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,26 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_LINUX_H
+#define ARM_UC_PAL_LINUX_H
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+extern ARM_UC_PAAL_UPDATE ARM_UCP_LINUX_GENERIC;
+
+#endif // ARM_UC_PAL_LINUX_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/update-client-pal-linux/arm_uc_pal_linux_implementation.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,174 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_LINUX_IMPLEMENTATION_H
+#define ARM_UC_PAL_LINUX_IMPLEMENTATION_H
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialize the underlying storage and set the callback handler.
+ *
+ * @param callback Function pointer to event handler.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback);
+
+/**
+ * @brief Get maximum number of supported storage locations.
+ *
+ * @return Number of storage locations.
+ */
+uint32_t ARM_UC_PAL_Linux_GetMaxID(void);
+
+/**
+ * @brief Prepare the storage layer for a new firmware image.
+ * @details The storage location is set up to receive an image with
+ *          the details passed in the details struct.
+ *
+ * @param location Storage location ID.
+ * @param details Pointer to a struct with firmware details.
+ * @param buffer Temporary buffer for formatting and storing metadata.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_Prepare(uint32_t location,
+                                        const arm_uc_firmware_details_t* details,
+                                        arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Write a fragment to the indicated storage location.
+ * @details The storage location must have been allocated using the Prepare
+ *          call. The call is expected to write the entire fragment before
+ *          signaling completion.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to where the fragment should be written.
+ * @param buffer Pointer to buffer struct with fragment.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_Write(uint32_t location,
+                                      uint32_t offset,
+                                      const arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Close storage location for writing and flush pending data.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_Finalize(uint32_t location);
+
+/**
+ * @brief Read a fragment from the indicated storage location.
+ * @details The function will read until the buffer is full or the end of
+ *          the storage location has been reached. The actual amount of
+ *          bytes read is set in the buffer struct.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to read from.
+ * @param buffer Pointer to buffer struct to store fragment. buffer->size
+ *        contains the intended read size.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ *         buffer->size contains actual bytes read on return.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_Read(uint32_t location,
+                                     uint32_t offset,
+                                     arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Set the firmware image in the slot to be the new active image.
+ * @details This call is responsible for initiating the process for
+ *          applying a new/different image. Depending on the platform this
+ *          could be:
+ *           * An empty call, if the installer can deduce which slot to
+ *             choose from based on the firmware details.
+ *           * Setting a flag to indicate which slot to use next.
+ *           * Decompressing/decrypting/installing the firmware image on
+ *             top of another.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_Activate(uint32_t location);
+
+/**
+ * @brief Get firmware details for the firmware image in the slot passed.
+ * @details This call populates the passed details struct with information
+ *          about the firmware image in the slot passed. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_GetFirmwareDetails(uint32_t location,
+                                                   arm_uc_firmware_details_t* details);
+
+/**
+ * @brief Get firmware details for the actively running firmware.
+ * @details This call populates the passed details struct with information
+ *          about the currently active firmware image. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_GetActiveFirmwareDetails(arm_uc_firmware_details_t* details);
+
+/**
+ * @brief Get details for the component responsible for installation.
+ * @details This call populates the passed details struct with information
+ *          about the local installer. Only the fields marked as supported
+ *          in the capabilities bitmap will have valid values. The
+ *          installer could be the bootloader, a recovery image, or some
+ *          other component responsible for applying the new firmware
+ *          image.
+ *
+ * @param details Pointer to installer details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_Linux_GetInstallerDetails(arm_uc_installer_details_t* details);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ARM_UC_PAL_Linux_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/update-client-pal-linux/arm_uc_pal_linux_implementation_internal.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,137 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_LINUX_IMPLEMENTATION_INTERNAL_H
+#define ARM_UC_PAL_LINUX_IMPLEMENTATION_INTERNAL_H
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+#include <stdbool.h>
+#include <stdio.h>
+
+#ifdef PAL_UPDATE_FIRMWARE_DIR
+#define ARM_UC_FIRMWARE_FOLDER_PATH PAL_UPDATE_FIRMWARE_DIR
+#define ARM_UC_HEADER_FOLDER_PATH PAL_UPDATE_FIRMWARE_DIR
+#endif
+
+#ifndef ARM_UC_FIRMWARE_FOLDER_PATH
+#define ARM_UC_FIRMWARE_FOLDER_PATH "/tmp"
+#endif
+
+#ifndef ARM_UC_HEADER_FOLDER_PATH
+#define ARM_UC_HEADER_FOLDER_PATH "/tmp"
+#endif
+
+#ifndef ARM_UC_INSTALLER_FOLDER_PATH
+#define ARM_UC_INSTALLER_FOLDER_PATH "/tmp"
+#endif
+
+#ifndef ARM_UC_USE_EXTERNAL_HEADER
+#define ARM_UC_USE_EXTERNAL_HEADER 0
+#endif
+
+#define ARM_UC_MAXIMUM_FILE_AND_PATH_LENGTH 128
+#define ARM_UC_MAXIMUM_COMMAND_LENGTH 256
+
+/* This is the type of the "post_runner" function in the worker struct below.
+   This function is called if the worker's command executed succesfully.
+   The callback returns the event that the worker will signal. */
+typedef int32_t (*arm_ucp_c_runner_t)();
+
+typedef struct {
+    const char* command;
+    bool header;
+    bool firmware;
+    bool location;
+    bool offset;
+    bool size;
+    int32_t success_event;
+    int32_t failure_event;
+    arm_ucp_c_runner_t post_runner;
+} arm_ucp_worker_t;
+
+typedef struct {
+    arm_ucp_worker_t* activate;
+    arm_ucp_worker_t* active_details;
+    arm_ucp_worker_t* details;
+    arm_ucp_worker_t* finalize;
+    arm_ucp_worker_t* initialize;
+    arm_ucp_worker_t* installer;
+    arm_ucp_worker_t* prepare;
+    arm_ucp_worker_t* read;
+    arm_ucp_worker_t* write;
+} arm_ucp_worker_config_t;
+
+#if defined(TARGET_IS_PC_LINUX)
+#include <pthread.h>
+typedef struct LinuxWorkerThreadInfo {
+    pthread_mutex_t mutex;
+    pthread_t       thread;
+    pthread_attr_t  attr;
+    int             attr_initialized;
+} linux_worker_thread_info_t;
+#endif
+
+void arm_uc_pal_linux_signal_callback(uint32_t event, bool from_thread);
+
+/* set module variables */
+void arm_uc_pal_linux_internal_set_callback(ARM_UC_PAAL_UPDATE_SignalEvent_t callback);
+void arm_uc_pal_linux_internal_set_offset(uint32_t offset);
+void arm_uc_pal_linux_internal_set_buffer(arm_uc_buffer_t* buffer);
+void arm_uc_pal_linux_internal_set_details(arm_uc_firmware_details_t* details);
+void arm_uc_pal_linux_internal_set_installer(arm_uc_installer_details_t* details);
+void arm_uc_pal_linux_internal_set_location(uint32_t* location);
+
+/* construct file path */
+arm_uc_error_t arm_uc_pal_linux_internal_file_path(char* buffer,
+                                                   size_t buffer_length,
+                                                   const char* folder,
+                                                   const char* type,
+                                                   uint32_t* location);
+
+/* read firmware header */
+arm_uc_error_t arm_uc_pal_linux_internal_read_header(uint32_t* location,
+                                                     arm_uc_firmware_details_t* details);
+
+/* read installer header */
+arm_uc_error_t arm_uc_pal_linux_internal_read_installer(arm_uc_installer_details_t* details);
+
+/* write firmware header*/
+arm_uc_error_t arm_uc_pal_linux_internal_write_header(uint32_t* location,
+                                                      const arm_uc_firmware_details_t* details);
+
+/* read file */
+arm_uc_error_t arm_uc_pal_linux_internal_read(const char* file_path,
+                                              uint32_t offset,
+                                              arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Function to run script in a worker thread before file operations.
+ *
+ * @param params Pointer to arm_ucp_worker_t struct.
+ */
+void* arm_uc_pal_linux_extended_pre_worker(void* params);
+
+/**
+ * @brief Function to run script in a worker thread before file operations.
+ *
+ * @param params Pointer to arm_ucp_worker_t struct.
+ */
+void* arm_uc_pal_linux_extended_post_worker(void* params);
+
+#endif /* ARM_UC_PAL_LINUX_IMPLEMENTATION_INTERNAL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-linux/update-client-pal-linux/arm_uc_pal_linux_openwrt.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,26 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_LINUX_H
+#define ARM_UC_PAL_LINUX_H
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+extern ARM_UC_PAAL_UPDATE ARM_UCP_LINUX_OPENWRT;
+
+#endif // ARM_UC_PAL_LINUX_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-target-specific/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,166 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-target-specific/source/arm_uc_pal_realtek_rtl8195am.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,825 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#if defined(TARGET_REALTEK_RTL8195AM)
+
+#include "update-client-paal/arm_uc_paal_update_api.h"
+#include "update-client-pal-flashiap/arm_uc_pal_flashiap_platform.h"
+
+#include "update-client-common/arm_uc_metadata_header_v2.h"
+#include "update-client-common/arm_uc_common.h"
+
+#include "ota_api.h"
+#include "flash_ext.h"
+
+#define HEADER_SIZE     (OTA_CRC32_OFS + 4)
+
+typedef enum {
+    BASE_ADDRESS_RUNNING,
+    BASE_ADDRESS_SPARE
+} base_address_t;
+
+typedef enum {
+    BASE_SLOT_0 = 0,
+    BASE_SLOT_1 = 1,
+    BASE_SLOT_INVALID
+} base_slot_t;
+
+/**
+ * Base slot, for caching between operations.
+ */
+static base_slot_t arm_uc_base_slot = BASE_SLOT_INVALID;
+
+static const uint32_t arm_uc_address_header[2] = { OTA_REGION1_HEADER, OTA_REGION2_HEADER };
+static const uint32_t arm_uc_address_firmware[2] = { OTA_REGION1_BASE, OTA_REGION2_BASE };
+
+/**
+ * Callback handler.
+ */
+static void (*arm_uc_pal_rtl8195am_callback)(uint32_t) = NULL;
+
+/**
+ * @brief      Signal external event handler with NULL pointer check.
+ *
+ * @param[in]  event  The event
+ */
+static void arm_uc_pal_rtl8195am_signal_internal(uint32_t event)
+{
+    if (arm_uc_pal_rtl8195am_callback)
+    {
+        arm_uc_pal_rtl8195am_callback(event);
+    }
+}
+
+/**
+ * @brief      Create header compatible with the RTL8195AM bootloader
+ *
+ * @param[in]  details  Update client firmware details struct.
+ * @param      buffer   Scratch buffer for creating the header.
+ *
+ * @return     ERR_NONE on success. ERR_INVALID_PARAMETER on failure.
+ */
+static arm_uc_error_t arm_uc_pal_create_realtek_header(const arm_uc_firmware_details_t* details, arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details && buffer && buffer->ptr && (buffer->size_max >= HEADER_SIZE))
+    {
+        /* set tag */
+        buffer->ptr[OTA_TAG_OFS    ] =  OTA_TAG_ID        & 0xFF;
+        buffer->ptr[OTA_TAG_OFS + 1] = (OTA_TAG_ID >>  8) & 0xFF;
+        buffer->ptr[OTA_TAG_OFS + 2] = (OTA_TAG_ID >> 16) & 0xFF;
+        buffer->ptr[OTA_TAG_OFS + 3] = (OTA_TAG_ID >> 24) & 0xFF;
+
+        /* set version tag */
+        buffer->ptr[OTA_VER_OFS    ] =  OTA_VER_ID        & 0xFF;
+        buffer->ptr[OTA_VER_OFS + 1] = (OTA_VER_ID >>  8) & 0xFF;
+        buffer->ptr[OTA_VER_OFS + 2] = (OTA_VER_ID >> 16) & 0xFF;
+        buffer->ptr[OTA_VER_OFS + 3] = (OTA_VER_ID >> 24) & 0xFF;
+
+        /* set timestamp */
+        buffer->ptr[OTA_EPOCH_OFS    ] =  details->version        & 0xFF;
+        buffer->ptr[OTA_EPOCH_OFS + 1] = (details->version >>  8) & 0xFF;
+        buffer->ptr[OTA_EPOCH_OFS + 2] = (details->version >> 16) & 0xFF;
+        buffer->ptr[OTA_EPOCH_OFS + 3] = (details->version >> 24) & 0xFF;
+        buffer->ptr[OTA_EPOCH_OFS + 4] = (details->version >> 32) & 0xFF;
+        buffer->ptr[OTA_EPOCH_OFS + 5] = (details->version >> 40) & 0xFF;
+        buffer->ptr[OTA_EPOCH_OFS + 6] = (details->version >> 48) & 0xFF;
+        buffer->ptr[OTA_EPOCH_OFS + 7] = (details->version >> 56) & 0xFF;
+
+        /* set size */
+        uint32_t size_with_header = details->size + HEADER_SIZE;
+
+        buffer->ptr[OTA_SIZE_OFS    ] =  size_with_header        & 0xFF;
+        buffer->ptr[OTA_SIZE_OFS + 1] = (size_with_header >>  8) & 0xFF;
+        buffer->ptr[OTA_SIZE_OFS + 2] = (size_with_header >> 16) & 0xFF;
+        buffer->ptr[OTA_SIZE_OFS + 3] = (size_with_header >> 24) & 0xFF;
+
+        /* copy hash */
+        for (size_t index = 0; index < ARM_UC_SHA256_SIZE; index++)
+        {
+            buffer->ptr[OTA_HASH_OFS + index] = details->hash[index];
+        }
+
+        /* copy campaign */
+        for (size_t index = 0; index < ARM_UC_GUID_SIZE; index++)
+        {
+            buffer->ptr[OTA_CAMPAIGN_OFS + index] = details->campaign[index];
+        }
+
+        /* set buffer size minus CRC */
+        buffer->size = HEADER_SIZE - 4;
+
+        result.code = ERR_NONE;
+    }
+
+    return result;
+}
+
+/**
+ * @brief      Read header for the image located at the base address.
+ *
+ * @param[in]  base_slot     Header slot.
+ * @param      details       Update client details struct.
+ *
+ * @return     ERR_NONE on success, ERR_INVALID_PARAMETER on failure.
+ */
+static arm_uc_error_t arm_uc_pal_get_realtek_header(base_slot_t base_slot,
+                                                    arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if ((base_slot != BASE_SLOT_INVALID) && details)
+    {
+        uint8_t buffer[HEADER_SIZE] = { 0 };
+
+        int rc = arm_uc_flashiap_read(buffer, arm_uc_address_header[base_slot], sizeof(buffer));
+
+        if (rc == 0)
+        {
+#if 0
+            printf("debug: \r\n");
+            for (size_t index = 0; index < sizeof(buffer); index++)
+            {
+                printf("%02X", buffer[index]);
+            }
+            printf("\r\n");
+#endif
+
+            /* parse tag */
+            uint32_t tag = buffer[OTA_TAG_OFS + 3];
+            tag = (tag << 8) | buffer[OTA_TAG_OFS + 2];
+            tag = (tag << 8) | buffer[OTA_TAG_OFS + 1];
+            tag = (tag << 8) | buffer[OTA_TAG_OFS + 0];
+
+            /* parse version tag */
+            uint32_t version_tag = buffer[OTA_VER_OFS + 3];
+            version_tag = (version_tag << 8) | buffer[OTA_VER_OFS + 2];
+            version_tag = (version_tag << 8) | buffer[OTA_VER_OFS + 1];
+            version_tag = (version_tag << 8) | buffer[OTA_VER_OFS + 0];
+
+            UC_PAAL_TRACE("tag: %" PRIX32, tag);
+            UC_PAAL_TRACE("version_tag: %" PRIX32, version_tag);
+
+            /* check tags */
+            if ((tag == OTA_TAG_ID) && (version_tag == OTA_VER_ID))
+            {
+                /* parse CRC */
+                uint32_t crc_header = buffer[OTA_CRC32_OFS + 3];
+                crc_header = (crc_header << 8) | buffer[OTA_CRC32_OFS + 2];
+                crc_header = (crc_header << 8) | buffer[OTA_CRC32_OFS + 1];
+                crc_header = (crc_header << 8) | buffer[OTA_CRC32_OFS + 0];
+
+                /* calculate crc */
+                uint32_t crc_calculated = arm_uc_crc32(buffer, OTA_CRC32_OFS);
+
+                UC_PAAL_TRACE("CRC header:     %" PRIX32, crc_header);
+                UC_PAAL_TRACE("CRC calculated: %" PRIX32, crc_calculated);
+
+                /* check crc before proceeding */
+                if (crc_header == crc_calculated)
+                {
+                    /* parse size */
+                    uint32_t size = buffer[OTA_SIZE_OFS + 3];
+                    size = (size << 8) | buffer[OTA_SIZE_OFS + 2];
+                    size = (size << 8) | buffer[OTA_SIZE_OFS + 1];
+                    size = (size << 8) | buffer[OTA_SIZE_OFS + 0];
+
+                    /* parse version */
+                    uint64_t version = buffer[OTA_EPOCH_OFS + 7];
+                    version = (version << 8) | buffer[OTA_EPOCH_OFS + 6];
+                    version = (version << 8) | buffer[OTA_EPOCH_OFS + 5];
+                    version = (version << 8) | buffer[OTA_EPOCH_OFS + 4];
+                    version = (version << 8) | buffer[OTA_EPOCH_OFS + 3];
+                    version = (version << 8) | buffer[OTA_EPOCH_OFS + 2];
+                    version = (version << 8) | buffer[OTA_EPOCH_OFS + 1];
+                    version = (version << 8) | buffer[OTA_EPOCH_OFS + 0];
+
+                    /* copy hash */
+                    for (size_t index = 0; index < ARM_UC_SHA256_SIZE; index++)
+                    {
+                        details->hash[index] = buffer[OTA_HASH_OFS + index];
+                    }
+
+                    details->size = size - HEADER_SIZE;
+                    details->version = version;
+
+                    UC_PAAL_TRACE("size: %" PRIu64, details->size);
+                    UC_PAAL_TRACE("version: %" PRIu64, details->version);
+
+#if 0
+                    printf("hash: ");
+                    for (size_t index = 0; index < ARM_UC_SHA256_SIZE; index++)
+                    {
+                        printf("%02X", details->hash[index]);
+                    }
+                    printf("\r\n");
+#endif
+
+                    result.code = ERR_NONE;
+                }
+                else
+                {
+                    UC_PAAL_ERR_MSG("header crc check failed");
+                }
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("invalid header");
+            }
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("error reading from flash");
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief      Find base address of either running or spare firmare slot.
+ *
+ * @param[in]  find  Enum specifying what to find (running or spare slot).
+ *
+ * @return     Base slot.
+ */
+static base_slot_t arm_uc_pal_find_base_slot(base_address_t find)
+{
+    base_slot_t base_slot = BASE_SLOT_0;
+
+    arm_uc_firmware_details_t slot_0 = { 0 };
+    arm_uc_firmware_details_t slot_1 = { 0 };
+
+    /* read header from both slots */
+    arm_uc_error_t result_0 = arm_uc_pal_get_realtek_header(BASE_SLOT_0, &slot_0);
+    arm_uc_error_t result_1 = arm_uc_pal_get_realtek_header(BASE_SLOT_1, &slot_1);
+
+    /* both headers are valid */
+    if ((result_0.error == ERR_NONE) && (result_1.error == ERR_NONE))
+    {
+        /* running firmware has the highest version number */
+        if (find == BASE_ADDRESS_RUNNING)
+        {
+            base_slot = (slot_0.version >= slot_1.version) ? BASE_SLOT_0 : BASE_SLOT_1;
+        }
+        /* spare firmware has the lowest version number */
+        else
+        {
+            /* same test, swap result */
+            base_slot = (slot_0.version >= slot_1.version) ? BASE_SLOT_1 : BASE_SLOT_0;
+        }
+    }
+    /* only slot0 has a valid header */
+    else if (result_0.error == ERR_NONE)
+    {
+        if (find == BASE_ADDRESS_RUNNING)
+        {
+            /* only valid header must be the running one */
+            base_slot = BASE_SLOT_0;
+        }
+        else
+        {
+            /* slot with invalid header can be used as spare */
+            base_slot = BASE_SLOT_1;
+        }
+    }
+    /* only slot1 has a valid header */
+    else if (result_1.error == ERR_NONE)
+    {
+        if (find == BASE_ADDRESS_RUNNING)
+        {
+            /* only valid header must be the running one */
+            base_slot = BASE_SLOT_1;
+        }
+        else
+        {
+            /* slot with invalid header can be used as spare */
+            base_slot = BASE_SLOT_0;
+        }
+    }
+
+    /* if both headers are invalid return 0 */
+
+    return base_slot;
+}
+
+/*****************************************************************************/
+
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_Initialize(void (*callback)(uint32_t))
+{
+    arm_uc_error_t result = { .code = ERR_NONE };
+
+    arm_uc_pal_rtl8195am_callback = callback;
+
+    return result;
+}
+
+/**
+ * @brief Get maximum number of supported storage locations.
+ *
+ * @return Number of storage locations.
+ */
+uint32_t ARM_UC_PAL_RTL8195AM_GetMaxID(void)
+{
+    return 2;
+}
+
+/**
+ * @brief Prepare the storage layer for a new firmware image.
+ * @details The storage location is set up to receive an image with
+ *          the details passed in the details struct.
+ *
+ * @param location Storage location ID.
+ * @param details Pointer to a struct with firmware details.
+ * @param buffer Temporary buffer for formatting and storing metadata.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_Prepare(uint32_t location,
+                                            const arm_uc_firmware_details_t* details,
+                                            arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details && buffer && buffer->ptr)
+    {
+        UC_PAAL_TRACE("Prepare: %" PRIX32 " %" PRIX64 " %" PRIu64,
+                      location,
+                      details->size,
+                      details->version);
+
+        /* find location for the spare slot */
+        arm_uc_base_slot = arm_uc_pal_find_base_slot(BASE_ADDRESS_SPARE);
+
+        UC_PAAL_TRACE("spare base slot: %d", arm_uc_base_slot);
+
+        /* check that the firmware can fit the spare slot */
+        if (((arm_uc_base_slot == BASE_SLOT_0) &&
+             (details->size < (OTA_REGION1_SIZE - FLASH_SECTOR_SIZE))) ||
+            ((arm_uc_base_slot == BASE_SLOT_1) &&
+             (details->size < (OTA_REGION2_SIZE - FLASH_SECTOR_SIZE))))
+        {
+            /* encode firmware details in buffer */
+            result  = arm_uc_pal_create_realtek_header(details, buffer);
+
+            /* make space for new firmware */
+            if (result.error == ERR_NONE)
+            {
+                /* erase header */
+                uint32_t erase_address = arm_uc_address_header[arm_uc_base_slot];
+                uint32_t end_address = erase_address + HEADER_SIZE;
+
+                /* erase */
+                while (erase_address < end_address)
+                {
+                    uint32_t sector_size = arm_uc_flashiap_get_sector_size(erase_address);
+                    int status = arm_uc_flashiap_erase(erase_address, sector_size);
+
+                    UC_PAAL_TRACE("erase: %" PRIX32 " %" PRIX32 " %d",
+                                  erase_address,
+                                  sector_size,
+                                  status);
+
+                    if (status == 0)
+                    {
+                        erase_address += sector_size;
+                    }
+                    else
+                    {
+                        result.code = ERR_INVALID_PARAMETER;
+                        break;
+                    }
+                }
+
+                /* erase firmware */
+                if (result.error == ERR_NONE)
+                {
+                    /* find end address */
+                    erase_address = arm_uc_address_firmware[arm_uc_base_slot];
+                    end_address = erase_address + details->size;
+
+                    /* erase */
+                    while (erase_address < end_address)
+                    {
+                        uint32_t sector_size = arm_uc_flashiap_get_sector_size(erase_address);
+                        int status = arm_uc_flashiap_erase(erase_address, sector_size);
+
+                        UC_PAAL_TRACE("erase: %" PRIX32 " %" PRIX32 " %d",
+                                      erase_address,
+                                      sector_size,
+                                      status);
+
+                        if (status == 0)
+                        {
+                            erase_address += sector_size;
+                        }
+                        else
+                        {
+                            result.code = ERR_INVALID_PARAMETER;
+                            break;
+                        }
+                    }
+
+                    /* write header */
+                    if (result.error == ERR_NONE)
+                    {
+                        UC_PAAL_TRACE("program: %u %" PRIu32,
+                                      arm_uc_address_header[arm_uc_base_slot],
+                                      buffer->size);
+
+                        /* set default return code */
+                        result.code = ERR_NONE;
+
+                        /* write header without CRC */
+                        int status = arm_uc_flashiap_program(buffer->ptr,
+                                                             arm_uc_address_header[arm_uc_base_slot],
+                                                             buffer->size);
+
+                        if (status != 0)
+                        {
+                            /* set return code */
+                            result.code = ERR_INVALID_PARAMETER;
+                        }
+
+                        if (result.error == ERR_NONE)
+                        {
+                            /* signal done */
+                            arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_PREPARE_DONE);
+                        }
+                        else
+                        {
+                            UC_PAAL_ERR_MSG("flash program failed");
+                        }
+                    }
+                    else
+                    {
+                        UC_PAAL_ERR_MSG("flash erase failed");
+                    }
+                }
+                else
+                {
+                    UC_PAAL_ERR_MSG("erase header failed");
+                }
+            }
+            else
+            {
+                UC_PAAL_ERR_MSG("create header failed");
+            }
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("firmware larger than slot");
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Write a fragment to the indicated storage location.
+ * @details The storage location must have been allocated using the Prepare
+ *          call. The call is expected to write the entire fragment before
+ *          signaling completion.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to where the fragment should be written.
+ * @param buffer Pointer to buffer struct with fragment.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_Write(uint32_t location,
+                                          uint32_t offset,
+                                          const arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (buffer && buffer->ptr && (arm_uc_base_slot != BASE_SLOT_INVALID))
+    {
+        /* find location address */
+        uint32_t physical_address = arm_uc_address_firmware[arm_uc_base_slot] + offset;
+
+        UC_PAAL_TRACE("Write: %p %" PRIX32 " %" PRIX32 " %" PRIX32,
+                 buffer->ptr,
+                 buffer->size,
+                 offset,
+                 physical_address);
+
+        /* set default return code */
+        result.code = ERR_NONE;
+
+        for (size_t index = 0; index < buffer->size; )
+        {
+            /* write aligned */
+            size_t modulo = (physical_address + index) % FLASH_PAGE_SIZE;
+            size_t remaining = buffer->size - index;
+            size_t write_size = 0;
+
+            /* fill remaining flash page */
+            if (modulo > 0)
+            {
+                write_size = modulo;
+            }
+            /* write last page */
+            else if (remaining < FLASH_PAGE_SIZE)
+            {
+                write_size = remaining;
+            }
+            /* write full page */
+            else
+            {
+                write_size = FLASH_PAGE_SIZE;
+            }
+
+            int status = arm_uc_flashiap_program(&buffer->ptr[index],
+                                                 physical_address + index,
+                                                 write_size);
+
+            if (status != 0)
+            {
+                /* set return code */
+                result.code = ERR_INVALID_PARAMETER;
+                break;
+            }
+
+            index += write_size;
+        }
+
+        if (result.error == ERR_NONE)
+        {
+            /* signal done */
+            arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_WRITE_DONE);
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("flash program failed");
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Close storage location for writing and flush pending data.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_Finalize(uint32_t location)
+{
+    arm_uc_error_t result = { .code = ERR_NONE };
+
+    UC_PAAL_TRACE("Finalize");
+
+    arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_FINALIZE_DONE);
+
+    return result;
+}
+
+/**
+ * @brief Read a fragment from the indicated storage location.
+ * @details The function will read until the buffer is full or the end of
+ *          the storage location has been reached. The actual amount of
+ *          bytes read is set in the buffer struct.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to read from.
+ * @param buffer Pointer to buffer struct to store fragment. buffer->size
+ *        contains the intended read size.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ *         buffer->size contains actual bytes read on return.
+ */
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_Read(uint32_t location,
+                                         uint32_t offset,
+                                         arm_uc_buffer_t* buffer)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (buffer && buffer->ptr)
+    {
+        /* find the base address for the spare slot if not already set */
+        if (arm_uc_base_slot == BASE_SLOT_INVALID)
+        {
+            arm_uc_base_slot = arm_uc_pal_find_base_slot(BASE_ADDRESS_SPARE);
+        }
+
+        /* calculate actual physical address */
+        uint32_t physical_address = arm_uc_address_firmware[arm_uc_base_slot] + offset;
+
+        UC_PAAL_TRACE("Read: %" PRIX32 " %" PRIX32 " %" PRIX32,
+                      physical_address,
+                      offset,
+                      buffer->size);
+
+        uint32_t read_size = buffer->size;
+
+        int status = arm_uc_flashiap_read(buffer->ptr, physical_address, read_size);
+
+        if (status == 0)
+        {
+            /* set buffer size */
+            buffer->size = read_size;
+
+            /* set return code */
+            result.code = ERR_NONE;
+
+            /* signal done */
+            arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_READ_DONE);
+        }
+        else
+        {
+            UC_PAAL_ERR_MSG("flash read failed");
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set the firmware image in the slot to be the new active image.
+ * @details This call is responsible for initiating the process for
+ *          applying a new/different image. Depending on the platform this
+ *          could be:
+ *           * An empty call, if the installer can deduce which slot to
+ *             choose from based on the firmware details.
+ *           * Setting a flag to indicate which slot to use next.
+ *           * Decompressing/decrypting/installing the firmware image on
+ *             top of another.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_Activate(uint32_t location)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    UC_PAAL_TRACE("Activate");
+
+    if (arm_uc_base_slot != BASE_SLOT_INVALID) 
+    {
+        uint8_t buffer[HEADER_SIZE] = { 0 };
+
+        int status = arm_uc_flashiap_read(buffer, arm_uc_address_header[arm_uc_base_slot], sizeof(buffer));
+
+        if (status == 0)
+        {
+            /* calculate CRC */
+            uint32_t crc = arm_uc_crc32(buffer, OTA_CRC32_OFS);
+
+            buffer[0] =  crc        & 0xFF;
+            buffer[1] = (crc >>  8) & 0xFF;
+            buffer[2] = (crc >> 16) & 0xFF;
+            buffer[3] = (crc >> 24) & 0xFF;
+
+            /* set crc in header to signal the bootloader that the image is ready */
+            status = arm_uc_flashiap_program(buffer, arm_uc_address_header[arm_uc_base_slot] + OTA_CRC32_OFS, 4);
+
+            if (status == 0)
+            {
+                /* set return code */
+                result.code = ERR_NONE;
+
+                /* signal done */
+                arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_ACTIVATE_DONE);
+            }
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get firmware details for the firmware image in the slot passed.
+ * @details This call populates the passed details struct with information
+ *          about the firmware image in the slot passed. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetFirmwareDetails(
+                                        uint32_t location,
+                                        arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    /* this function is only used by the mbed Bootloader */
+
+    return result;
+}
+
+/*****************************************************************************/
+
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetActiveDetails(arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        UC_PAAL_TRACE("GetActiveDetails");
+
+        /* find running slot */
+        base_slot_t base_slot = arm_uc_pal_find_base_slot(BASE_ADDRESS_RUNNING);
+
+        UC_PAAL_TRACE("active base: %d", base_slot);
+
+        result = arm_uc_pal_get_realtek_header(base_slot, details);
+
+        /* signal event if operation was successful */
+        if (result.error == ERR_NONE)
+        {
+            arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE);
+        }
+    }
+
+    return result;
+}
+
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetInstallerDetails(arm_uc_installer_details_t* details)
+{
+    arm_uc_error_t result = { .code = ERR_INVALID_PARAMETER };
+
+    if (details)
+    {
+        /* reset installer details struct */
+        memset(&details->arm_hash, 0, ARM_UC_SHA256_SIZE);
+        memset(&details->oem_hash, 0, ARM_UC_SHA256_SIZE);
+        details->layout = 0;
+
+        /* the magic tag identifies the bootloader it is compatible with */
+        details->oem_hash[0] = (OTA_TAG_ID >> 24) & 0xFF;
+        details->oem_hash[1] = (OTA_TAG_ID >> 16) & 0xFF;
+        details->oem_hash[2] = (OTA_TAG_ID >>  8) & 0xFF;
+        details->oem_hash[3] =  OTA_TAG_ID        & 0xFF;
+
+        details->oem_hash[4] = (OTA_VER_ID >> 24) & 0xFF;
+        details->oem_hash[5] = (OTA_VER_ID >> 16) & 0xFF;
+        details->oem_hash[6] = (OTA_VER_ID >>  8) & 0xFF;
+        details->oem_hash[7] =  OTA_VER_ID        & 0xFF;
+
+        result.code = ERR_NONE;
+
+        arm_uc_pal_rtl8195am_signal_internal(ARM_UC_PAAL_EVENT_GET_INSTALLER_DETAILS_DONE);
+    }
+
+    return result;
+}
+
+ARM_UC_PAAL_UPDATE_CAPABILITIES ARM_UC_PAL_RTL8195AM_GetCapabilities(void)
+{
+    ARM_UC_PAAL_UPDATE_CAPABILITIES result = {
+        .installer_arm_hash = 0,
+        .installer_oem_hash = 0,
+        .installer_layout   = 0,
+        .firmware_hash      = 1,
+        .firmware_hmac      = 0,
+        .firmware_campaign  = 0,
+        .firmware_version   = 1,
+        .firmware_size      = 1
+    };
+
+    return result;
+}
+
+const ARM_UC_PAAL_UPDATE ARM_UCP_REALTEK_RTL8195AM =
+{
+    .Initialize                 = ARM_UC_PAL_RTL8195AM_Initialize,
+    .GetCapabilities            = ARM_UC_PAL_RTL8195AM_GetCapabilities,
+    .GetMaxID                   = ARM_UC_PAL_RTL8195AM_GetMaxID,
+    .Prepare                    = ARM_UC_PAL_RTL8195AM_Prepare,
+    .Write                      = ARM_UC_PAL_RTL8195AM_Write,
+    .Finalize                   = ARM_UC_PAL_RTL8195AM_Finalize,
+    .Read                       = ARM_UC_PAL_RTL8195AM_Read,
+    .Activate                   = ARM_UC_PAL_RTL8195AM_Activate,
+    .GetActiveFirmwareDetails   = ARM_UC_PAL_RTL8195AM_GetActiveDetails,
+    .GetFirmwareDetails         = ARM_UC_PAL_RTL8195AM_GetFirmwareDetails,
+    .GetInstallerDetails        = ARM_UC_PAL_RTL8195AM_GetInstallerDetails
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/pal-target-specific/update-client-pal-target-specific/arm_uc_pal_realtek_rtl8195am.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,147 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_PAL_RTL8195AM_IMPLEMENTATION_H
+#define ARM_UC_PAL_RTL8195AM_IMPLEMENTATION_H
+
+#include "update-client-common/arm_uc_error.h"
+#include "update-client-common/arm_uc_types.h"
+#include "update-client-paal/arm_uc_paal_update_api.h"
+
+extern ARM_UC_PAAL_UPDATE ARM_UCP_REALTEK_RTL8195AM;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_Initialize(ARM_UC_PAAL_UPDATE_SignalEvent_t callback);
+
+/**
+ * @brief Get maximum number of supported storage locations.
+ *
+ * @return Number of storage locations.
+ */
+uint32_t ARM_UC_PAL_RTL8195AM_GetMaxID(void);
+
+/**
+ * @brief Prepare the storage layer for a new firmware image.
+ * @details The storage location is set up to receive an image with
+ *          the details passed in the details struct.
+ *
+ * @param location Storage location ID.
+ * @param details Pointer to a struct with firmware details.
+ * @param buffer Temporary buffer for formatting and storing metadata.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_Prepare(uint32_t location,
+                                            const arm_uc_firmware_details_t* details,
+                                            arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Write a fragment to the indicated storage location.
+ * @details The storage location must have been allocated using the Prepare
+ *          call. The call is expected to write the entire fragment before
+ *          signaling completion.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to where the fragment should be written.
+ * @param buffer Pointer to buffer struct with fragment.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_Write(uint32_t location,
+                                          uint32_t offset,
+                                          const arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Close storage location for writing and flush pending data.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_Finalize(uint32_t location);
+
+/**
+ * @brief Read a fragment from the indicated storage location.
+ * @details The function will read until the buffer is full or the end of
+ *          the storage location has been reached. The actual amount of
+ *          bytes read is set in the buffer struct.
+ *
+ * @param location Storage location ID.
+ * @param offset Offset in bytes to read from.
+ * @param buffer Pointer to buffer struct to store fragment. buffer->size
+ *        contains the intended read size.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ *         buffer->size contains actual bytes read on return.
+ */
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_Read(uint32_t location,
+                                         uint32_t offset,
+                                         arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Set the firmware image in the slot to be the new active image.
+ * @details This call is responsible for initiating the process for
+ *          applying a new/different image. Depending on the platform this
+ *          could be:
+ *           * An empty call, if the installer can deduce which slot to
+ *             choose from based on the firmware details.
+ *           * Setting a flag to indicate which slot to use next.
+ *           * Decompressing/decrypting/installing the firmware image on
+ *             top of another.
+ *
+ * @param location Storage location ID.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_Activate(uint32_t location);
+
+/**
+ * @brief Get firmware details for the firmware image in the slot passed.
+ * @details This call populates the passed details struct with information
+ *          about the firmware image in the slot passed. Only the fields
+ *          marked as supported in the capabilities bitmap will have valid
+ *          values.
+ *
+ * @param details Pointer to firmware details struct to be populated.
+ * @return Returns ERR_NONE on accept, and signals the event handler with
+ *         either DONE or ERROR when complete.
+ *         Returns ERR_INVALID_PARAMETER on reject, and no signal is sent.
+ */
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetFirmwareDetails(
+                                        uint32_t location,
+                                        arm_uc_firmware_details_t* details);
+
+/*****************************************************************************/
+
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetActiveDetails(arm_uc_firmware_details_t* details);
+
+arm_uc_error_t ARM_UC_PAL_RTL8195AM_GetInstallerDetails(arm_uc_installer_details_t* details);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ARM_UC_PAL_RTL8195AM_IMPLEMENTATION_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,166 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/source/arm_uc_http_socket.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,122 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-source-http-socket/arm_uc_http_socket.h"
+#include "update-client-common/arm_uc_common.h"
+
+#include "arm_uc_http_socket_private.h"
+
+/*****************************************************************************/
+/* Public Function                                                           */
+/*****************************************************************************/
+
+/**
+ * @brief Initialize Http module.
+ * @details Function pointer to event handler is passed as argument.
+ *
+ * @param context Struct holding all global variables.
+ * @param handler Event handler for signaling when each operation is complete.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_HttpSocket_Initialize(arm_uc_http_socket_context_t* context,
+                                             ARM_UCS_HttpEvent_t handler)
+{
+    return arm_uc_socket_initialize(context, handler);
+}
+
+/**
+ * @brief Resets HTTP socket to uninitialized state and clears memory struct.
+ * @details HTTP sockets must be initialized again before use.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_HttpSocket_Terminate()
+{
+    return arm_uc_socket_terminate();
+}
+
+/**
+ * @brief Get hash for resource at URI.
+ * @details Store hash in provided buffer. Enclosing "" and '\0' are removed.
+ *
+ *          Event generated: EVENT_HASH
+ *
+ * @param uri Pointer to struct with resource location.
+ * @param buffer Pointer to structure with buffer location, maxSize, and size.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_HttpSocket_GetHash(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer)
+{
+    return arm_uc_socket_get(uri, buffer, UINT32_MAX, RQST_TYPE_HASH_ETAG);
+}
+
+/**
+ * @brief Get date for resource at URI.
+ * @details Store Last-Modified data in provided buffer. Enclosing "" and '\0' are removed.
+ *
+ *          Event generated: EVENT_DATE
+ *
+ * @param uri Pointer to struct with resource location.
+ * @param buffer Pointer to structure with buffer location, maxSize, and size.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_HttpSocket_GetDate(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer)
+{
+    return arm_uc_socket_get(uri, buffer, UINT32_MAX, RQST_TYPE_HASH_DATE);
+}
+
+/**
+ * @brief Get full resource at URI.
+ * @details Download resource at URI and store in provided buffer.
+ *          If the provided buffer is not big enough to contain the whole resource
+ *          what can fit in the buffer will be downloaded.
+ *          The user can then use GetFragment to download the rest.
+
+ *          Events generated: EVENT_DOWNLOAD_PENDING if there is still data to
+ *          download and EVENT_DOWNLOAD_DONE if the file is completely downloaded.
+ *
+ * @param uri Pointer to structure with resource location.
+ * @param buffer Pointer to structure with buffer location, maxSize, and size.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_HttpSocket_GetFile(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer)
+{
+    return arm_uc_socket_get(uri, buffer, UINT32_MAX, RQST_TYPE_GET_FILE);
+}
+
+/**
+ * @brief Get partial resource at URI.
+ * @details Download resource at URI from given offset and store in buffer.
+ *
+ *          The buffer maxSize determines how big a fragment to download. If the
+ *          buffer is larger than the requested fragment (offset to end-of-file)
+ *          the buffer size is set to indicate the number of available bytes.
+ *
+ *          Events generated: EVENT_DOWNLOAD_PENDING if there is still data to
+ *          download and EVENT_DOWNLOAD_DONE if the file is completely downloaded.
+ *
+ * @param uri Pointer to structure with resource location.
+ * @param buffer Pointer to structure with buffer location, maxSize, and size.
+ * @param offset Offset in resource to begin download from.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_HttpSocket_GetFragment(arm_uc_uri_t* uri,
+                                              arm_uc_buffer_t* buffer,
+                                              uint32_t offset)
+{
+    return arm_uc_socket_get(uri, buffer, offset, RQST_TYPE_GET_FRAG);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/source/arm_uc_http_socket_private.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1230 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "arm_uc_http_socket_private.h"
+
+#include "arm_uc_socket_help.h"
+
+#include <pal.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+
+#if !defined(ARM_UC_SOCKET_TIMEOUT_MS)
+#define ARM_UC_SOCKET_TIMEOUT_MS 10000 /* 10 seconds */
+#endif
+
+/* Pointer to struct containing all global variables.
+   Can be dynamically allocated and deallocated.
+*/
+static arm_uc_http_socket_context_t* context = NULL;
+
+/******************************************************************************
+ * Internal helpers for DNS resolution
+ * These functions are used to implement DNS resolution in two variants:
+ * asynchronous (MBED_CONF_MBED_CLIENT_DNS_USE_THREAD == 1) or
+ * synchronous (otherwise). */
+
+#if MBED_CONF_MBED_CLIENT_DNS_USE_THREAD /* use asychronous DNS calls */
+
+#define arm_uc_get_address_info pal_getAddressInfoAsync
+
+static arm_uc_error_t arm_uc_start_dns_timer()
+{
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_FAILED };
+
+    if (context)
+    {
+        palStatus_t pal_inner = pal_osTimerStart(context->timeout_timer_id,
+                                                ARM_UC_SOCKET_TIMEOUT_MS);
+        if (pal_inner != PAL_SUCCESS)
+        {
+            UC_SRCE_ERR_MSG("Start socket timeout timer failed pal status: 0x%" PRIu32,
+                            (uint32_t)pal_inner);
+            arm_uc_socket_close();
+        }
+        else
+        {
+            result.code = SRCE_ERR_NONE;
+        }
+    }
+    return result;
+}
+
+static arm_uc_error_t arm_uc_stop_dns_timer()
+{
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_FAILED };
+
+    if (context)
+    {
+        palStatus_t pal_inner = pal_osTimerStop(context->timeout_timer_id);
+        if (pal_inner != PAL_SUCCESS)
+        {
+            UC_SRCE_ERR_MSG("pal_osTimerStop returned 0x%" PRIX32,
+                            (uint32_t) pal_inner);
+        }
+        else
+        {
+            result.code = SRCE_ERR_NONE;
+        }
+    }
+    return result;
+}
+
+#else /* use synchronous DNS calls */
+
+static palStatus_t arm_uc_get_address_info(const char* url, palSocketAddress_t* address,
+                                           palSocketLength_t* address_length,
+                                           palGetAddressInfoAsyncCallback_t callback,
+                                           void* argument)
+{
+    /* Run the synchronous DNS request and call the callback
+       immediately after the request is done */
+    palStatus_t pal_inner = pal_getAddressInfo(url, address, address_length);
+    /* Call the callback with the result of pal_getAddressInfo.
+       The callback will examine the value of pal_inner and act
+       accordingly (see arm_uc_dns_callback below). */
+    callback(url, address, address_length, pal_inner, argument);
+    /* Always return PAL_SUCCESS so that the caller can continue
+       execution. The actual check for success/failure happens
+       in the callback (see the comment above). */
+    return PAL_SUCCESS;
+}
+
+/* Timers are not used for synchronous DNS calls,
+   since the synchronous call can't be interrupted */
+static arm_uc_error_t arm_uc_start_dns_timer()
+{
+    return (arm_uc_error_t){ SRCE_ERR_NONE };
+}
+
+static arm_uc_error_t arm_uc_stop_dns_timer()
+{
+    return (arm_uc_error_t){ SRCE_ERR_NONE };
+}
+
+#endif // MBED_CONF_MBED_CLIENT_DNS_USE_THREAD
+
+/*****************************************************************************/
+
+/**
+ * @brief Initialize Http module.
+ * @details A memory struct is passed as well as a function pointer for event
+ *          handling.
+ *
+ * @param context Struct holding all global variables.
+ * @param handler Event handler for signaling when each operation is complete.
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_socket_initialize(arm_uc_http_socket_context_t* _context,
+                                        void (*handler)(uint32_t))
+{
+    UC_SRCE_TRACE("arm_uc_socket_initialize");
+
+    /* default return value */
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_FAILED };
+
+    /* save global context */
+    context = _context;
+
+    if (context)
+    {
+        /* initialize global variables */
+        context->callback_handler = handler;
+
+        context->request_uri = NULL;
+        context->request_buffer = NULL;
+        context->request_offset = 0;
+        context->request_type = RQST_TYPE_NONE;
+
+        context->socket_state = STATE_DISCONNECTED;
+        context->expected_event = SOCKET_EVENT_UNDEFINED;
+        context->expected_remaining = 0;
+
+        context->socket = NULL;
+
+        context->isr_callback_counter = 0;
+
+        context->timeout_timer_id = 0;
+
+        context->cache_address.addressType = 0;
+        memset(context->cache_address.addressData, 0, PAL_NET_MAX_ADDR_SIZE);
+        context->cache_address_length = 0;
+
+        /* set return value to success */
+        result = (arm_uc_error_t){ SRCE_ERR_NONE };
+    }
+
+    return result;
+}
+
+/**
+ * @brief Resets HTTP socket to uninitialized state and clears memory struct.
+ * @details HTTP sockets must be initialized again before use.
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_socket_terminate()
+{
+    /* default return value */
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_FAILED };
+
+    if (context)
+    {
+        /* close socket */
+        arm_uc_socket_close();
+
+        /* reset all global variables */
+        context->request_uri = NULL;
+        context->request_buffer = NULL;
+        context->request_offset = 0;
+        context->request_type = RQST_TYPE_NONE;
+
+        context->socket_state = STATE_DISCONNECTED;
+        context->expected_event = SOCKET_EVENT_UNDEFINED;
+        context->expected_remaining = 0;
+
+        context->socket = NULL;
+
+        context = NULL;
+
+        result = (arm_uc_error_t){ SRCE_ERR_NONE };
+    }
+
+    return result;
+}
+
+/**
+ * @brief Get resource at URI.
+ * @details Download resource at URI from given offset and store in buffer.
+ *          Events are generated when download finish or on error
+ *
+ * @param uri Pointer to structure with resource location.
+ * @param buffer Pointer to structure with buffer location, maxSize, and size.
+ * @param offset Offset in resource to begin download from.
+ * @param type Indicate what type of request that was initiated.
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_socket_get(arm_uc_uri_t* uri,
+                                 arm_uc_buffer_t* buffer,
+                                 uint32_t offset,
+                                 arm_uc_rqst_t type)
+{
+    UC_SRCE_TRACE("arm_uc_socket_get");
+
+    /* default return value */
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+
+    /* check for NULL pointers */
+    if (uri &&
+        uri->scheme &&
+        uri->host &&
+        uri->path &&
+        buffer &&
+        buffer->ptr &&
+        context)
+    {
+        /* parameters are valid */
+        result.code = SRCE_ERR_NONE;
+
+        /* store request */
+        context->request_uri = uri;
+        context->request_buffer = buffer;
+        context->request_offset = offset;
+        context->request_type = type;
+
+        /* clear buffer */
+        context->request_buffer->size = 0;
+
+        UC_SRCE_TRACE("Socket State: %d", context->socket_state);
+
+        /* connect socket if not already connected */
+        result = arm_uc_socket_connect();
+    }
+
+    return result;
+}
+
+/**
+ * @brief Connect to server set in the global URI struct.
+ * @details Connecting generates a socket event, which automatically processes
+ *          the request passed in arm_uc_socket_get. If a DNS request must
+ *          be made, this call initiates an asynchronous DNS request. After
+ *          the request is done, the connection process will be resumed in
+ *          arm_uc_socket_finish_connect().
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_socket_connect()
+{
+    /* default return value */
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_FAILED };
+
+    /* NULL pointer check */
+    if (context && context->request_uri)
+    {
+        if (context->socket_state == STATE_DISCONNECTED)
+        {
+            result = (arm_uc_error_t){ SRCE_ERR_NONE };
+
+            /* create socket timeout timer */
+            palStatus_t pal_inner = pal_osTimerCreate(arm_uc_timeout_timer_callback,
+                                                      NULL,
+                                                      palOsTimerOnce,
+                                                      &context->timeout_timer_id);
+
+            if (pal_inner != PAL_SUCCESS)
+            {
+                UC_SRCE_ERR_MSG("socket timeout timer creation failed pal status: 0x%" PRIu32,
+                                (uint32_t)pal_inner);
+                arm_uc_socket_close();
+                result = (arm_uc_error_t){ SRCE_ERR_FAILED };
+            }
+            else
+            {
+                /* start socket timeout timer */
+                result = arm_uc_start_dns_timer();
+            }
+            if (result.code == SRCE_ERR_NONE)
+            {
+                /* initiate DNS lookup */
+                pal_inner = arm_uc_get_address_info(context->request_uri->host,
+                                                    &context->cache_address,
+                                                    &context->cache_address_length,
+                                                    arm_uc_dns_callback,
+                                                    NULL);
+
+                if (pal_inner != PAL_SUCCESS)
+                {
+                    UC_SRCE_ERR_MSG("pal_getAddressInfoAsync (DNS) failed pal status: 0x%" PRIu32,
+                                    (uint32_t)pal_inner);
+                    arm_uc_socket_close();
+                    result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+                }
+                else
+                {
+                    UC_SRCE_TRACE("Initiated DNS lookup");
+                }
+            }
+        }
+        else if (context->socket_state == STATE_CONNECTED_IDLE) /* already connected */
+        {
+            /* Socket already connected, progress state machine */
+            palStatus_t pal_inner = pal_osTimerStart(context->timeout_timer_id,
+                                         ARM_UC_SOCKET_TIMEOUT_MS);
+
+            if (pal_inner != PAL_SUCCESS)
+            {
+                UC_SRCE_ERR_MSG("Start socket timeout timer failed pal status: 0x%" PRIu32,
+                                (uint32_t)pal_inner);
+                arm_uc_socket_close();
+                return (arm_uc_error_t){ SRCE_ERR_FAILED };
+            }
+
+            UC_SRCE_TRACE("Socket already connected, progress state machine");
+            context->expected_event = SOCKET_EVENT_CONNECT_DONE;
+            result = (arm_uc_error_t){ SRCE_ERR_NONE };
+            arm_uc_socket_isr(NULL);
+        }
+        else /* socket busy */
+        {
+            UC_SRCE_TRACE("Socket Busy");
+            result = (arm_uc_error_t){ SRCE_ERR_BUSY };
+        }
+    }
+
+    UC_SRCE_TRACE("arm_uc_socket_connect returning %s", ARM_UC_err2Str(result));
+
+    return result;
+}
+
+/**
+ * @brief Finishes connecting to the server requested in a previous call to
+ *        arm_uc_socket_connect().
+ * @details This function is called after the DNS resolution for the host
+ *          requested in arm_uc_socket_get() above is done. It finishes the
+ *          connection process by creating a socket and connecting it.
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_socket_finish_connect()
+{
+    /* default return value */
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_FAILED };
+
+    /* NULL pointer check */
+    if (context && context->request_uri)
+    {
+        result = (arm_uc_error_t){ SRCE_ERR_NONE };
+
+        UC_SRCE_TRACE("socket: address type is: %u", context->cache_address.addressType);
+        /* create new async PAL socket */
+        palStatus_t pal_inner = pal_asynchronousSocket((palSocketDomain_t)context->cache_address.addressType,
+                                                       PAL_SOCK_STREAM,
+                                                       true,
+                                                       0,
+                                                       arm_uc_socket_isr,
+                                                       &context->socket);
+
+        if (pal_inner != PAL_SUCCESS)
+        {
+            UC_SRCE_ERR_MSG("socket creation failed with pal status: 0x%" PRIX32,
+                            (uint32_t) pal_inner);
+            arm_uc_socket_close();
+            result = (arm_uc_error_t){ SRCE_ERR_FAILED };
+        }
+        else
+        {
+            UC_SRCE_TRACE("socket: create success");
+        }
+
+        /* start socket timeout timer */
+        if (result.code == SRCE_ERR_NONE)
+        {
+            pal_inner = pal_osTimerStart(context->timeout_timer_id,
+                                            ARM_UC_SOCKET_TIMEOUT_MS);
+
+            if (pal_inner != PAL_SUCCESS)
+            {
+                UC_SRCE_ERR_MSG("Start socket timeout timer failed");
+                arm_uc_socket_close();
+                result = (arm_uc_error_t){ SRCE_ERR_FAILED };
+            }
+        }
+
+        /* convert URI to PAL address if cache is not empty */
+        if ((result.code == SRCE_ERR_NONE) &&
+            (context->cache_address_length != 0))
+        {
+            /* set PAL port */
+            pal_inner = pal_setSockAddrPort(&context->cache_address,
+                                            context->request_uri->port);
+
+            if (pal_inner != PAL_SUCCESS)
+            {
+                UC_SRCE_ERR_MSG("pal_setSockAddrPort returned: 0x%" PRIX32,
+                                (uint32_t) pal_inner);
+                arm_uc_socket_close();
+                result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+            }
+        }
+
+        /* connect to server */
+        if (result.code == SRCE_ERR_NONE)
+        {
+            pal_inner = pal_connect(context->socket,
+                                    &context->cache_address,
+                                    context->cache_address_length);
+            UC_SRCE_TRACE("pal_connect returned: 0x%" PRIX32,
+                            (uint32_t) pal_inner);
+
+            if (pal_inner == PAL_SUCCESS) /* synchronous finish */
+            {
+                context->socket_state = STATE_CONNECTED_IDLE;
+                context->expected_event = SOCKET_EVENT_CONNECT_DONE;
+                result = (arm_uc_error_t){ SRCE_ERR_NONE };
+                arm_uc_socket_isr(NULL);
+            }
+            else if (pal_inner == PAL_ERR_SOCKET_IN_PROGRES) /* asynchronous finish */
+            {
+                context->expected_event = SOCKET_EVENT_CONNECT_DONE;
+                result = (arm_uc_error_t){ SRCE_ERR_NONE };
+            }
+            else
+            {
+                UC_SRCE_ERR_MSG("Error: socket connection failed");
+                result = (arm_uc_error_t){ SRCE_ERR_FAILED };
+                arm_uc_socket_close();
+            }
+        }
+    }
+
+    UC_SRCE_TRACE("arm_uc_socket_finish_connect returning %s", ARM_UC_err2Str(result));
+
+    return result;
+}
+
+
+/**
+ * @brief Send request passed in arm_uc_socket_get.
+ * @details This call assumes the HTTP socket is already connected to server.
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_socket_send_request()
+{
+    /* default return value */
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_FAILED };
+
+    /* NULL pointer check */
+    if (context)
+    {
+        /* get local references */
+        arm_uc_buffer_t* request_buffer = context->request_buffer;
+        arm_uc_uri_t*    request_uri    = context->request_uri;
+        arm_uc_rqst_t    request_type   = context->request_type;
+
+        /* template for generating HTTP requests */
+        static const char HTTP_HEADER_TEMPLATE[] =
+            "%s %s HTTP/1.1\r\n" // status line
+            "Host: %s\r\n"; // mandated for http 1.1
+
+        if (request_type == RQST_TYPE_HASH_ETAG ||
+            request_type == RQST_TYPE_HASH_DATE)
+        {
+            /* construct ETag and Date request header */
+            request_buffer->size = snprintf((char *) request_buffer->ptr,
+                                            request_buffer->size_max,
+                                            HTTP_HEADER_TEMPLATE,
+                                            "HEAD",
+                                            request_uri->path,
+                                            request_uri->host);
+        }
+        else
+        {
+            /* construct download header */
+            request_buffer->size = snprintf((char *) request_buffer->ptr,
+                                            request_buffer->size_max,
+                                            HTTP_HEADER_TEMPLATE,
+                                            "GET",
+                                            request_uri->path,
+                                            request_uri->host);
+        }
+
+        if (request_type == RQST_TYPE_GET_FRAG)
+        {
+            /* construct the Range field that makes this a partial content request */
+            request_buffer->size += snprintf((char *) request_buffer->ptr + request_buffer->size,
+                                             request_buffer->size_max - request_buffer->size,
+                                             "Range: bytes=%" PRIu32 "-%" PRIu32 "\r\n",
+                                             context->request_offset,
+                                             context->request_offset + request_buffer->size_max - 1);
+        }
+
+        /* terminate request with a carriage return and newline */
+        request_buffer->size += snprintf((char *) request_buffer->ptr + request_buffer->size,
+                                         request_buffer->size_max - request_buffer->size,
+                                         "\r\n");
+
+        /* terminate string */
+        request_buffer->ptr[request_buffer->size] = '\0';
+        UC_SRCE_TRACE("%s", request_buffer->ptr);
+
+        /*************************************************************************/
+
+        size_t bytes_sent = 0;
+
+        /* send HTTP request */
+        palStatus_t pal_result = pal_send(context->socket,
+                                          request_buffer->ptr,
+                                          request_buffer->size,
+                                          &bytes_sent);
+
+        if (pal_result == PAL_SUCCESS) /* asynchronous finish */
+        {
+            UC_SRCE_TRACE("send success");
+
+            /* reset buffer and prepare to receive header */
+            request_buffer->size = 0;
+            context->socket_state = STATE_PROCESS_HEADER;
+            context->expected_event = SOCKET_EVENT_SEND_DONE;
+
+            result = (arm_uc_error_t){ SRCE_ERR_NONE };
+        }
+        else if(pal_result == PAL_ERR_SOCKET_WOULD_BLOCK)
+        {
+            UC_SRCE_TRACE("send would block, will retry");
+
+            /* keep current state and force callback to retry sending */
+            request_buffer->size = 0;
+            arm_uc_socket_isr(NULL);
+
+            result = (arm_uc_error_t){ SRCE_ERR_NONE };
+        }
+        else
+        {
+            UC_SRCE_TRACE("send error 0x%" PRIX32, (uint32_t) pal_result);
+
+            /* clean up */
+            arm_uc_socket_error(UCS_HTTP_EVENT_ERROR);
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Receive data from HTTP socket.
+ * @details Data is stored in global buffer. The call will automatically retry
+ *          if the socket is busy.
+ */
+void arm_uc_socket_receive()
+{
+    /* NULL pointer check */
+    if (context)
+    {
+        /* get local references */
+        arm_uc_buffer_t* request_buffer = context->request_buffer;
+
+        size_t received_bytes = 0;
+        palStatus_t pal_result = PAL_SUCCESS;
+
+        while ( (context->socket_state != STATE_DISCONNECTED) &&
+                (pal_result == PAL_SUCCESS) &&
+                context->request_buffer )
+        {
+            if (request_buffer->size >= request_buffer->size_max)
+            {
+                UC_SRCE_ERR_MSG("There is no space in the buffer left");
+                arm_uc_socket_error(UCS_HTTP_EVENT_ERROR_BUFFER_SIZE);
+                break;
+            }
+
+            /* append data from socket receive buffer to request buffer. */
+            pal_result = pal_recv(context->socket,
+                                  &(request_buffer->ptr[request_buffer->size]),
+                                  request_buffer->size_max - request_buffer->size,
+                                  &received_bytes);
+
+            if (pal_result == PAL_SUCCESS && received_bytes > 0)
+            {
+                /* Note: the proper formatter %zu is not supported on mbed's libc,
+                 * hence the casts to difference type.
+                 */
+                UC_SRCE_TRACE("recv success: %lu bytes received",
+                              (unsigned long)received_bytes);
+
+                if (request_buffer->size + received_bytes > request_buffer->size_max)
+                {
+                    UC_SRCE_ERR_MSG("Got more data than available space in the buffer");
+                    arm_uc_socket_error(UCS_HTTP_EVENT_ERROR_BUFFER_SIZE);
+                    break;
+                }
+
+                /* update buffer size with received bytes */
+                request_buffer->size += received_bytes;
+
+                /* update expected event to signal receive done */
+                context->expected_event = SOCKET_EVENT_RECEIVE_CONTINUE;
+
+                /* received data */
+                if (context->socket_state == STATE_PROCESS_HEADER)
+                {
+                    /* expecting HTTP header */
+                    arm_uc_socket_process_header();
+                }
+                else if (context->socket_state == STATE_PROCESS_BODY)
+                {
+                    /* expecting body */
+                    arm_uc_socket_process_body();
+                }
+                else
+                {
+                    /* unexpected data, generate error and clean up */
+                    arm_uc_socket_error(UCS_HTTP_EVENT_ERROR);
+                }
+            }
+            else if (pal_result == PAL_ERR_SOCKET_WOULD_BLOCK)
+            {
+                /* Note: at least on mbed os the pal_recv() returns garbage on recievedDataSize
+                 * if the socket call returns anything but PAL_SUCCESS, so this needs to
+                 * recalculate the remaining bytes count.
+                 */
+                UC_SRCE_TRACE("recv: pending: %" PRIu32,
+                              (request_buffer->size_max - request_buffer->size));
+
+                /* update expected event to retry receiving */
+                context->expected_event = SOCKET_EVENT_RECEIVE_CONTINUE;
+            }
+            else
+            {
+                UC_SRCE_ERR_MSG("Error: socket receive failed");
+
+                /* clean up */
+                arm_uc_socket_error(UCS_HTTP_EVENT_ERROR);
+            }
+        }
+    }
+}
+
+/**
+ * @brief Function is called when some data has been received but an HTTP
+ *        header has yet to be processed.
+ * @details Function is called repeatedly until a header is found or the buffer
+ *          is full. Once a header is found, the ETag, date, or content length
+ *          is parsed. For file and fragment downloads the receive process is
+ *          restarted and the header is erased.
+ */
+void arm_uc_socket_process_header()
+{
+    /* NULL pointer check */
+    if (context)
+    {
+        /* get local references */
+        arm_uc_buffer_t* request_buffer = context->request_buffer;
+        arm_uc_uri_t*    request_uri    = context->request_uri;
+        arm_uc_rqst_t    request_type   = context->request_type;
+        uint32_t         request_offset = context->request_offset;
+
+        /* setup default return to be failure */
+        bool request_successfully_processed = false;
+
+        uint32_t index = arm_uc_strnstrn(request_buffer->ptr,
+                                         request_buffer->size,
+                                         (const uint8_t*) "\r\n\r\n",
+                                         4);
+
+        /* Continue receiving if full header is not found. */
+        if (index > request_buffer->size)
+        {
+            request_successfully_processed = true;
+            arm_uc_socket_receive();
+        }
+        else
+        {
+            /* process header */
+            UC_SRCE_TRACE("HTTP header found");
+
+            const char header_tag[] = "HTTP/1.1 ";
+
+            uint32_t header_start = arm_uc_strnstrn(request_buffer->ptr,
+                                                    request_buffer->size,
+                                                    (const uint8_t*) header_tag,
+                                                    sizeof(header_tag) - 1);
+
+            /* found beginning of header */
+            if (header_start < request_buffer->size)
+            {
+                /* status code is after the header tag */
+                header_start = header_start + sizeof(header_tag) - 1;
+            }
+
+            /* buffer size check */
+            if (header_start < request_buffer->size)
+            {
+                /* parse status code */
+                bool header_parsed = false;
+                uint32_t status_code = arm_uc_str2uint32(
+                                            &(request_buffer->ptr[header_start]),
+                                            request_buffer->size - header_start,
+                                            &header_parsed);
+
+                if (header_parsed == true)
+                {
+                    UC_SRCE_TRACE("HTTP status code %" PRIu32, status_code);
+
+                    /* Redirect status codes:
+                       301: Moved Permanently
+                       302: Found [Elsewhere]
+                       303: See Other
+                       307: Temporary Redirect
+                    */
+                    if ((status_code >= 301 && status_code <= 303) ||
+                        (status_code == 307))
+                    {
+                        /* move location to front of buffer */
+                        const char tag[] = "Location";
+                        bool found = arm_uc_socket_trim_value(request_buffer,
+                                                              tag,
+                                                              sizeof(tag) - 1);
+
+                        if (found)
+                        {
+                            /* NULL terminate string */
+                            request_buffer->ptr[request_buffer->size] = '\0';
+
+                            /* parse location and store in URI */
+                            arm_uc_error_t err = arm_uc_str2uri(request_buffer->ptr,
+                                                                request_buffer->size,
+                                                                request_uri);
+
+                            if ((err.error == ERR_NONE) &&
+                                (request_uri->scheme == URI_SCHEME_HTTP))
+                            {
+                                UC_SRCE_TRACE("HTTP redirecting to http://%s:%" PRIu16 "/%s",
+                                              request_uri->host,
+                                              request_uri->port,
+                                              request_uri->path);
+
+                                /* close current socket */
+                                arm_uc_socket_close();
+
+                                /* run "get" again with the new location (above) */
+                                err = arm_uc_socket_get(request_uri, request_buffer,
+                                                        request_offset, request_type);
+                                if (err.error == ERR_NONE)
+                                {
+                                    request_successfully_processed = true;
+                                }
+                                else
+                                {
+                                    UC_SRCE_ERR_MSG("Error: HTTP redirect failed");
+                                }
+                            }
+                            else
+                            {
+                                UC_SRCE_ERR_MSG("Error: unable to parse URI string");
+                            }
+                        }
+                        else
+                        {
+                            UC_SRCE_ERR_MSG("Error: unable to find redirect location");
+                        }
+                    }
+                    /* All remaining codes outside 200-226 are treated as errors */
+                    else if (status_code < 200 || status_code > 226)
+                    {
+                        UC_SRCE_ERR_MSG("Error: server returned HTTP status code %" PRIu32,
+                                        status_code);
+                    }
+                    /* All codes between 200 to 226 */
+                    else
+                    {
+                        /* NOTE: HTTP 1.1 Code 206 with Header "Connection:close" is not
+                           handled here, instead the execution falls trough to error-
+                           handling in http_socket (ARM_UCS_HTTPEVent with UCS_HTTP_EVENT_ERROR)
+                           where the retry-mechanism will resume firmware download if
+                           the server closed the connection.
+                        */
+                        if (request_type == RQST_TYPE_HASH_ETAG)
+                        {
+                            /* look for ETag and move to front of buffer */
+                            const char tag[] = "ETag";
+                            bool found = arm_uc_socket_trim_value(request_buffer,
+                                                                  tag,
+                                                                  sizeof(tag) - 1);
+
+                            if (found)
+                            {
+                                /* ETag successfully read - post callback */
+                                if (context->callback_handler)
+                                {
+                                    palStatus_t status = pal_osTimerStop(context->timeout_timer_id);
+                                    if (status != PAL_SUCCESS)
+                                    {
+                                        UC_SRCE_ERR_MSG("pal_osTimerStop returned 0x%" PRIX32,
+                                                        (uint32_t) status);
+                                        arm_uc_socket_close();
+                                    }
+
+                                    ARM_UC_PostCallback(&context->event_callback_struct,
+                                                        context->callback_handler,
+                                                        UCS_HTTP_EVENT_HASH);
+                                }
+
+                                /* request complete - close socket */
+                                arm_uc_socket_close();
+
+                                /* success - no clean up needed */
+                                request_successfully_processed = true;
+                            }
+                            else
+                            {
+                                UC_SRCE_ERR_MSG("Error: unable to find ETag");
+                            }
+                        }
+                        else if (request_type == RQST_TYPE_HASH_DATE)
+                        {
+                            /* look for date and move to front of buffer */
+                            const char tag[] = "Last-Modified";
+                            bool found = arm_uc_socket_trim_value(request_buffer,
+                                                                  tag,
+                                                                  sizeof(tag) - 1);
+
+                            if (found)
+                            {
+                                /* date successfully read - post callback */
+                                if (context->callback_handler)
+                                {
+                                    palStatus_t status = pal_osTimerStop(context->timeout_timer_id);
+                                    if (status != PAL_SUCCESS)
+                                    {
+                                        UC_SRCE_ERR_MSG("pal_osTimerStop returned 0x%" PRIX32,
+                                                        (uint32_t) status);
+                                        arm_uc_socket_close();
+                                    }
+
+                                    ARM_UC_PostCallback(&context->event_callback_struct,
+                                                        context->callback_handler,
+                                                        UCS_HTTP_EVENT_DATE);
+                                }
+
+                                /* request complete - close socket */
+                                arm_uc_socket_close();
+
+                                /* signal clean up is not needed */
+                                request_successfully_processed = true;
+                            }
+                            else
+                            {
+                                UC_SRCE_ERR_MSG("Error: unable to find last modified date");
+                            }
+                        }
+                        /* request is GetFile or GetFragment */
+                        else
+                        {
+                            /* save current buffer size so we can recover body after
+                               the content length has been read. */
+                            uint32_t current_size = request_buffer->size;
+
+                            /* find content length and move value to front of buffer */
+                            const char tag[] = "Content-Length";
+                            bool found = arm_uc_socket_trim_value(request_buffer,
+                                                                  tag,
+                                                                  sizeof(tag) - 1);
+
+                            if (found)
+                            {
+                                /* NULL terminate string */
+                                request_buffer->ptr[request_buffer->size] = '\0';
+
+                                /* parse full length of content */
+                                int parsed = sscanf((char *) request_buffer->ptr,
+                                                    "%10" SCNu32,
+                                                    &context->expected_remaining);
+
+                                /* only continue if exactly one argument was parsed */
+                                if (parsed == 1)
+                                {
+                                    UC_SRCE_TRACE("content: %" PRIu32,
+                                                  context->expected_remaining);
+
+                                    /* replace HTTP header with body */
+                                    memmove(request_buffer->ptr,
+                                            &(request_buffer->ptr[index + 4]),
+                                            current_size - (index + 4));
+
+                                    /* set size of partial body */
+                                    request_buffer->size = current_size - (index + 4);
+
+                                    /*  */
+                                    if (request_buffer->size >= context->expected_remaining)
+                                    {
+                                        /* all data received - process data */
+                                        arm_uc_socket_process_body();
+                                    }
+                                    else
+                                    {
+                                        /* expecting more data - continue receiving */
+                                        UC_SRCE_TRACE("expecting more data %" PRIu32 "/%" PRIu32 "\r\n",
+                                            request_buffer->size,
+                                            context->expected_remaining);
+                                    }
+
+                                    /* signal clean up is not needed */
+                                    request_successfully_processed = true;
+
+                                    /* continue processing body */
+                                    context->socket_state = STATE_PROCESS_BODY;
+                                }
+                                else
+                                {
+                                    UC_SRCE_ERR_MSG("Error: unable to parse content length");
+                                }
+                            }
+                            else
+                            {
+                                UC_SRCE_ERR_MSG("Error: unable find content length");
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    UC_SRCE_ERR_MSG("Error: unable to read status code");
+                }
+            }
+            else
+            {
+                UC_SRCE_ERR_MSG("Error: HTTP header not found");
+            }
+        }
+
+        /* clean up */
+        if (request_successfully_processed == false)
+        {
+            arm_uc_socket_error(UCS_HTTP_EVENT_ERROR);
+        }
+    }
+}
+
+/**
+ * @brief Function is called when file or fragment is being downloaded.
+ * @details Function drives the download and continues until the buffer is full
+ *          or the expected amount of data has been downloaded.
+ */
+void arm_uc_socket_process_body()
+{
+    /* NULL pointer check */
+    if (context)
+    {
+        /* check if all expected bytes have been received */
+        if (context->request_buffer->size >= context->expected_remaining)
+        {
+            UC_SRCE_TRACE("process body done");
+
+            /* fragment or file successfully received - post callback */
+            if (context->callback_handler)
+            {
+                palStatus_t status = pal_osTimerStop(context->timeout_timer_id);
+                if (status != PAL_SUCCESS)
+                {
+                    UC_SRCE_ERR_MSG("pal_osTimerStop returned 0x%" PRIX32,
+                                    (uint32_t) status);
+                    arm_uc_socket_close();
+                }
+
+                ARM_UC_PostCallback(&context->event_callback_struct,
+                                    context->callback_handler,
+                                    UCS_HTTP_EVENT_DOWNLOAD);
+            }
+
+            /* reset buffers and state */
+            context->socket_state = STATE_CONNECTED_IDLE;
+            context->request_buffer = NULL;
+            context->expected_event = SOCKET_EVENT_UNDEFINED;
+        }
+    }
+}
+
+/**
+ * @brief Close socket and set internal state to disconnected.
+ */
+void arm_uc_socket_close()
+{
+    /* NULL pointer check */
+    if (context)
+    {
+        /* close socket if not NULL */
+        if (context->socket)
+        {
+            pal_close(&context->socket);
+        }
+
+        /* delete socket timeout timer */
+        if (context->timeout_timer_id != (palTimerID_t) NULL)
+        {
+            pal_osTimerDelete(&context->timeout_timer_id);
+        }
+
+        /* reset buffers and state */
+        context->request_buffer = NULL;
+        context->expected_event = SOCKET_EVENT_UNDEFINED;
+        context->socket_state = STATE_DISCONNECTED;
+        context->timeout_timer_id = 0;
+    }
+}
+
+/**
+ * @brief Close socket, set internal state to disconnected and generate error
+ *        event.
+ */
+void arm_uc_socket_error(arm_ucs_http_event_t error)
+{
+    /* NULL pointer check */
+    if (context)
+    {
+        if (context->socket_state != STATE_DISCONNECTED)
+        {
+            /* close socket */
+            arm_uc_socket_close();
+        }
+
+        /* clear DNS cache */
+        context->cache_address.addressType = 0;
+        memset(context->cache_address.addressData, 0, PAL_NET_MAX_ADDR_SIZE);
+        context->cache_address_length = 0;
+
+        /* if callback handler is set, generate error event */
+        if (context->callback_handler)
+        {
+            UC_SRCE_ERR_MSG("posting to callback with event %d", error);
+            ARM_UC_PostCallback(&context->event_callback_struct,
+                                context->callback_handler,
+                                error);
+        }
+    }
+}
+
+/**
+ * @brief PAL socket event handler.
+ * @param unused PAL API doesn't support parameters.
+ */
+void arm_uc_socket_callback(uint32_t unused)
+{
+    (void) unused;
+
+    UC_SRCE_TRACE("arm_uc_socket_callback");
+
+    /* NULL pointer check */
+    if (context)
+    {
+        /* unlock posting callbacks to the queue */
+        pal_osAtomicIncrement(&context->isr_callback_counter, -1);
+
+        switch (context->expected_event)
+        {
+            case SOCKET_EVENT_DNS_DONE:
+                UC_SRCE_TRACE("DNS done");
+
+                {
+                    /* stop DNS timeout timer */
+                    arm_uc_error_t result = arm_uc_stop_dns_timer();
+                    if (result.code != SRCE_ERR_NONE)
+                    {
+                        arm_uc_socket_error(UCS_HTTP_EVENT_ERROR);
+                    }
+                    else
+                    {
+                        if (context->cache_address.addressType == 0 &&
+                            context->cache_address_length == 0)
+                        {
+                            UC_SRCE_ERR_MSG("DNS resolution failed for host %s",
+                                            context->request_uri->host);
+                            arm_uc_socket_error(UCS_HTTP_EVENT_ERROR);
+                        }
+                        else
+                        {
+                            result = arm_uc_socket_finish_connect();
+                            if (result.code != SRCE_ERR_NONE)
+                            {
+                                UC_SRCE_ERR_MSG("arm_uc_socket_finish_connect failed: %s",
+                                                ARM_UC_err2Str(result));
+                                arm_uc_socket_error(UCS_HTTP_EVENT_ERROR);
+                            }
+                        }
+                    }
+                }
+                break;
+
+            case SOCKET_EVENT_CONNECT_DONE:
+                UC_SRCE_TRACE("Connect done");
+
+                context->socket_state = STATE_CONNECTED_IDLE;
+                {
+                    arm_uc_error_t result = arm_uc_socket_send_request();
+                    if (result.code != SRCE_ERR_NONE)
+                    {
+                        UC_SRCE_ERR_MSG("arm_uc_socket_send_request failed: %s",
+                                        ARM_UC_err2Str(result));
+                        arm_uc_socket_error(UCS_HTTP_EVENT_ERROR);
+                    }
+                }
+                break;
+
+            case SOCKET_EVENT_SEND_DONE:
+                UC_SRCE_TRACE("send done");
+
+                /* request send, receive response */
+                context->expected_event = SOCKET_EVENT_RECEIVE_CONTINUE;
+                arm_uc_socket_receive();
+                break;
+
+            case SOCKET_EVENT_RECEIVE_CONTINUE:
+                UC_SRCE_TRACE("recv continue");
+
+                /* outstanding data, continue receiving */
+                arm_uc_socket_receive();
+                break;
+
+            case SOCKET_EVENT_TIMER_FIRED:
+                UC_SRCE_TRACE("socket timeout timer fired");
+
+                /* delete socket timeout timer */
+                if (context->timeout_timer_id != (palTimerID_t) NULL)
+                {
+                    pal_osTimerDelete(&context->timeout_timer_id);
+                    context->timeout_timer_id = 0;
+                }
+                arm_uc_socket_error(UCS_HTTP_EVENT_ERROR);
+                break;
+
+            case SOCKET_EVENT_UNDEFINED:
+            default:
+                UC_SRCE_TRACE("event: undefined");
+                break;
+        }
+    }
+}
+
+/**
+ * @brief Callback handler for PAL socket events. Callbacks go through the task
+ *        queue because we don't know what context we are running from.
+ */
+void arm_uc_socket_isr(void* unused)
+{
+    /* NULL pointer check */
+    if (context)
+    {
+        /* ensure we only have one callback in flight */
+        int32_t count = pal_osAtomicIncrement(&context->isr_callback_counter, 0);
+
+        if (count == 0)
+        {
+            pal_osAtomicIncrement(&context->isr_callback_counter, 1);
+
+            /* post callback to de-escalate event */
+            ARM_UC_PostCallback(&context->isr_callback_struct,
+                                arm_uc_socket_callback,
+                                0);
+        }
+    }
+}
+
+/**
+ * @brief Callback handler for the socket timeout timer callback.
+ *        Callbacks go through the task queue because we don't know
+ *        what context we are running from.
+ */
+void arm_uc_timeout_timer_callback(void const *unused)
+{
+    (void) unused;
+
+    if (context != NULL)
+    {
+        context->expected_event = SOCKET_EVENT_TIMER_FIRED;
+        /* push event to the socket event queue */
+        arm_uc_socket_isr(NULL);
+    }
+}
+
+/**
+ * @brief Callback handler for the asynchronous DNS resolver.
+ *        Callbacks go through the task queue because we don't know
+ *        what context we are running from.
+ */
+void arm_uc_dns_callback(const char* url, palSocketAddress_t* address,
+                         palSocketLength_t* address_length, palStatus_t status,
+                         void *argument)
+{
+    (void)url;
+    (void)address;
+    (void)address_length;
+    (void)argument;
+
+    if (context != NULL)
+    {
+        /* check if DNS call succeeded */
+        if (status != PAL_SUCCESS)
+        {
+            /* clear the address-related fields to signal an error */
+            context->cache_address.addressType = 0;
+            context->cache_address_length = 0;
+        }
+        context->expected_event = SOCKET_EVENT_DNS_DONE;
+        /* push event to the socket event queue */
+        arm_uc_socket_isr(NULL);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/source/arm_uc_http_socket_private.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,155 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __ARM_UC_HTTP_SOCKET_PRIVATE_H__
+#define __ARM_UC_HTTP_SOCKET_PRIVATE_H__
+
+#include "update-client-source-http-socket/arm_uc_http_socket.h"
+#include "update-client-common/arm_uc_common.h"
+#include <pal.h>
+
+/**
+ * @brief Initialize Http module.
+ * @details A memory struct is passed as well as a function pointer for event
+ *          handling.
+ *
+ * @param context Struct holding all global variables.
+ * @param handler Event handler for signaling when each operation is complete.
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_socket_initialize(arm_uc_http_socket_context_t* context,
+                                        ARM_UCS_HttpEvent_t handler);
+
+/**
+ * @brief Resets HTTP socket to uninitialized state and clears memory struct.
+ * @details HTTP sockets must be initialized again before use.
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_socket_terminate(void);
+
+/**
+ * @brief Get resource at URI.
+ * @details Download resource at URI from given offset and store in buffer.
+ *          Events are generated when download finish or on error
+ *
+ * @param uri Pointer to structure with resource location.
+ * @param buffer Pointer to structure with buffer location, maxSize, and size.
+ * @param offset Offset in resource to begin download from.
+ * @param type Indicate what type of request that was initiated.
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_socket_get(arm_uc_uri_t* uri,
+                                 arm_uc_buffer_t* buffer,
+                                 uint32_t offset,
+                                 arm_uc_rqst_t type);
+
+/**
+ * @brief Connect to server set in the global URI struct.
+ * @details Connecting generates a socket event, which automatically processes
+ *          the request passed in arm_uc_socket_get. If a DNS request must
+ *          be made, this call initiates an asynchronous DNS request. After
+ *          the request is done, the connection process will be resumed in
+ *          arm_uc_socket_finish_connect().
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_socket_connect(void);
+
+/**
+ * @brief Finishes connecting to the server requested in a previous call to
+ *        arm_uc_socket_connect().
+ * @details This function is called after the DNS resolution for the host
+ *          requested in arm_uc_socket_get() above is done. It finishes the
+ *          connection process by creating a socket and connecting it.
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_socket_finish_connect(void);
+
+/**
+ * @brief Send request passed in arm_uc_socket_get.
+ * @details This call assumes the HTTP socket is already connected to server.
+ * @return Error code.
+ */
+arm_uc_error_t arm_uc_socket_send_request(void);
+
+/**
+ * @brief Receive data from HTTP socket.
+ * @details Data is stored in global buffer. The call will automatically retry
+ *          if the socket is busy.
+ */
+void arm_uc_socket_receive(void);
+
+/**
+ * @brief Function is called when some data has been received but an HTTP
+ *        header has yet to be processed.
+ * @details Function is called repeatedly until a header is found or the buffer
+ *          is full. Once a header is found, the ETag, date, or content length
+ *          is parsed. For file and fragment downloads the receive process is
+ *          restarted and the header is erased.
+ */
+void arm_uc_socket_process_header(void);
+
+/**
+ * @brief Function is called when file or fragment is being downloaded.
+ * @details Function drives the download and continues until the buffer is full
+ *          or the expected amount of data has been downloaded.
+ */
+void arm_uc_socket_process_body(void);
+
+/**
+ * @brief Close socket and set internal state to disconnected.
+ */
+void arm_uc_socket_close(void);
+
+/**
+ * @brief Close socket, set internal state to disconnected and generate error
+ *        event.
+ * @param error The code of the error event.
+ */
+void arm_uc_socket_error(arm_ucs_http_event_t error);
+
+/**
+ * @brief Callback function for handling events in application context.
+ * @param unused Unused.
+ */
+void arm_uc_socket_callback(uint32_t unused);
+
+/**
+ * @brief Callback function for handling events in interrupt context.
+ * @details All events are de-escalated through the callback queue.
+ */
+void arm_uc_socket_isr(void*);
+
+/**
+ * @brief Callback handler for the socket timeout timer callback.
+ *        Callbacks go through the task queue because we don't know
+ *        what context we are running from.
+ */
+void arm_uc_timeout_timer_callback(void const *);
+
+/**
+ * @brief Callback handler for the asynchronous DNS resolver.
+ *        Callbacks go through the task queue because we don't know
+ *        what context we are running from.
+ */
+void arm_uc_dns_callback(const char* url,
+                         palSocketAddress_t* address,
+                         palSocketLength_t* address_length,
+                         palStatus_t status,
+                         void* argument);
+
+#endif // __ARM_UC_HTTP_SOCKET_PRIVATE_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/source/arm_uc_socket_help.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,81 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "arm_uc_socket_help.h"
+
+#include <string.h>
+
+/**
+ * @brief Helper function for picking out values from an HTTP header.
+ * @details The buffer is searched for the tag provided tag and if found the
+ *          remainder of that line is MOVED to the front of the buffer and the
+ *          size is shrunk to only include the detected value.
+ *
+ * @param buffer Pointer to an arm_uc_buffer_t.
+ * @param tag_buffer Pointer to tag (a string).
+ * @param tag_size Length of the tag.
+ * @return True if tag was found. False otherwise.
+ */
+bool arm_uc_socket_trim_value(arm_uc_buffer_t* buffer,
+                              const char* tag_buffer,
+                              uint32_t tag_size)
+{
+    /* default return value */
+    bool result = false;
+
+    /* check for NULL pointers */
+    if (buffer && buffer->ptr && tag_buffer)
+    {
+        /* search for the tag */
+        uint32_t start = arm_uc_strnstrn(buffer->ptr,
+                                         buffer->size,
+                                         (const uint8_t*) tag_buffer,
+                                         tag_size);
+
+        /* check if index is within bounds */
+        if (start < buffer->size)
+        {
+            /* remove tag */
+            start += tag_size;
+
+            /* remove ": " between tag and value */
+            start += 2;
+
+            /* search for the end of the line */
+            uint32_t length = arm_uc_strnstrn(&(buffer->ptr[start]),
+                                              buffer->size - start,
+                                              (const uint8_t*) "\r",
+                                              1);
+
+            /* move value to front of buffer if all indices are within bounds */
+            if ((start + length) < buffer->size)
+            {
+                /* memmove handles overlapping regions */
+                memmove(buffer->ptr, &(buffer->ptr[start]), length);
+
+                /* resize buffer */
+                buffer->size = length;
+
+                /* set return value to success */
+                result = true;
+            }
+        }
+    }
+
+    return result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/source/arm_uc_socket_help.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,42 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __ARM_UC_SOCKET_HELP_H__
+#define __ARM_UC_SOCKET_HELP_H__
+
+#include "update-client-common/arm_uc_common.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/**
+ * @brief Helper function for picking out values from an HTTP header.
+ * @details The buffer is searched for the tag provided tag and if found the
+ *          remainder of that line is MOVED to the front of the buffer and the
+ *          size is shrunk to only include the detected value.
+ *
+ * @param buffer Pointer to an arm_uc_buffer_t.
+ * @param tag_buffer Pointer to tag (a string).
+ * @param tag_size Length of the tag.
+ * @return True if tag was found. False otherwise.
+ */
+bool arm_uc_socket_trim_value(arm_uc_buffer_t* buffer,
+                              const char* tag_buffer,
+                              uint32_t tag_size);
+
+#endif // __ARM_UC_SOCKET_HELP_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http-socket/update-client-source-http-socket/arm_uc_http_socket.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,189 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef UPDATE_CLIENT_SOURCE_HTTP_SOCKET_H
+#define UPDATE_CLIENT_SOURCE_HTTP_SOCKET_H
+
+#include "update-client-common/arm_uc_common.h"
+
+#include <pal.h>
+
+/**
+ * @brief Events passed to event handler.
+ * @details EVENT_HASH Get hash complete.
+ *          EVENT_DATE Get date complete.
+ *          EVENT_DOWNLOAD_PENDING Download complete with data pending.
+ *          EVENT_DOWNLOAD_DONE Download complete, all done.
+ */
+typedef enum {
+    UCS_HTTP_EVENT_HASH,
+    UCS_HTTP_EVENT_DATE,
+    UCS_HTTP_EVENT_DOWNLOAD,
+    UCS_HTTP_EVENT_ERROR,
+    UCS_HTTP_EVENT_ERROR_BUFFER_SIZE
+} arm_ucs_http_event_t;
+
+typedef enum {
+    RQST_TYPE_NONE, // to indicate idle
+    RQST_TYPE_HASH_ETAG,
+    RQST_TYPE_HASH_DATE,
+    RQST_TYPE_GET_FILE,
+    RQST_TYPE_GET_FRAG
+} arm_uc_rqst_t;
+
+typedef enum {
+    STATE_DISCONNECTED,
+    STATE_PROCESS_HEADER,
+    STATE_PROCESS_BODY,
+    STATE_CONNECTED_IDLE
+} arm_uc_socket_state_t;
+
+typedef enum {
+    SOCKET_EVENT_DNS_DONE,
+    SOCKET_EVENT_CONNECT_DONE,
+    SOCKET_EVENT_SEND_DONE,
+    SOCKET_EVENT_RECEIVE_CONTINUE,
+    SOCKET_EVENT_UNDEFINED,
+    SOCKET_EVENT_TIMER_FIRED
+} arm_uc_socket_event_t;
+
+/**
+ * @brief Prototype for event handler.
+ */
+typedef void (*ARM_UCS_HttpEvent_t)(uint32_t event);
+
+typedef struct {
+    /* external callback handler */
+    ARM_UCS_HttpEvent_t callback_handler;
+
+    /* location */
+    arm_uc_uri_t* request_uri;
+
+    /* buffer to store downloaded data */
+    arm_uc_buffer_t* request_buffer;
+
+    /* fragment offset in a multi-fragment download */
+    uint32_t request_offset;
+
+    /* request type */
+    arm_uc_rqst_t request_type;
+
+    /* internal state */
+    arm_uc_socket_state_t socket_state;
+
+    /* expected socket event */
+    arm_uc_socket_event_t expected_event;
+
+    /* remaining bytes in request */
+    uint32_t expected_remaining;
+
+    /* structs for callback queue */
+    int32_t isr_callback_counter;
+    arm_uc_callback_t isr_callback_struct; // initialized in source-http
+    arm_uc_callback_t event_callback_struct; // initialized in source-http
+    arm_uc_callback_t timer_callback_struct; // initialized in source-http
+
+    /* pointer to socket */
+    palSocket_t socket;
+
+    /* timer id for the socket timeout timer */
+    palTimerID_t timeout_timer_id;
+
+    /* cache for storing DNS lookup */
+    palSocketAddress_t cache_address;
+    palSocketLength_t cache_address_length;
+} arm_uc_http_socket_context_t;
+
+/**
+ * @brief Initialize Http module.
+ * @details A memory struct is passed as well as a function pointer for event
+ *          handling.
+ *
+ * @param context Struct holding all global variables.
+ * @param handler Event handler for signaling when each operation is complete.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_HttpSocket_Initialize(arm_uc_http_socket_context_t* context,
+                                             ARM_UCS_HttpEvent_t handler);
+
+/**
+ * @brief Resets HTTP socket to uninitialized state and clears memory struct.
+ * @details HTTP sockets must be initialized again before use.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_HttpSocket_Terminate(void);
+
+/**
+ * @brief Get hash for resource at URI.
+ * @details Store hash in provided buffer. Enclosing "" and '\0' are removed.
+ *
+ *          Event generated: EVENT_HASH
+ *
+ * @param uri Pointer to struct with resource location.
+ * @param buffer Pointer to structure with buffer location, maxSize, and size.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_HttpSocket_GetHash(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Get date for resource at URI.
+ * @details Store Last-Modified data in provided buffer. Enclosing "" and '\0' are removed.
+ *
+ *          Event generated: EVENT_DATE
+ *
+ * @param uri Pointer to struct with resource location.
+ * @param buffer Pointer to structure with buffer location, maxSize, and size.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_HttpSocket_GetDate(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Get full resource at URI.
+ * @details Download resource at URI and store in provided buffer.
+ *          If the provided buffer is not big enough to contain the whole resource
+ *          what can fit in the buffer will be downloaded.
+ *          The user can then use GetFragment to download the rest.
+
+ *          Events generated: EVENT_DOWNLOAD_PENDING if there is still data to
+ *          download and EVENT_DOWNLOAD_DONE if the file is completely downloaded.
+ *
+ * @param uri Pointer to structure with resource location.
+ * @param buffer Pointer to structure with buffer location, maxSize, and size.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_HttpSocket_GetFile(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer);
+
+/**
+ * @brief Get partial resource at URI.
+ * @details Download resource at URI from given offset and store in buffer.
+ *
+ *          The buffer maxSize determines how big a fragment to download. If the
+ *          buffer is larger than the requested fragment (offset to end-of-file)
+ *          the buffer size is set to indicate the number of available bytes.
+ *
+ *          Events generated: EVENT_DOWNLOAD_PENDING if there is still data to
+ *          download and EVENT_DOWNLOAD_DONE if the file is completely downloaded.
+ *
+ * @param uri Pointer to structure with resource location.
+ * @param buffer Pointer to structure with buffer location, maxSize, and size.
+ * @param offset Offset in resource to begin download from.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_HttpSocket_GetFragment(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer, uint32_t offset);
+
+#endif /* UPDATE_CLIENT_SOURCE_HTTP_SOCKET_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,166 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http/source/arm_uc_source_http.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,761 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-source-http/arm_uc_source_http.h"
+#include "update-client-source-http/arm_uc_source_http_extra.h"
+
+#include "update-client-source-http-socket/arm_uc_http_socket.h"
+
+#include <time.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#define ARM_UCS_DEFAULT_COST (1000)
+#define ARM_UCS_HASH_LENGTH  (40)
+
+typedef struct _ARM_UCS_Configuration
+{
+    arm_uc_uri_t manifest;
+    uint32_t interval;
+    uint32_t currentCost;
+    time_t lastPoll;
+    int8_t hash[ARM_UCS_HASH_LENGTH];
+    void (*eventHandler)(uint32_t event);
+} ARM_UCS_Configuration_t;
+
+static ARM_UCS_Configuration_t default_config = {
+    .manifest = {
+        .size_max = 0,
+        .size = 0,
+        .ptr = NULL,
+        .scheme = URI_SCHEME_NONE,
+        .port = 0,
+        .host = NULL,
+        .path = NULL
+    },
+    .interval = 0,
+    .currentCost = 0xFFFFFFFF,
+    .lastPoll = 0,
+    .hash = { 0 },
+    .eventHandler = 0
+};
+
+typedef enum {
+    STATE_UCS_HTTP_IDLE,
+    STATE_UCS_HTTP_MANIFEST,
+    STATE_UCS_HTTP_FIRMWARE,
+    STATE_UCS_HTTP_KEYTABLE,
+    STATE_UCS_HTTP_HASH
+} arm_ucs_http_state_t;
+
+#define MAX_RETRY 3
+typedef struct {
+    arm_ucs_http_state_t stateHttp;
+    arm_uc_uri_t *uri;
+    arm_uc_buffer_t *buffer;
+    uint32_t offset;
+    uint8_t retryCount;
+} arm_ucs_state_t;
+
+static arm_ucs_state_t arm_ucs_state;
+
+static arm_uc_http_socket_context_t arm_uc_http_socket_context = { 0 };
+
+/* Helper function for resetting internal state */
+static inline void uc_state_reset()
+{
+    arm_ucs_state.stateHttp  = STATE_UCS_HTTP_IDLE;
+    arm_ucs_state.uri        = NULL;
+    arm_ucs_state.buffer     = NULL;
+    arm_ucs_state.offset     = 0;
+    arm_ucs_state.retryCount = 0;
+}
+
+/* Helper function for checking if the stored hash is all zeros */
+static inline bool hash_is_zero()
+{
+    bool result = true;
+
+    for (uint32_t index = 0; index < ARM_UCS_HASH_LENGTH; index++)
+    {
+        if (default_config.hash[index] != 0)
+        {
+            result = false;
+            break;
+        }
+    }
+
+    return result;
+}
+
+static arm_uc_error_t ARM_UCS_Get(arm_uc_uri_t* uri,
+                                  arm_uc_buffer_t* buffer,
+                                  uint32_t offset,
+                                  arm_ucs_http_state_t newHttpState);
+
+/******************************************************************************/
+/* ARM Update Client Source Extra                                             */
+/******************************************************************************/
+
+/**
+ * @brief Set URI location for the default manifest.
+ * @details The default manifest is polled regularly and generates a
+ *          notification upon change. The URI struct and the content pointer to
+ *          must be valid throughout the lifetime of the application.
+ *
+ * @param uri URI struct with manifest location.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_SetDefaultManifestURL(arm_uc_uri_t* uri)
+{
+    UC_SRCE_TRACE("ARM_UCS_SetDefaultManifestURL");
+
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+
+    if (uri != 0)
+    {
+        /* check scheme is http */
+        if (uri->scheme == URI_SCHEME_HTTP)
+        {
+            /* copy pointers to local struct */
+            default_config.manifest = *uri;
+
+            result = (arm_uc_error_t){ SRCE_ERR_NONE };
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Set polling interval for notification generation.
+ * @details The default manifest location is polled with this interval.
+ *
+ * @param seconds Seconds between each poll.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_SetPollingInterval(uint32_t seconds)
+{
+    UC_SRCE_TRACE("ARM_UCS_SetPollingInterval");
+
+    default_config.interval = seconds;
+
+    return (arm_uc_error_t){ SRCE_ERR_NONE };
+}
+
+/**
+ * @brief Main function for the Source.
+ * @details This function will query the default manifest location and generate
+ *          a notification if it has changed since the last time it was checked.
+ *          The number of queries generated is bound by the polling interval.
+ *
+ *          This function should be used on systems with timed callbacks.
+ *
+ * @return Seconds until the next polling interval.
+ */
+uint32_t ARM_UCS_CallMultipleTimes(arm_uc_buffer_t* hash_buffer)
+{
+    uint32_t result = default_config.interval;
+    time_t unixtime = time(NULL);
+    uint32_t elapsed = unixtime - default_config.lastPoll;
+
+    if ((default_config.eventHandler == NULL) ||
+        (arm_ucs_state.stateHttp != STATE_UCS_HTTP_IDLE) ||
+        (hash_buffer == NULL))
+    {
+        return default_config.interval;
+    }
+
+    if (elapsed >= default_config.interval)
+    {
+        UC_SRCE_TRACE("ARM_UCS_CallMultipleTimes");
+
+        // poll default URI
+        default_config.lastPoll = unixtime;
+
+        // get resource hash
+        arm_ucs_state.stateHttp = STATE_UCS_HTTP_HASH;
+        arm_ucs_state.buffer = hash_buffer;
+
+        arm_uc_error_t retval = ARM_UCS_HttpSocket_GetHash(&default_config.manifest,
+                                                           arm_ucs_state.buffer);
+        if (retval.error != ERR_NONE)
+        {
+            uc_state_reset();
+            return default_config.interval;
+        }
+    }
+    else
+    {
+        result = (elapsed > 0) ? default_config.interval - elapsed : default_config.interval;
+    }
+
+    return result;
+}
+
+
+ARM_UCS_HTTPSourceExtra_t ARM_UCS_HTTPSourceExtra =
+{
+    .SetDefaultManifestURL = ARM_UCS_SetDefaultManifestURL,
+    .SetPollingInterval    = ARM_UCS_SetPollingInterval,
+    .CallMultipleTimes     = ARM_UCS_CallMultipleTimes
+};
+
+/******************************************************************************/
+/* ARM Update Client Source                                                   */
+/******************************************************************************/
+
+static void ARM_UCS_ProcessHash()
+{
+    UC_SRCE_TRACE("ARM_UCS_ProcessHash");
+
+#if ARM_UC_SOURCE_MANAGER_TRACE_ENABLE
+    printf("hash: ");
+    for (uint32_t index = 0; index < arm_ucs_state.buffer->size; index++)
+    {
+        printf("%c", arm_ucs_state.buffer->ptr[index]);
+    }
+    printf("\r\n");
+#endif
+
+    bool hashIsNew = false;
+    bool firstBoot = hash_is_zero();
+
+    /* compare hash with previous check */
+    for (uint32_t index = 0; index < arm_ucs_state.buffer->size; index++)
+    {
+        /* compare hash */
+        if (default_config.hash[index] != arm_ucs_state.buffer->ptr[index])
+        {
+            /* store new hash */
+            default_config.hash[index] = arm_ucs_state.buffer->ptr[index];
+
+            hashIsNew = true;
+        }
+    }
+
+    /* Request complete, reset state */
+    uc_state_reset();
+
+    /* Signal that a new manifest is available if the hash is non-zero
+       and different from the last check.
+    */
+    if (hashIsNew && !firstBoot)
+    {
+        if (default_config.eventHandler)
+        {
+            default_config.eventHandler(EVENT_NOTIFICATION);
+        }
+    }
+}
+
+static void ARM_UCS_HTTPEvent(uint32_t event)
+{
+    UC_SRCE_TRACE("ARM_UCS_HTTPEvent");
+
+    switch (event)
+    {
+        /* Hash received, process it */
+        case UCS_HTTP_EVENT_HASH:
+            UC_SRCE_TRACE("UCS_HTTP_EVENT_HASH");
+
+            ARM_UCS_ProcessHash();
+            break;
+
+        /* Download complete */
+        case UCS_HTTP_EVENT_DOWNLOAD:
+            {
+                UC_SRCE_TRACE("UCS_HTTP_EVENT_DOWNLOAD");
+
+                /* cache state before resetting it */
+                arm_ucs_http_state_t previous_state = arm_ucs_state.stateHttp;
+
+                /* reset internal state */
+                uc_state_reset();
+
+                /* signal successful download based on request */
+                if  (default_config.eventHandler)
+                {
+                    if (previous_state == STATE_UCS_HTTP_MANIFEST)
+                    {
+                        default_config.eventHandler(EVENT_MANIFEST);
+                    }
+                    else if (previous_state == STATE_UCS_HTTP_FIRMWARE)
+                    {
+                        default_config.eventHandler(EVENT_FIRMWARE);
+                    }
+                    else if (previous_state == STATE_UCS_HTTP_KEYTABLE)
+                    {
+                        default_config.eventHandler(EVENT_KEYTABLE);
+                    }
+                    else
+                    {
+                        default_config.eventHandler(EVENT_ERROR);
+                    }
+                }
+            }
+            break;
+
+        /* Socket error */
+        case UCS_HTTP_EVENT_ERROR:
+            {
+                UC_SRCE_TRACE("UCS_HTTP_EVENT_ERROR");
+
+                /* Treat polling as retry when reading hash */
+                if (arm_ucs_state.stateHttp == STATE_UCS_HTTP_HASH)
+                {
+                    /* If the stored hash is zero, this error is most likely
+                       generated due to the default manifest not being uploaded
+                       yet. Mark the stored hash as non-zero, so the first time
+                       the device successfully retrieves a hash we download the
+                       manifest.
+                    */
+                    bool result = hash_is_zero();
+
+                    if (result)
+                    {
+                        default_config.hash[0] = 0xFF;
+                    }
+
+                    /* reset state but don't take any further action */
+                    uc_state_reset();
+                }
+                /* Perform MAX_RETRY otherwise */
+                else if (arm_ucs_state.retryCount < MAX_RETRY)
+                {
+                    /* restore buffer size on retry */
+                    arm_ucs_state.buffer->size = arm_ucs_state.buffer->size_max;
+
+                    /* restore stateHttp */
+                    arm_ucs_http_state_t previous_state = arm_ucs_state.stateHttp;
+                    arm_ucs_state.stateHttp = STATE_UCS_HTTP_IDLE;
+
+                    arm_uc_error_t retval = ARM_UCS_Get(arm_ucs_state.uri,
+                                                        arm_ucs_state.buffer,
+                                                        arm_ucs_state.offset,
+                                                        previous_state);
+
+                    /* retry unsuccessful */
+                    if (retval.error != ERR_NONE)
+                    {
+                        /* reset internal state */
+                        uc_state_reset();
+
+                        /* generate error event */
+                        if (default_config.eventHandler)
+                        {
+                            default_config.eventHandler(EVENT_ERROR);
+                        }
+                    }
+                }
+                else
+                {
+                    /* reset internal state */
+                    uc_state_reset();
+
+                    /* generate error event */
+                    if (default_config.eventHandler)
+                    {
+                        default_config.eventHandler(EVENT_ERROR);
+                    }
+                }
+            }
+            break;
+
+        /* supplied buffer not large enough */
+        case UCS_HTTP_EVENT_ERROR_BUFFER_SIZE:
+            {
+                /* reset internal state */
+                uc_state_reset();
+
+                /* generate error event */
+                if (default_config.eventHandler)
+                {
+                    default_config.eventHandler(EVENT_ERROR_BUFFER_SIZE);
+                }
+            }
+            break;
+
+        default:
+            UC_SRCE_TRACE("Unknown event");
+            break;
+    }
+}
+
+/**
+ * @brief Get driver version.
+ * @return Driver version.
+ */
+uint32_t ARM_UCS_GetVersion(void)
+{
+    UC_SRCE_TRACE("ARM_UCS_GetVersion");
+
+    return 0;
+}
+
+/**
+ * @brief Get Source capabilities.
+ * @return Struct containing capabilites. See definition above.
+ */
+ARM_SOURCE_CAPABILITIES ARM_UCS_GetCapabilities(void)
+{
+    UC_SRCE_TRACE("ARM_UCS_GetCapabilities");
+
+    ARM_SOURCE_CAPABILITIES result = {
+        .notify = 0,
+        .manifest_default = 0,
+        .manifest_url = 0,
+        .firmware = 0,
+        .keytable = 0
+    };
+
+    /* the event handler must be set before module can be used */
+    if (default_config.eventHandler != 0)
+    {
+        result.manifest_url = 1;
+        result.firmware = 1;
+        result.keytable = 1;
+
+        /* notification requires that the default manifest is set */
+        if ((default_config.manifest.port != 0) || (default_config.interval != 0))
+        {
+            result.notify = 1;
+            result.manifest_default = 1;
+        }
+    }
+
+    return result;
+}
+
+/**
+ * @brief Initialize Source.
+ * @details Function pointer to event handler is passed as argument.
+ *
+ * @param cb_event Function pointer to event handler. See events above.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_Initialize(ARM_SOURCE_SignalEvent_t cb_event)
+{
+    UC_SRCE_TRACE("ARM_UCS_Initialize");
+
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+
+    if (cb_event != 0)
+    {
+        default_config.currentCost = ARM_UCS_DEFAULT_COST;
+        default_config.eventHandler = cb_event;
+        result = (arm_uc_error_t){ SRCE_ERR_NONE };
+
+        /* register http callback handler */
+        ARM_UCS_HttpSocket_Initialize(&arm_uc_http_socket_context,
+                                      ARM_UCS_HTTPEvent);
+    }
+
+    uc_state_reset();
+    return result;
+}
+
+/**
+ * @brief Uninitialized Source.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_Uninitialize(void)
+{
+    UC_SRCE_TRACE("ARM_UCS_Uninitialize");
+
+    return (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+}
+
+/**
+ * @brief Cost estimation for retrieving manifest from the default location.
+ * @details The estimation can vary over time and should not be cached too long.
+ *          0x00000000 - The manifest is already downloaded.
+ *          0xFFFFFFFF - Cannot retrieve manifest from this Source.
+ *
+ * @param cost Pointer to variable for the return value.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetManifestDefaultCost(uint32_t* cost)
+{
+    UC_SRCE_TRACE("ARM_UCS_GetManifestDefaultCost");
+
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+
+    if (cost != 0)
+    {
+        *cost = default_config.currentCost;
+        result = (arm_uc_error_t){ SRCE_ERR_NONE };
+    }
+
+    return result;
+}
+
+/**
+ * @brief Cost estimation for retrieving manifest from URL.
+ * @details The estimation can vary over time and should not be cached too long.
+ *          0x00000000 - The manifest is already downloaded.
+ *          0xFFFFFFFF - Cannot retrieve manifest from this Source.
+ *
+ * @param uri URI struct with manifest location.
+ * @param cost Pointer to variable for the return value.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetManifestURLCost(arm_uc_uri_t* uri, uint32_t* cost)
+{
+    UC_SRCE_TRACE("ARM_UCS_GetManifestURLCost");
+
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+
+    /* return default cost regardless of actual uri location */
+    if ((uri != 0) && (cost != 0))
+    {
+        *cost = default_config.currentCost;
+        result = (arm_uc_error_t){ SRCE_ERR_NONE };
+    }
+    /* return no-path cost if URL is invalid */
+    else if (cost != 0)
+    {
+        *cost = 0xFFFFFFFF;
+        result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+    }
+
+    return result;
+}
+
+/**
+ * @brief Cost estimation for retrieving firmware from URL.
+ * @details The estimation can vary over time and should not be cached too long.
+ *          0x00000000 - The firmware is already downloaded.
+ *          0xFFFFFFFF - Cannot retrieve firmware from this Source.
+ *
+ * @param uri URI struct with firmware location.
+ * @param cost Pointer to variable for the return value.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetFirmwareURLCost(arm_uc_uri_t* uri, uint32_t* cost)
+{
+    UC_SRCE_TRACE("ARM_UCS_GetFirmwareURLCost");
+
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+
+    /* return default cost regardless of actual uri location */
+    if ((uri != 0) && (cost != 0))
+    {
+        *cost = default_config.currentCost;
+        result = (arm_uc_error_t){ SRCE_ERR_NONE };
+    }
+    /* return no-path cost if URL is invalid */
+    else if (cost != 0)
+    {
+        *cost = 0xFFFFFFFF;
+        result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+    }
+
+    return result;
+}
+
+/**
+ * @brief Cost estimation for retrieving key table from URL.
+ * @details The estimation can vary over time and should not be cached too long.
+ *          0x00000000 - The firmware is already downloaded.
+ *          0xFFFFFFFF - Cannot retrieve firmware from this Source.
+ *
+ * @param uri URI struct with keytable location.
+ * @param cost Pointer to variable for the return value.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetKeytableURLCost(arm_uc_uri_t* uri, uint32_t* cost)
+{
+    UC_SRCE_TRACE("ARM_UCS_GetKeytableURLCost");
+
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+
+    /* return default cost regardless of actual uri location */
+    if ((uri != 0) && (cost != 0))
+    {
+        *cost = default_config.currentCost;
+        result = (arm_uc_error_t){ SRCE_ERR_NONE };
+    }
+    /* return no-path cost if URL is invalid */
+    else if (cost != 0)
+    {
+        *cost = 0xFFFFFFFF;
+        result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+    }
+
+    return result;
+}
+
+/**
+ * @brief (Internal) Retrieve resource according to the given parameters
+ *        in arm_ucs_state and store the returned data in the buffer in arm_ucs_state.
+ * @param uri URI struct with resource location.
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ * @param offset Offset to retrieve fragment from.
+ * @param newHttpState The intended new http state to be assigned to arm_ucs_state.stateHttp
+ */
+static arm_uc_error_t ARM_UCS_Get(arm_uc_uri_t* uri,
+                                  arm_uc_buffer_t* buffer,
+                                  uint32_t offset,
+                                  arm_ucs_http_state_t newHttpState)
+{
+    UC_SRCE_TRACE("ARM_UCS_Get");
+
+    // check current state
+    if (default_config.eventHandler == 0)
+    {
+        UC_SRCE_ERR_MSG("Uninitialized");
+
+        return (arm_uc_error_t){ SRCE_ERR_UNINITIALIZED };
+    }
+    else if (arm_ucs_state.stateHttp != STATE_UCS_HTTP_IDLE)
+    {
+        UC_SRCE_ERR_MSG("Busy");
+
+        return (arm_uc_error_t){ SRCE_ERR_BUSY };
+    }
+
+    // assign new state
+    arm_ucs_state.stateHttp      = newHttpState;
+    arm_ucs_state.uri            = uri;
+    arm_ucs_state.buffer         = buffer;
+    arm_ucs_state.offset         = offset;
+
+    // Call the socket layer to get the requested data
+    arm_uc_error_t result = (arm_uc_error_t){ SRCE_ERR_INVALID_PARAMETER };
+
+    while ((result.error != ERR_NONE) && (arm_ucs_state.retryCount++ < MAX_RETRY))
+    {
+        // restore buffer size on retry
+        arm_ucs_state.buffer->size = arm_ucs_state.buffer->size_max;
+
+        switch(arm_ucs_state.stateHttp)
+        {
+            case STATE_UCS_HTTP_MANIFEST:
+            case STATE_UCS_HTTP_FIRMWARE:
+                if (arm_ucs_state.buffer != 0 && arm_ucs_state.uri != 0)
+                {
+                    result = ARM_UCS_HttpSocket_GetFragment(arm_ucs_state.uri,
+                                                            arm_ucs_state.buffer,
+                                                            arm_ucs_state.offset);
+                }
+                break;
+
+            case STATE_UCS_HTTP_KEYTABLE:
+                if (arm_ucs_state.buffer != 0 && arm_ucs_state.uri != 0)
+                {
+                    result = ARM_UCS_HttpSocket_GetFile(arm_ucs_state.uri,
+                                                        arm_ucs_state.buffer);
+                }
+                break;
+
+            default:
+                UC_SRCE_ERR_MSG("Invalid request parameter");
+                result = (arm_uc_error_t) { SRCE_ERR_INVALID_PARAMETER };
+                break;
+        }
+    }
+
+    if (result.error != ERR_NONE)
+    {
+        uc_state_reset();
+    }
+
+    return result;
+}
+
+/**
+ * @brief Retrieve manifest from the default location.
+ * @details Manifest is stored in supplied buffer.
+ *          Event is generated once manifest is in buffer.
+ *
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetManifestDefault(arm_uc_buffer_t* buffer, uint32_t offset)
+{
+    UC_SRCE_TRACE("ARM_UCS_GetManifestDefault");
+
+    return ARM_UCS_Get(&default_config.manifest, buffer, offset, STATE_UCS_HTTP_MANIFEST);
+}
+
+/**
+ * @brief Retrieve manifest from URL.
+ * @details Manifest is stored in supplied buffer.
+ *          Event is generated once manifest is in buffer.
+ *
+ * @param uri URI struct with manifest location.
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetManifestURL(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer, uint32_t offset)
+{
+    UC_SRCE_TRACE("ARM_UCS_GetManifestURL");
+
+    return ARM_UCS_Get(uri, buffer, offset, STATE_UCS_HTTP_MANIFEST);
+}
+
+/**
+ * @brief Retrieve firmware fragment.
+ * @details Firmware fragment is stored in supplied buffer.
+ *          Event is generated once fragment is in buffer.
+ *
+ * @param uri URI struct with firmware location.
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ * @param offset Firmware offset to retrieve fragment from.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetFirmwareFragment(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer, uint32_t offset)
+{
+    UC_SRCE_TRACE("ARM_UCS_GetFirmwareFragment");
+
+    return ARM_UCS_Get(uri, buffer, offset, STATE_UCS_HTTP_FIRMWARE);
+}
+
+/**
+ * @brief Retrieve a key table from a URL.
+ * @details Key table is stored in supplied buffer.
+ *          Event is generated once fragment is in buffer.
+ *
+ * @param uri URI struct with keytable location.
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetKeytableURL(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer)
+{
+    UC_SRCE_TRACE("ARM_UCS_GetKeytableURL");
+
+    return ARM_UCS_Get(uri, buffer, UINT32_MAX, STATE_UCS_HTTP_KEYTABLE);
+}
+
+ARM_UPDATE_SOURCE ARM_UCS_HTTPSource =
+{
+    .GetVersion             = ARM_UCS_GetVersion,
+    .GetCapabilities        = ARM_UCS_GetCapabilities,
+    .Initialize             = ARM_UCS_Initialize,
+    .Uninitialize           = ARM_UCS_Uninitialize,
+    .GetManifestDefaultCost = ARM_UCS_GetManifestDefaultCost,
+    .GetManifestURLCost     = ARM_UCS_GetManifestURLCost,
+    .GetFirmwareURLCost     = ARM_UCS_GetFirmwareURLCost,
+    .GetKeytableURLCost     = ARM_UCS_GetKeytableURLCost,
+    .GetManifestDefault     = ARM_UCS_GetManifestDefault,
+    .GetManifestURL         = ARM_UCS_GetManifestURL,
+    .GetFirmwareFragment    = ARM_UCS_GetFirmwareFragment,
+    .GetKeytableURL         = ARM_UCS_GetKeytableURL
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http/update-client-source-http/arm_uc_source_http.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,147 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __UPDATE_CLIENT_SOURCE_HTTP_H__
+#define __UPDATE_CLIENT_SOURCE_HTTP_H__
+
+#include "update-client-source/arm_uc_source.h"
+
+/**
+ * @brief Get driver version.
+ * @return Driver version.
+ */
+uint32_t ARM_UCS_GetVersion(void);
+
+/**
+ * @brief Get Source capabilities.
+ * @return Struct containing capabilites. See definition above.
+ */
+ARM_SOURCE_CAPABILITIES ARM_UCS_GetCapabilities(void);
+
+/**
+ * @brief Initialize Source.
+ * @details Function pointer to event handler is passed as argument.
+ *
+ * @param cb_event Function pointer to event handler. See events above.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_Initialize(ARM_SOURCE_SignalEvent_t cb_event);
+
+/**
+ * @brief Uninitialized Source.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_Uninitialize(void);
+
+/**
+ * @brief Cost estimation for retrieving manifest from the default location.
+ * @details The estimation can vary over time and should not be cached too long.
+ *          0x00000000 - The manifest is already downloaded.
+ *          0xFFFFFFFF - Cannot retrieve manifest from this Source.
+ *
+ * @param cost Pointer to variable for the return value.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetManifestDefaultCost(uint32_t* cost);
+
+/**
+ * @brief Cost estimation for retrieving manifest from URL.
+ * @details The estimation can vary over time and should not be cached too long.
+ *          0x00000000 - The manifest is already downloaded.
+ *          0xFFFFFFFF - Cannot retrieve manifest from this Source.
+ *
+ * @param uri URI struct with manifest location.
+ * @param cost Pointer to variable for the return value.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetManifestURLCost(arm_uc_uri_t* uri, uint32_t* cost);
+
+/**
+ * @brief Cost estimation for retrieving firmware from URL.
+ * @details The estimation can vary over time and should not be cached too long.
+ *          0x00000000 - The firmware is already downloaded.
+ *          0xFFFFFFFF - Cannot retrieve firmware from this Source.
+ *
+ * @param uri URI struct with firmware location.
+ * @param cost Pointer to variable for the return value.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetFirmwareURLCost(arm_uc_uri_t* uri, uint32_t* cost);
+
+/**
+ * @brief Cost estimation for retrieving key table from URL.
+ * @details The estimation can vary over time and should not be cached too long.
+ *          0x00000000 - The firmware is already downloaded.
+ *          0xFFFFFFFF - Cannot retrieve firmware from this Source.
+ *
+ * @param uri URI struct with keytable location.
+ * @param cost Pointer to variable for the return value.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetKeytableURLCost(arm_uc_uri_t* uri, uint32_t* cost);
+
+/**
+ * @brief Retrieve manifest from the default location.
+ * @details Manifest is stored in supplied buffer.
+ *          Event is generated once manifest is in buffer.
+ *
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ * @param offset Manifest offset in bytes where the requested fragment begins.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetManifestDefault(arm_uc_buffer_t* buffer, uint32_t offset);
+
+/**
+ * @brief Retrieve manifest from URL.
+ * @details Manifest is stored in supplied buffer.
+ *          Event is generated once manifest is in buffer.
+ *
+ * @param uri URI struct with manifest location.
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ * @param offset Manifest offset in bytes where the requested fragment begins.
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetManifestURL(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer, uint32_t offset);
+
+/**
+ * @brief Retrieve firmware fragment.
+ * @details Firmware fragment is stored in supplied buffer.
+ *          Event is generated once fragment is in buffer.
+ *
+ * @param uri URI struct with firmware location.
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ * @param offset Firmware offset to retrieve fragment from.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetFirmwareFragment(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer, uint32_t offset);
+
+/**
+ * @brief Retrieve a key table from a URL.
+ * @details Key table is stored in supplied buffer.
+ *          Event is generated once fragment is in buffer.
+ *
+ * @param uri URI struct with keytable location.
+ * @param buffer Struct containing byte array, maximum size, and actual size.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_GetKeytableURL(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer);
+
+extern ARM_UPDATE_SOURCE ARM_UCS_HTTPSource;
+
+#endif // __UPDATE_CLIENT_SOURCE_HTTP_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-http/update-client-source-http/arm_uc_source_http_extra.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,69 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __UPDATE_CLIENT_SOURCE_HTTP_EXTRA_H__
+#define __UPDATE_CLIENT_SOURCE_HTTP_EXTRA_H__
+
+#include "update-client-common/arm_uc_common.h"
+
+#include <stdint.h>
+
+/**
+ * @brief Set URI location for the default manifest.
+ * @details The default manifest is polled regularly and generates a
+ *          notification upon change. The URI struct and the content pointer to
+ *          must be valid throughout the lifetime of the application.
+ *
+ * @param uri URI struct with manifest location.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_SetDefaultManifestURL(arm_uc_uri_t* uri);
+
+/**
+ * @brief Set polling interval for notification generation.
+ * @details The default manifest location is polled with this interval.
+ *
+ * @param seconds Seconds between each poll.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UCS_SetPollingInterval(uint32_t seconds);
+
+/**
+ * @brief Main function for the Source.
+ * @details This function will query the default manifest location and generate
+ *          a notification if it has changed since the last time it was checked.
+ *          The number of queries generated is bound by the polling interval.
+ *
+ *          This function should be used on systems with timed callbacks.
+ *
+ * @param buffer arm_uc_buffer_t for storing HTTP header during hash check.
+ * @return Seconds until the next polling interval.
+ */
+uint32_t ARM_UCS_CallMultipleTimes(arm_uc_buffer_t* buffer);
+
+
+typedef struct _ARM_UCS_HTTPLinuxExtra_t
+{
+    arm_uc_error_t (*SetDefaultManifestURL)(arm_uc_uri_t* uri);
+    arm_uc_error_t (*SetPollingInterval)(uint32_t seconds);
+    uint32_t (*CallMultipleTimes)(arm_uc_buffer_t* buffer);
+} ARM_UCS_HTTPSourceExtra_t;
+
+extern ARM_UCS_HTTPSourceExtra_t ARM_UCS_HTTPSourceExtra;
+
+#endif // __UPDATE_CLIENT_SOURCE_HTTP_EXTRA_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-manager/.mbedignore	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,3 @@
+TESTS/tests/sanity/*
+test/*
+*/test/*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-manager/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,166 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-manager/source/arm_uc_source_manager.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,573 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-source-manager/arm_uc_source_manager.h"
+
+#include "update-client-common/arm_uc_common.h"
+#include "update-client-source/arm_uc_source.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+static const ARM_UPDATE_SOURCE* source_registry[MAX_SOURCES];
+static ARM_SOURCE_SignalEvent_t event_cb;
+
+// storage set aside for adding event_cb to the event queue
+static arm_uc_callback_t event_cb_storage = { 0 };
+
+typedef enum {
+    QUERY_TYPE_UNKNOWN,
+    QUERY_TYPE_MANIFEST_DEFAULT,
+    QUERY_TYPE_MANIFEST_URL,
+    QUERY_TYPE_FIRMWARE,
+    QUERY_TYPE_KEYTABLE
+} query_type_t;
+
+typedef struct {
+    arm_uc_uri_t *uri;             // the uri from which the resourced should be fetched
+    arm_uc_buffer_t *buffer;       // buffer given by caller to contain the results of the fetch
+    uint32_t offset;               // offset parameter passed to the source
+    query_type_t type;             // type of request, whether is manifest, firmware or keytable
+    uint8_t excludes[MAX_SOURCES]; // records the tried and failed sources during a get request
+    uint8_t current_source;        // records the index of source use in the get request in progress
+} request_t;
+
+// Hold information about the request in flight, there will always only be one request in flight
+static request_t request_in_flight;
+
+/* ==================================================================== *
+ * Private Functions                                                    *
+ * ==================================================================== */
+
+/**
+ * @brief Initialise a request_t struct, called when a new request
+ *        have been initiated from the hub
+ */
+static arm_uc_error_t ARM_UCSM_RequestStructInit(request_t* request);
+
+/**
+ * @brief The SourceRegistry is an array of ARM_UPDATE_SOURCE
+ */
+static arm_uc_error_t ARM_UCSM_SourceRegistryInit(void);
+static arm_uc_error_t ARM_UCSM_SourceRegistryAdd(const ARM_UPDATE_SOURCE* source);
+static arm_uc_error_t ARM_UCSM_SourceRegistryRemove(const ARM_UPDATE_SOURCE* source);
+
+/**
+ * @brief return the index of the source with the smallest cost
+ * @param url Struct containing URL. NULL for default Manifest.
+ * @param type The type of current request.
+ * @param excludes Pointer to an array of size MAX_SOURCES to indicate
+ *                 sources we want to exclude in the search. Set excludes[i]=1 to
+ *                 exclude source_registry[i]
+ * @param index Used to return the index of the source with the smallest cost
+ */
+static arm_uc_error_t ARM_UCSM_SourceRegistryGetLowestCost(arm_uc_uri_t* uri,
+                                                           query_type_t type,
+                                                           uint8_t* excludes,
+                                                           uint32_t* index);
+
+/**
+ * @brief Find the source of lowest cost and call the corresponding method
+ *        depending on the type of the request. Retry with source of the next
+ *        smallest cost if previous sources failed until the source registry
+ *        is exhausted.
+ */
+static arm_uc_error_t ARM_UCSM_Get(request_t* req);
+
+/**
+ * @brief Catch callbacks from sources to enable error handling
+ */
+static void ARM_UCSM_CallbackWrapper(uint32_t event);
+
+/**
+ * @brief Retry get due to source being busy
+ */
+static void ARM_UCSM_AsyncRetryGet(uint32_t);
+
+/**
+ * @brief Initialise the `Request` struct
+ */
+static arm_uc_error_t ARM_UCSM_RequestStructInit(request_t* request)
+{
+    for (uint32_t i=0; i<MAX_SOURCES; i++)
+    {
+        request->excludes[i] = 0;
+    }
+
+    request->current_source = MAX_SOURCES;
+    request->uri            = NULL;
+    request->offset         = 0;
+    request->type           = QUERY_TYPE_UNKNOWN;
+    request->buffer         = NULL;
+
+    return (arm_uc_error_t){ SOMA_ERR_NONE };
+}
+
+/**
+ * @brief Initialise the source_registry array to NULL
+ */
+static arm_uc_error_t ARM_UCSM_SourceRegistryInit(void)
+{
+    for(uint32_t i=0; i<MAX_SOURCES; i++)
+    {
+        source_registry[i] = NULL;
+    }
+
+    return (arm_uc_error_t){ SOMA_ERR_NONE };
+}
+/**
+ * @brief Returns the index of the given source in the source array,
+ *        or MAX_SOURCES if the source is not found
+ */
+static uint32_t ARM_UCSM_GetIndexOfSource(const ARM_UPDATE_SOURCE* source)
+{
+    uint32_t index = MAX_SOURCES;
+
+    for(uint32_t i=0; i<MAX_SOURCES; i++)
+    {
+        if(source_registry[i] == source)
+        {
+            index = i;
+            break;
+        }
+    }
+    return index;
+}
+
+/**
+ * @brief Add pointer to source to the source_registry array
+ */
+static arm_uc_error_t ARM_UCSM_SourceRegistryAdd(const ARM_UPDATE_SOURCE* source)
+{
+    uint8_t added = 0;
+
+    for(uint32_t i=0; i<MAX_SOURCES; i++)
+    {
+        if(source_registry[i] == NULL)
+        {
+            source_registry[i] = source;
+            added = 1;
+            break;
+        }
+    }
+
+    if (added == 0) // registry full
+    {
+        return (arm_uc_error_t){ SOMA_ERR_SOURCE_REGISTRY_FULL };
+    }
+
+    return (arm_uc_error_t){ SOMA_ERR_NONE };
+}
+
+/**
+ * @brief Remove pointer to source from the source_registry array
+ */
+static arm_uc_error_t ARM_UCSM_SourceRegistryRemove(const ARM_UPDATE_SOURCE* source)
+{
+    uint32_t index = ARM_UCSM_GetIndexOfSource(source);
+
+    if (index == MAX_SOURCES) // source not found
+    {
+        return (arm_uc_error_t){ SOMA_ERR_SOURCE_NOT_FOUND };
+    }
+
+    source_registry[index] = NULL;
+    return (arm_uc_error_t){ SOMA_ERR_NONE };
+}
+
+/**
+ * @brief return the index of the source with the smallest cost
+ * @param url Struct containing URL. NULL for default Manifest.
+ * @param type The type of current request.
+ * @param excludes Pointer to an array of size MAX_SOURCES to indicate
+ *                 sources we want to exclude in the search. Set excludes[i]=1 to
+ *                 exclude source_registry[i]
+ * @param index Used to return the index of the source with the smalllest cost
+ */
+static arm_uc_error_t ARM_UCSM_SourceRegistryGetLowestCost(arm_uc_uri_t* uri,
+                                                           query_type_t type,
+                                                           uint8_t* excludes,
+                                                           uint32_t* index)
+{
+    uint32_t min_cost = UINT32_MAX;
+    uint32_t min_cost_index = 0;
+    arm_uc_error_t retval = (arm_uc_error_t){ SOMA_ERR_NONE };
+
+    UC_SRCE_TRACE("+ARM_UCSM_SourceRegistryGetLowestCost");
+
+    // loop through all sources
+    for (uint32_t i=0; i<MAX_SOURCES; i++)
+    {
+        // if source is NULL or it has been explicitly excluded because of failure before
+        if (source_registry[i] == NULL || (excludes != NULL && excludes[i] == 1))
+        {
+            continue;
+        }
+
+        ARM_SOURCE_CAPABILITIES cap  = source_registry[i]->GetCapabilities();
+
+        uint32_t cost = UINT32_MAX;
+        if (uri == NULL && type == QUERY_TYPE_MANIFEST_DEFAULT && cap.manifest_default == 1)
+        {
+            retval = source_registry[i]->GetManifestDefaultCost(&cost);
+        }
+        else if (uri != NULL && type == QUERY_TYPE_MANIFEST_URL && cap.manifest_url == 1)
+        {
+            retval = source_registry[i]->GetManifestURLCost(uri, &cost);
+        }
+        else if (uri != NULL && type == QUERY_TYPE_FIRMWARE && cap.firmware == 1)
+        {
+            retval = source_registry[i]->GetFirmwareURLCost(uri, &cost);
+        }
+        else if (uri != NULL && type == QUERY_TYPE_KEYTABLE && cap.keytable == 1)
+        {
+            retval = source_registry[i]->GetKeytableURLCost(uri, &cost);
+        }
+
+        if (retval.code != SRCE_ERR_NONE) // get cost from source i failed
+        {
+            // cost is invalid at this point, hence skip to next iteration
+            UC_SRCE_TRACE("-ARM_UCSM_SourceRegistryGetLowestCost: invalid cost for %" PRIu32, i);
+            continue;
+        }
+
+        // record the cost and i if cost is lower
+        if (min_cost > cost)
+        {
+            min_cost = cost;
+            min_cost_index = i;
+        }
+    }
+
+    if (min_cost == UINT32_MAX)
+    {
+        UC_SRCE_TRACE("-ARM_UCSM_SourceRegistryGetLowestCost: Error - No route");
+        return (arm_uc_error_t){ SOMA_ERR_NO_ROUTE_TO_SOURCE };
+    }
+
+    *index = min_cost_index;
+    UC_SRCE_TRACE("-ARM_UCSM_SourceRegistryGetLowestCost: index = %" PRIu32, min_cost_index);
+    return (arm_uc_error_t){ SOMA_ERR_NONE };
+}
+
+/**
+ * @brief Find the source of lowest cost and call the corresponding method
+ *        depending on the type of the request. Retry with source of the next
+ *        smallest cost if previous sources failed until the source registry
+ *        is exhausted.
+ */
+static arm_uc_error_t ARM_UCSM_Get(request_t* req)
+{
+    UC_SRCE_TRACE("+ARM_UCSM_Get");
+    if (req->uri != NULL)
+    {
+        UC_SRCE_TRACE("with %" PRIx32 ", host [%s], path [%s], type %" PRIu32,
+                req->uri, req->uri->host,req->uri->path, req->type);
+    }
+    else
+    {
+        UC_SRCE_TRACE("with NULL, type %" PRIu32,
+                req->type);
+    }
+
+    uint32_t index = 0;
+
+    // get the source of lowest cost
+    arm_uc_error_t retval = ARM_UCSM_SourceRegistryGetLowestCost(req->uri,
+                                                                 req->type,
+                                                                 req->excludes,
+                                                                 &index);
+    if (retval.code != SOMA_ERR_NONE)
+    {
+        UC_SRCE_TRACE("-ARM_UCSM_Get: error retval.code %" PRIu32, retval.code);
+        return retval;
+    }
+
+    if ((req->uri == NULL) && (req->type == QUERY_TYPE_MANIFEST_DEFAULT))
+    {
+        UC_SRCE_TRACE("calling source %" PRIu32 " GetManifestDefault", index);
+        retval = source_registry[index]->GetManifestDefault(req->buffer, req->offset);
+    }
+    else if ((req->uri != NULL) && (req->type == QUERY_TYPE_MANIFEST_URL))
+    {
+        UC_SRCE_TRACE("calling source %" PRIu32 " GetManifestURL with %" PRIx32, index, req->uri);
+        retval = source_registry[index]->GetManifestURL(req->uri, req->buffer, req->offset);
+    }
+    else if ((req->uri != NULL) && (req->type == QUERY_TYPE_FIRMWARE))
+    {
+        UC_SRCE_TRACE("calling source %" PRIu32 " GetFirmwareFragment with %" PRIx32, index, req->uri);
+        retval = source_registry[index]->GetFirmwareFragment(req->uri, req->buffer, req->offset);
+    }
+    else if ((req->uri != NULL) && (req->type == QUERY_TYPE_KEYTABLE))
+    {
+        UC_SRCE_TRACE("calling source %" PRIu32 " GetKeytableURL with %" PRIx32, index, req->uri);
+        retval = source_registry[index]->GetKeytableURL(req->uri, req->buffer);
+    }
+    else
+    {
+        if (req->uri == NULL ) {
+            UC_SRCE_TRACE("-ARM_UCSM_Get: Error - Invalid parameter (URI == NULL)");
+        } else {
+        	UC_SRCE_TRACE("-ARM_UCSM_Get: Error - Invalid parameter (unknown request type)");
+        }
+        return (arm_uc_error_t){ SOMA_ERR_INVALID_PARAMETER };
+    }
+
+    if (retval.code == SRCE_ERR_BUSY)
+    {
+        UC_SRCE_TRACE("-ARM_UCSM_Get: Error - Busy -> PostCallback AsyncRetryGet");
+        ARM_UC_PostCallback(&event_cb_storage, ARM_UCSM_AsyncRetryGet, 0);
+        return (arm_uc_error_t){ SOMA_ERR_NONE };
+    }
+    else if (retval.error != ERR_NONE)
+    {
+        // failure, try source with the next smallest cost
+        req->excludes[index] = 1;
+        UC_SRCE_TRACE("-ARM_UCSM_Get: Error - failure (try source with the next smallest cost)");
+        return ARM_UCSM_Get(req);
+    }
+
+    // record the index of source handling the get request currently
+    req->current_source = index;
+    UC_SRCE_TRACE("-ARM_UCSM_Get: Using source %" PRIu32, index);
+
+    return (arm_uc_error_t){ SOMA_ERR_NONE };
+}
+
+/**
+ * @brief If source is busy ARM_UCSM_AsyncRetryGet is registered with
+          the event queue so it is called again to retry the same source
+ */
+static void ARM_UCSM_AsyncRetryGet(uint32_t unused)
+{
+    (void) unused;
+
+    UC_SRCE_TRACE("+ARM_UCSM_AsyncRetryGet");
+    arm_uc_error_t retval = ARM_UCSM_Get(&request_in_flight);
+    if (retval.error != ERR_NONE)
+    {
+        ARM_UCSM_RequestStructInit(&request_in_flight);
+        ARM_UC_PostCallback(&event_cb_storage, event_cb, ARM_UC_SM_EVENT_ERROR);
+    }
+    UC_SRCE_TRACE("-ARM_UCSM_AsyncRetryGet");
+}
+
+/**
+ * @brief Translate source event into source manager event
+ */
+static ARM_UC_SM_Event_t ARM_UCSM_TranslateEvent(uint32_t source_event)
+{
+    ARM_UC_SM_Event_t event = ARM_UC_SM_EVENT_ERROR;
+
+    switch(source_event)
+    {
+        case EVENT_NOTIFICATION:
+            event = ARM_UC_SM_EVENT_NOTIFICATION;
+            break;
+        case EVENT_MANIFEST:
+            event = ARM_UC_SM_EVENT_MANIFEST;
+            break;
+        case EVENT_FIRMWARE:
+            event = ARM_UC_SM_EVENT_FIRMWARE;
+            break;
+        case EVENT_KEYTABLE:
+            event = ARM_UC_SM_EVENT_KEYTABLE;
+            break;
+        case EVENT_ERROR:
+            event = ARM_UC_SM_EVENT_ERROR;
+            break;
+        case EVENT_ERROR_BUFFER_SIZE:
+            event = ARM_UC_SM_EVENT_ERROR_BUFFER_SIZE;
+            break;
+    }
+
+    return event;
+}
+
+/**
+ * @brief Catch callbacks from sources to enable error handling
+ */
+static void ARM_UCSM_CallbackWrapper(uint32_t source_event)
+{
+    UC_SRCE_TRACE("+ARM_UCSM_CallbackWrapper");
+    UC_SRCE_TRACE("source_event == %" PRIu32, source_event);
+    ARM_UC_SM_Event_t event = ARM_UCSM_TranslateEvent(source_event);
+
+    if (event == ARM_UC_SM_EVENT_ERROR && request_in_flight.type != QUERY_TYPE_UNKNOWN)
+    {
+        UC_SRCE_TRACE("ARM_UCSM_TranslateEvent event error == %" PRIu32, event);
+        request_in_flight.excludes[request_in_flight.current_source] = 1;
+        arm_uc_error_t retval = ARM_UCSM_Get(&request_in_flight);
+        if (retval.code != SOMA_ERR_NONE)
+        {
+            UC_SRCE_TRACE("ARM_UCSM_Get() retval.code == %" PRIu32, retval.code);
+            ARM_UCSM_RequestStructInit(&request_in_flight);
+            ARM_UC_PostCallback(&event_cb_storage, event_cb, event);
+        }
+    }
+    else
+    {
+        UC_SRCE_TRACE("");
+        ARM_UCSM_RequestStructInit(&request_in_flight);
+        ARM_UC_PostCallback(&event_cb_storage, event_cb, event);
+    }
+    UC_SRCE_TRACE("-ARM_UCSM_CallbackWrapper");
+}
+
+/* ==================================================================== *
+ * Public API                                                           *
+ * ==================================================================== */
+
+/* further documentation of the API can be found in source_manager.h */
+
+arm_uc_error_t ARM_UCSM_Initialize(ARM_SOURCE_SignalEvent_t callback)
+{
+    // remember the callback
+    event_cb = callback;
+
+    // init source_registry to NULL
+    return ARM_UCSM_SourceRegistryInit();
+}
+
+arm_uc_error_t ARM_UCSM_Uninitialize()
+{
+    for (size_t i = 0; i < MAX_SOURCES; i++)
+    {
+        if (source_registry[i] != NULL)
+        {
+            source_registry[i]->Uninitialize();
+            source_registry[i] = NULL;
+        }
+    }
+    return (arm_uc_error_t){ERR_NONE};
+}
+
+arm_uc_error_t ARM_UCSM_AddSource(const ARM_UPDATE_SOURCE* source)
+{
+    if (ARM_UCSM_GetIndexOfSource(source) != MAX_SOURCES)
+    {
+        // Source already added, don't add again
+        // TODO: should this return SOMA_ERR_NONE or a new error
+        // SOMA_ERR_ALREADY_PRESENT?
+        return (arm_uc_error_t){ SOMA_ERR_NONE };
+    }
+    source->Initialize(ARM_UCSM_CallbackWrapper);
+    return ARM_UCSM_SourceRegistryAdd(source);
+}
+
+arm_uc_error_t ARM_UCSM_RemoveSource(const ARM_UPDATE_SOURCE* source)
+{
+    arm_uc_error_t err = ARM_UCSM_SourceRegistryRemove(source);
+    if (err.code == SOMA_ERR_NONE)
+    {
+        // Call 'uninitialize' only if the source was found (and removed)
+        source->Uninitialize();
+    }
+    return err;
+}
+
+/* All the `Get` APIs map into `ARM_UCSM_Get` */
+
+arm_uc_error_t ARM_UCSM_GetManifest(arm_uc_buffer_t* buffer, uint32_t offset)
+{
+    UC_SRCE_TRACE("+ARM_UCSM_GetManifest");
+    ARM_UCSM_RequestStructInit(&request_in_flight);
+    request_in_flight.buffer = buffer;
+    request_in_flight.offset = offset;
+    request_in_flight.type   = QUERY_TYPE_MANIFEST_DEFAULT;
+
+    arm_uc_error_t retval = ARM_UCSM_Get(&request_in_flight);
+    if (retval.code != SOMA_ERR_NONE)
+    {
+        ARM_UCSM_RequestStructInit(&request_in_flight);
+    }
+
+    UC_SRCE_TRACE("-ARM_UCSM_GetManifest");
+    return retval;
+}
+
+arm_uc_error_t ARM_UCSM_GetManifestFrom(arm_uc_uri_t* uri,
+                                        arm_uc_buffer_t* buffer,
+                                        uint32_t offset)
+{
+    UC_SRCE_TRACE("+ARM_UCSM_GetManifestFrom");
+    ARM_UCSM_RequestStructInit(&request_in_flight);
+    request_in_flight.uri    = uri;
+    request_in_flight.buffer = buffer;
+    request_in_flight.offset = offset;
+    request_in_flight.type   = QUERY_TYPE_MANIFEST_URL;
+
+    arm_uc_error_t retval = ARM_UCSM_Get(&request_in_flight);
+    if (retval.code != SOMA_ERR_NONE)
+    {
+        ARM_UCSM_RequestStructInit(&request_in_flight);
+    }
+
+    UC_SRCE_TRACE("-ARM_UCSM_GetManifestFrom");
+    return retval;
+}
+
+arm_uc_error_t ARM_UCSM_GetFirmwareFragment(arm_uc_uri_t* uri,
+                                            arm_uc_buffer_t* buffer,
+                                            uint32_t offset)
+{
+    UC_SRCE_TRACE("+ARM_UCSM_GetFirmwareFragment");
+    ARM_UCSM_RequestStructInit(&request_in_flight);
+    request_in_flight.uri    = uri;
+    request_in_flight.buffer = buffer;
+    request_in_flight.offset = offset;
+    request_in_flight.type   = QUERY_TYPE_FIRMWARE;
+
+    arm_uc_error_t retval = ARM_UCSM_Get(&request_in_flight);
+    if (retval.code != SOMA_ERR_NONE)
+    {
+        ARM_UCSM_RequestStructInit(&request_in_flight);
+    }
+
+    UC_SRCE_TRACE("-ARM_UCSM_GetFirmwareFragment");
+    return retval;
+}
+
+arm_uc_error_t ARM_UCSM_GetKeytable(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer)
+{
+    UC_SRCE_TRACE("+ARM_UCSM_GetKeytable");
+    ARM_UCSM_RequestStructInit(&request_in_flight);
+    request_in_flight.uri    = uri;
+    request_in_flight.buffer = buffer;
+    request_in_flight.type   = QUERY_TYPE_KEYTABLE;
+
+    arm_uc_error_t retval = ARM_UCSM_Get(&request_in_flight);
+    if (retval.code != SOMA_ERR_NONE)
+    {
+        ARM_UCSM_RequestStructInit(&request_in_flight);
+    }
+
+    UC_SRCE_TRACE("+ARM_UCSM_GetKeytable");
+    return retval;
+}
+
+ARM_UC_SOURCE_MANAGER_t ARM_UC_SourceManager = {
+    .Initialize          = ARM_UCSM_Initialize,
+    .Uninitialize        = ARM_UCSM_Uninitialize,
+    .AddSource           = ARM_UCSM_AddSource,
+    .RemoveSource        = ARM_UCSM_RemoveSource,
+    .GetManifest         = ARM_UCSM_GetManifest,
+    .GetManifestFrom     = ARM_UCSM_GetManifestFrom,
+    .GetFirmwareFragment = ARM_UCSM_GetFirmwareFragment,
+    .GetKeytable         = ARM_UCSM_GetKeytable
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source-manager/update-client-source-manager/arm_uc_source_manager.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,146 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_SOURCE_MANAGER_H
+#define ARM_UC_SOURCE_MANAGER_H
+
+#include "update-client-common/arm_uc_common.h"
+#include "update-client-source/arm_uc_source.h"
+
+typedef enum {
+    ARM_UC_SM_EVENT_NOTIFICATION,
+    ARM_UC_SM_EVENT_MANIFEST,
+    ARM_UC_SM_EVENT_FIRMWARE,
+    ARM_UC_SM_EVENT_KEYTABLE,
+    ARM_UC_SM_EVENT_ERROR,
+    ARM_UC_SM_EVENT_ERROR_BUFFER_SIZE
+} ARM_UC_SM_Event_t;
+
+typedef struct _ARM_UC_SOURCE_MANAGER {
+
+    /**
+     * @brief Initialize module and register event handler.
+     * @details The event handler is shared among all asynchronous calls.
+     *
+     * @param  callback Function pointer to event handler.
+     * @return Error code.
+     */
+    arm_uc_error_t (*Initialize)(ARM_SOURCE_SignalEvent_t event_cb);
+    arm_uc_error_t (*Uninitialize)(void);
+
+    /**
+     * @brief Add firmware source to manager.
+     * @details Each source is represented as a pointer to a struct, containing
+     *          function pointers.
+     *
+     *          For example:
+     *          typedef struct _ARM_UPDATE_SOURCE {
+     *              ARM_DRIVER_VERSION     (*GetVersion)     (void);
+     *              ARM_SOURC_CAPABILITIES (*GetCapabilities)(void);
+     *              int32_t                (*Initialize)     (ARM_SOURCE_SignalEvent_t event);
+     *          } ARM_UPDATE_SOURCE;
+     *
+     * @param source Collection of function pointers to source.
+     * @return Error code.
+     */
+    arm_uc_error_t (*AddSource)(const ARM_UPDATE_SOURCE* source);
+    arm_uc_error_t (*RemoveSource)(const ARM_UPDATE_SOURCE* source);
+
+    /**
+     * @brief Copy manifest into provided buffer.
+     * @details Default manifest location is used. An event is generated when the
+     *          manifest has been received.
+     *
+     * @param buffer Struct holding a byte array, maximum size, and actual size.
+     *
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetManifest)(arm_uc_buffer_t* buffer, uint32_t offset);
+
+    /**
+     * @brief Copy manifest into provided buffer.
+     * @details Manifest location is provided. An event is generated when the
+     *          manifest has been received.
+     *
+     * @param uri Struct containing the URI to the manifest.
+     * @param buffer Struct holding a byte array, maximum size, and actual size.
+     *
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetManifestFrom)(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer, uint32_t offset);
+
+    /**
+     * @brief Copy firmware fragment into provided buffer.
+     * @details Firmware is downloaded one fragment at a time. Each call generates
+     *          an event when the fragment has been received.
+     *
+     * @param uri Struct containing the URI to the manifest.
+     * @param buffer Struct holding a byte array, maximum size, and actual size.
+     * @param offset Firmware offset in bytes where the next fragment begins.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetFirmwareFragment)(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer, uint32_t offset);
+
+    /**
+     * @brief Retrieve key table and write it into provided buffer.
+     * @details An event is generated when the manifest has been received.
+     *
+     * @param uri Struct containing the URI to the keytable.
+     * @param buffer Struct holding a byte array, maximum size, and actual size.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetKeytable)(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer);
+
+} ARM_UC_SOURCE_MANAGER_t;
+
+extern ARM_UC_SOURCE_MANAGER_t ARM_UC_SourceManager;
+
+/**
+ * Usage examples
+ *
+ * void callback(uint32_t event)
+ * {
+ *      switch (event)
+ *      {
+ *          // New manifest is available
+ *          case ARM_UC_SM_EVENT_NOTIFICATION:
+ *              break;
+ *
+ *          // Manifest received from default location
+ *          case ARM_UC_SM_EVENT_MANIFEST:
+ *              break;
+ *
+ *          // Manifest received from URL
+ *          case ARM_UC_SM_EVENT_FIRMWARE:
+ *              break;
+ *
+ *          // Firmware fragment received
+ *          case ARM_UC_SM_EVENT_KEYTABLE:
+ *              break;
+ *      }
+ * }
+ *
+ * void main(int)
+ * {
+ *      // initialize Source Manager with callback handler
+ *      ARM_UC_SourceManager.Initialise(callback);
+ * }
+ *
+ */
+
+#endif /* SOURCE_MANAGER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source/LICENSE	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,166 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/modules/source/update-client-source/arm_uc_source.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,190 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __ARM_UPDATE_SOURCE_H__
+#define __ARM_UPDATE_SOURCE_H__
+
+#include "update-client-common/arm_uc_common.h"
+
+#include <stdint.h>
+
+/**
+ * @brief Struct containing the Source's capabilities.
+ * @details notify: Source can notify about new manifests.
+ *          manifest_default: Source can download manifest from default location.
+ *          manifest_url: Source can download manifest from URL.
+ *          firmware: Source can download firmware from URL.
+ */
+typedef struct _ARM_SOURCE_CAPABILITIES {
+    uint32_t notify: 1;
+    uint32_t manifest_default: 1;
+    uint32_t manifest_url: 1;
+    uint32_t firmware: 1;
+    uint32_t keytable: 1;
+    uint32_t reserved: 27;
+} ARM_SOURCE_CAPABILITIES;
+
+/**
+ * @brief Events passed to event handler.
+ * @details EVENT_NOTIFICATION: New manifest is available.
+ *          EVENT_MANIFEST: Manifest retrieved.
+ *          EVENT_FIRMWARE: Firmware fragment retrieved.
+ */
+typedef enum _ARM_SOURCE_EVENT {
+    EVENT_NOTIFICATION,
+    EVENT_MANIFEST,
+    EVENT_FIRMWARE,
+    EVENT_KEYTABLE,
+    EVENT_ERROR,
+    EVENT_ERROR_BUFFER_SIZE
+} ARM_SOURCE_EVENT;
+
+/**
+ * @brief Prototype for event handler.
+ */
+typedef void (*ARM_SOURCE_SignalEvent_t)(uint32_t event);
+
+/**
+ * @brief Structure definition holding API function pointers.
+ */
+typedef struct _ARM_UPDATE_SOURCE {
+
+    /**
+     * @brief Get driver version.
+     * @return Driver version.
+     */
+    uint32_t (*GetVersion)(void);
+
+    /**
+     * @brief Get Source capabilities.
+     * @return Struct containing capabilites. See definition above.
+     */
+    ARM_SOURCE_CAPABILITIES (*GetCapabilities)(void);
+
+    /**
+     * @brief Initialize Source.
+     * @details Function pointer to event handler is passed as argument.
+     *
+     * @param cb_event Function pointer to event handler. See events above.
+     * @return Error code.
+     */
+    arm_uc_error_t (*Initialize)(ARM_SOURCE_SignalEvent_t cb_event);
+
+    /**
+     * @brief Uninitialized Source.
+     * @return Error code.
+     */
+    arm_uc_error_t (*Uninitialize)(void);
+
+    /**
+     * @brief Cost estimation for retrieving manifest from the default location.
+     * @details The estimation can vary over time and should not be cached too long.
+     *          0x00000000 - The manifest is already downloaded.
+     *          0xFFFFFFFF - Cannot retrieve manifest from this Source.
+     *
+     * @param cost Pointer to variable for the return value.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetManifestDefaultCost)(uint32_t* cost);
+
+    /**
+     * @brief Cost estimation for retrieving manifest from URL.
+     * @details The estimation can vary over time and should not be cached too long.
+     *          0x00000000 - The manifest is already downloaded.
+     *          0xFFFFFFFF - Cannot retrieve manifest from this Source.
+     *
+     * @param uri URI struct with manifest location.
+     * @param cost Pointer to variable for the return value.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetManifestURLCost)(arm_uc_uri_t* uri, uint32_t* cost);
+
+    /**
+     * @brief Cost estimation for retrieving firmware from URL.
+     * @details The estimation can vary over time and should not be cached too long.
+     *          0x00000000 - The firmware is already downloaded.
+     *          0xFFFFFFFF - Cannot retrieve firmware from this Source.
+     *
+     * @param uri URI struct with firmware location.
+     * @param cost Pointer to variable for the return value.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetFirmwareURLCost)(arm_uc_uri_t* uri, uint32_t* cost);
+
+    /**
+     * @brief Cost estimation for retrieving key table from URL.
+     * @details The estimation can vary over time and should not be cached too long.
+     *          0x00000000 - The firmware is already downloaded.
+     *          0xFFFFFFFF - Cannot retrieve firmware from this Source.
+     *
+     * @param uri URI struct with keytable location.
+     * @param cost Pointer to variable for the return value.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetKeytableURLCost)(arm_uc_uri_t* uri, uint32_t* cost);
+
+    /**
+     * @brief Retrieve manifest from the default location.
+     * @details Manifest is stored in supplied buffer.
+     *          Event is generated once manifest is in buffer.
+     *
+     * @param buffer Struct containing byte array, maximum size, and actual size.
+     * @param offset Manifest offset in bytes where the requested fragment begins.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetManifestDefault)(arm_uc_buffer_t* buffer, uint32_t offset);
+
+    /**
+     * @brief Retrieve manifest from URL.
+     * @details Manifest is stored in supplied buffer.
+     *          Event is generated once manifest is in buffer.
+     *
+     * @param uri URI struct with manifest location.
+     * @param buffer Struct containing byte array, maximum size, and actual size.
+     * @param offset Manifest offset in bytes where the requested fragment begins.
+     *
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetManifestURL)(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer, uint32_t offset);
+
+    /**
+     * @brief Retrieve firmware fragment.
+     * @details Firmware fragment is stored in supplied buffer.
+     *          Event is generated once fragment is in buffer.
+     *
+     * @param uri URI struct with firmware location.
+     * @param buffer Struct containing byte array, maximum size, and actual size.
+     * @param offset Firmware offset to retrieve fragment from.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetFirmwareFragment)(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer, uint32_t offset);
+
+    /**
+     * @brief Retrieve a key table from a URL.
+     * @details Key table is stored in supplied buffer.
+     *          Event is generated once fragment is in buffer.
+     *
+     * @param uri URI struct with keytable location.
+     * @param buffer Struct containing byte array, maximum size, and actual size.
+     * @return Error code.
+     */
+    arm_uc_error_t (*GetKeytableURL)(arm_uc_uri_t* uri, arm_uc_buffer_t* buffer);
+
+} ARM_UPDATE_SOURCE;
+
+#endif /* __ARM_UPDATE_SOURCE_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,481 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update-client-hub/update_client_hub.h"
+
+#include "update-client-common/arm_uc_common.h"
+#include "update-client-control-center/arm_uc_control_center.h"
+#include "update-client-control-center/arm_uc_pre_shared_key.h"
+#include "update-client-control-center/arm_uc_certificate.h"
+#include "update-client-source-manager/arm_uc_source_manager.h"
+#include "update-client-firmware-manager/arm_uc_firmware_manager.h"
+#include "update-client-manifest-manager/update-client-manifest-manager.h"
+
+#include "update_client_hub_state_machine.h"
+#include "update_client_hub_event_handlers.h"
+#include "update_client_hub_error_handler.h"
+
+#include "pal4life-device-identity/pal_device_identity.h"
+
+#define HANDLE_INIT_ERROR(retval, msg, ...)\
+    if (retval.error != ERR_NONE)\
+    {\
+        ARM_UC_HUB_setState(ARM_UC_HUB_STATE_UNINITIALIZED);\
+        UC_HUB_ERR_MSG(msg " error code %s", ##__VA_ARGS__, ARM_UC_err2Str(retval));\
+        return retval;\
+    }
+
+static const ARM_UPDATE_SOURCE** arm_uc_sources = NULL;
+static uint8_t arm_uc_sources_size = 0;
+
+static arm_uc_mmContext_t manifestManagerInitContext = { 0 };
+static arm_uc_mmContext_t* pManifestManagerInitContext = &manifestManagerInitContext;
+
+/**
+ * @brief Handle any errors posted by the scheduler.
+ * @details This explicitly runs *not* in interrupt context, the scheduler has a dedicated
+ *            callback structure to ensure it can post at least this event.
+ *          ARM_UC_HUB_ErrorHandler() will invoke the HUB callback that was set up.
+ *          It is up to the external application to go about inducing a reset etc,
+ *            if that is what it decides. Note that the HUB is no longer operable
+ *            and the app should probably Uninitialize it and report an error.
+ *            However, the HUB will attempt some cleanup after it returns.
+ * @param an_event the type of the event causing the error callback.
+ *        The only possible errors from the scheduler are currently:
+ *            ARM_UC_EQ_ERR_POOL_EXHAUSTED
+ *            ARM_UC_EQ_ERR_FAILED_TAKE
+ *        These are passed on to the Hub error handler as an internal error,
+ *          and the hub state is now considered unknown from this perspective.
+ *          (An internal error is considered fatal by the hub.)
+ */
+void UC_HUB_scheduler_error_handler(uint32_t an_event)
+{
+    UC_HUB_ERR_MSG("scheduler error: %" PRIu32, an_event);
+    ARM_UC_HUB_ErrorHandler(HUB_ERR_INTERNAL_ERROR, ARM_UC_HUB_getState());
+}
+
+/**
+ * @brief Call initialiser of all components of the client.
+ *        finish asynchronously, will invoke callback when initialization is done.
+ * @param init_cb the callback to be invoked at the end of initialization.
+ */
+arm_uc_error_t ARM_UC_HUB_Initialize(void (*init_cb)(int32_t))
+{
+    arm_uc_error_t retval;
+
+    if (ARM_UC_HUB_getState() != ARM_UC_HUB_STATE_UNINITIALIZED)
+    {
+        UC_HUB_ERR_MSG("Already Initialized/Initializing");
+        return (arm_uc_error_t){ ERR_INVALID_STATE };
+    }
+    ARM_UC_HUB_setState(ARM_UC_HUB_STATE_INITIALIZING);
+
+    ARM_UC_SchedulerInit();
+    ARM_UC_HUB_setInitializationCallback(init_cb);
+    ARM_UC_SetSchedulerErrorHandler(UC_HUB_scheduler_error_handler);
+
+    /* Register event handler with Control Center. */
+    retval = ARM_UC_ControlCenter_Initialize(ARM_UC_HUB_ControlCenterEventHandler);
+    HANDLE_INIT_ERROR(retval, "Control Center init failed")
+
+    /* Register event handler with Firmware Manager */
+    retval = ARM_UC_FirmwareManager.Initialize(ARM_UC_HUB_FirmwareManagerEventHandler);
+    HANDLE_INIT_ERROR(retval, "Firmware Manager init failed")
+
+    /* Register event handler with Source Manager */
+    retval = ARM_UC_SourceManager.Initialize(ARM_UC_HUB_SourceManagerEventHandler);
+    HANDLE_INIT_ERROR(retval, "Source Manager init failed")
+
+    for (uint8_t index = 0; index < arm_uc_sources_size; index++)
+    {
+        ARM_UC_SourceManager.AddSource(arm_uc_sources[index]);
+    }
+
+    /* Register event handler and add config store implementation to manifest
+       manager.
+    */
+    retval = ARM_UC_mmInit(&pManifestManagerInitContext,
+                           ARM_UC_HUB_ManifestManagerEventHandler,
+                           NULL);
+    HANDLE_INIT_ERROR(retval, "Manifest manager init failed")
+
+    /* add hard coded certificates to the manifest manager */
+    // retval = ARM_UC_mmStoreCertificate(CA_PATH, cert, CERT_SIZE);
+    // if ((retval.error != ERR_NONE) && (retval.code != MFST_ERR_PENDING))
+    // {
+    //     HANDLE_INIT_ERROR(retval, "Manifest manager StoreCertificate failed")
+    // }
+
+    return (arm_uc_error_t){ ERR_NONE };
+}
+
+/**
+ * @brief Process events in the event queue.
+ */
+arm_uc_error_t ARM_UC_HUB_ProcessEvents()
+{
+    ARM_UC_ProcessQueue();
+
+    return (arm_uc_error_t){ ERR_NONE };
+}
+
+/**
+ * @brief Register callback function for when callbacks are added to an empty queue.
+ */
+arm_uc_error_t ARM_UC_HUB_AddNotificationHandler(void (*handler)(void))
+{
+    ARM_UC_AddNotificationHandler(handler);
+
+    return (arm_uc_error_t){ ERR_NONE };
+}
+
+/**
+ * @brief Add source to the Update Client.
+ */
+arm_uc_error_t ARM_UC_HUB_SetSources(const ARM_UPDATE_SOURCE* sources[],
+                                     uint8_t size)
+{
+    arm_uc_sources = sources;
+    arm_uc_sources_size = size;
+
+    return (arm_uc_error_t){ ERR_NONE };
+}
+
+/**
+ * Set PAAL Update implementation
+ */
+arm_uc_error_t ARM_UC_HUB_SetStorage(const ARM_UC_PAAL_UPDATE* implementation)
+{
+    return ARM_UCP_SetPAALUpdate(implementation);
+}
+
+/**
+ * @brief Add monitor to the control center.
+ */
+arm_uc_error_t ARM_UC_HUB_AddMonitor(const ARM_UPDATE_MONITOR* monitor)
+{
+    return ARM_UC_ControlCenter_AddMonitor(monitor);
+}
+
+/**
+ * @brief Temporary error reporting function.
+ */
+void ARM_UC_HUB_AddErrorCallback(void (*callback)(int32_t error))
+{
+    ARM_UC_HUB_AddErrorCallbackInternal(callback);
+}
+
+/**
+ * @brief Authorize request.
+ */
+arm_uc_error_t ARM_UC_Authorize(arm_uc_request_t request)
+{
+    return ARM_UC_ControlCenter_Authorize(request);
+}
+
+/**
+ * @brief Set callback for receiving download progress.
+ * @details User application call for setting callback handler.
+ *          The callback function takes the progreess in percent as argument.
+ *
+ * @param callback Function pointer to the progress function.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_SetProgressHandler(void (*callback)(uint32_t progress, uint32_t total))
+{
+    return ARM_UC_ControlCenter_SetProgressHandler(callback);
+}
+
+/**
+ * @brief Set callback function for authorizing requests.
+ * @details User application call for setting callback handler.
+ *          The callback function takes an enum request and an authorization
+ *          function pointer. To authorize the given request, the caller
+ *          invokes the authorization function.
+ *
+ * @param callback Function pointer to the authorization function.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_SetAuthorizeHandler(void (*callback)(int32_t))
+{
+    return ARM_UC_ControlCenter_SetAuthorityHandler(callback);
+}
+
+/**
+ * @brief Override update authorization handler.
+ * @details Force download and update to progress regardless of authorization
+ *          handler. This function is used for unblocking an update in a buggy
+ *          application.
+ */
+void ARM_UC_OverrideAuthorization(void)
+{
+    ARM_UC_ControlCenter_OverrideAuthorization();
+}
+
+/**
+ * @brief Add certificate.
+ * @details [long description]
+ *
+ * @param certificate Pointer to certiface being added.
+ * @param certificate_length Certificate length.
+ * @param fingerprint Pointer to the fingerprint of the certificate being added.
+ * @param fingerprint_length Fingerprint length.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_AddCertificate(const uint8_t* certificate,
+                                     uint16_t certificate_length,
+                                     const uint8_t* fingerprint,
+                                     uint16_t fingerprint_length,
+                                     void (*callback)(arm_uc_error_t, const arm_uc_buffer_t*))
+{
+    return ARM_UC_Certificate_Add(certificate,
+                                  certificate_length,
+                                  fingerprint,
+                                  fingerprint_length,
+                                  callback);
+}
+
+/**
+ * @brief Set pointer to pre-shared-key with the given size.
+ *
+ * @param key Pointer to pre-shared-key.
+ * @param bits Key size in bits.
+ *
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_AddPreSharedKey(const uint8_t* key, uint16_t bits)
+{
+    return ARM_UC_PreSharedKey_SetKey(key, bits);
+}
+
+/**
+ * @brief Function for setting the vendor ID.
+ * @details The ID is copied to a 16 byte struct. Any data after the first
+ *          16 bytes will be ignored.
+ * @param id Pointer to ID.
+ * @param length Length of ID.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_SetVendorId(const uint8_t* id, uint8_t length)
+{
+    arm_uc_guid_t uuid = { 0 };
+
+    if (id)
+    {
+        for (uint8_t index = 0;
+             (index < sizeof(arm_uc_guid_t) && (index < length));
+             index++)
+        {
+            ((uint8_t*) uuid)[index] = id[index];
+        }
+    }
+
+    return pal_setVendorGuid(&uuid);
+}
+
+/**
+ * @brief Function for setting the class ID.
+ * @details The ID is copied to a 16 byte struct. Any data after the first
+ *          16 bytes will be ignored.
+ * @param id Pointer to ID.
+ * @param length Length of ID.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_SetClassId(const uint8_t* id, uint8_t length)
+{
+    arm_uc_guid_t uuid = { 0 };
+
+    if (id)
+    {
+        for (uint8_t index = 0;
+             (index < sizeof(arm_uc_guid_t) && (index < length));
+             index++)
+        {
+            ((uint8_t*) uuid)[index] = id[index];
+        }
+    }
+
+    return pal_setClassGuid(&uuid);
+}
+
+/**
+ * @brief Function for setting the device ID.
+ * @details The ID is copied to a 16 byte struct. Any data after the first
+ *          16 bytes will be ignored.
+ * @param id Pointer to ID.
+ * @param length Length of ID.
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_SetDeviceId(const uint8_t* id, uint8_t length)
+{
+    arm_uc_guid_t uuid = { 0 };
+
+    if (id)
+    {
+        for (uint8_t index = 0;
+             (index < sizeof(arm_uc_guid_t) && (index < length));
+             index++)
+        {
+            ((uint8_t*) uuid)[index] = id[index];
+        }
+    }
+
+    return pal_setDeviceGuid(&uuid);
+}
+
+/**
+ * @brief Function for reporting the vendor ID.
+ * @details 16 bytes are copied into the supplied buffer.
+ * @param id Pointer to storage for ID. MUST be at least 16 bytes long.
+ * @param id_max the size of the ID buffer
+ * @param id_size pointer to a variable to receive the size of the ID
+ *                written into the buffer (always 16).
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_GetVendorId(uint8_t* id,
+                                  const size_t id_max,
+                                  size_t* id_size)
+{
+    arm_uc_guid_t guid = {0};
+    arm_uc_error_t err = {ERR_NONE};
+    if (id_max < sizeof(arm_uc_guid_t))
+    {
+        err.code = ARM_UC_DI_ERR_SIZE;
+    }
+    if (err.error == ERR_NONE)
+    {
+        err = pal_getVendorGuid(&guid);
+    }
+    if (err.error == ERR_NONE)
+    {
+        memcpy(id, guid, sizeof(arm_uc_guid_t));
+        if (id_size != NULL)
+        {
+            *id_size = sizeof(arm_uc_guid_t);
+        }
+    }
+    return err;
+}
+
+/**
+ * @brief Function for reporting the class ID.
+ * @details 16 bytes are copied into the supplied buffer.
+ * @param id Pointer to storage for ID. MUST be at least 16 bytes long.
+ * @param id_max the size of the ID buffer
+ * @param id_size pointer to a variable to receive the size of the ID
+ *                written into the buffer (always 16).
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_GetClassId(uint8_t* id,
+                                  const size_t id_max,
+                                  size_t* id_size)
+{
+    arm_uc_guid_t guid = {0};
+    arm_uc_error_t err = {ERR_NONE};
+    if (id_max < sizeof(arm_uc_guid_t))
+    {
+        err.code = ARM_UC_DI_ERR_SIZE;
+    }
+    if (err.error == ERR_NONE)
+    {
+        err = pal_getClassGuid(&guid);
+    }
+    if (err.error == ERR_NONE)
+    {
+        memcpy(id, guid, sizeof(arm_uc_guid_t));
+        if (id_size != NULL)
+        {
+            *id_size = sizeof(arm_uc_guid_t);
+        }
+    }
+    return err;
+}
+
+/**
+ * @brief Function for reporting the device ID.
+ * @details 16 bytes are copied into the supplied buffer.
+ * @param id Pointer to storage for ID. MUST be at least 16 bytes long.
+ * @param id_max the size of the ID buffer
+ * @param id_size pointer to a variable to receive the size of the ID
+ *                written into the buffer (always 16).
+ * @return Error code.
+ */
+arm_uc_error_t ARM_UC_GetDeviceId(uint8_t* id,
+                                  const size_t id_max,
+                                  size_t* id_size)
+{
+    arm_uc_guid_t guid = {0};
+    arm_uc_error_t err = {ERR_NONE};
+    if (id_max < sizeof(arm_uc_guid_t))
+    {
+        err.code = ARM_UC_DI_ERR_SIZE;
+    }
+    if (err.error == ERR_NONE)
+    {
+        err = pal_getDeviceGuid(&guid);
+    }
+    if (err.error == ERR_NONE)
+    {
+        memcpy(id, guid, sizeof(arm_uc_guid_t));
+        if (id_size != NULL)
+        {
+            *id_size = sizeof(arm_uc_guid_t);
+        }
+    }
+    return err;
+}
+
+arm_uc_error_t ARM_UC_HUB_Uninitialize(void)
+{
+    if (ARM_UC_HUB_getState() != ARM_UC_HUB_STATE_INITIALIZED)
+    {
+       UC_HUB_ERR_MSG("Update Client not initialized");
+       return (arm_uc_error_t){ ERR_INVALID_STATE };
+    }
+
+    arm_uc_error_t err = ARM_UC_SourceManager.Uninitialize();
+    ARM_UC_HUB_setState(ARM_UC_HUB_STATE_UNINITIALIZED);
+    return err;
+}
+
+/**
+ * @brief Return the details of the active firmware.
+ * @param details Pointer to the firmware details structure.
+ * @return ARM_UC_HUB_ERR_NOT_AVAILABLE if the active firmware details
+ *         are not yet available, ERR_INVALID_PARAMETER if "details" is
+ *         NULL or ERR_NONE for success.
+ */
+arm_uc_error_t ARM_UC_API_GetActiveFirmwareDetails(arm_uc_firmware_details_t* details)
+{
+    arm_uc_error_t err = {ARM_UC_HUB_ERR_NOT_AVAILABLE};
+
+    if (details == NULL)
+    {
+        err.code = ERR_INVALID_PARAMETER;
+    }
+    else
+    {
+        arm_uc_firmware_details_t *hub_details = ARM_UC_HUB_getActiveFirmwareDetails();
+        if (hub_details)
+        {
+            memcpy(details, hub_details, sizeof(arm_uc_firmware_details_t));
+            err.code = ERR_NONE;
+        }
+    }
+    return err;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub_error_handler.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,193 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update_client_hub_error_handler.h"
+
+#include "update-client-control-center/arm_uc_control_center.h"
+#include "update-client-common/arm_uc_common.h"
+
+static void (*arm_uc_error_callback_handler)(int32_t error) = NULL;
+
+void ARM_UC_HUB_AddErrorCallbackInternal(void (*callback)(int32_t error))
+{
+    arm_uc_error_callback_handler = callback;
+}
+
+/**
+ * @brief Error handler.
+ * @details Generates error code for the user application and any registered
+ *          monitors. Also responsible for setting the Hub back to a consistent
+ *          state.
+ *
+ *          Supported error codes:
+ *
+ *          ARM_UC_MONITOR_RESULT_INITIAL
+ *          ARM_UC_MONITOR_RESULT_SUCCESS
+ *          ARM_UC_MONITOR_RESULT_ERROR_STORAGE
+ *          ARM_UC_MONITOR_RESULT_ERROR_MEMORY
+ *          ARM_UC_MONITOR_RESULT_ERROR_CONNECTION
+ *          ARM_UC_MONITOR_RESULT_ERROR_CRC
+ *          ARM_UC_MONITOR_RESULT_ERROR_TYPE
+ *          ARM_UC_MONITOR_RESULT_ERROR_URI
+ *          ARM_UC_MONITOR_RESULT_ERROR_UPDATE
+ *          ARM_UC_MONITOR_RESULT_ERROR_HASH
+ *
+ * @param error arm_uc_error_t code.
+ * @param state Internal Hub state.
+ */
+void ARM_UC_HUB_ErrorHandler(int32_t error, arm_uc_hub_state_t state)
+{
+    UC_HUB_TRACE("error: %" PRIX32 " %d", (uint32_t) error, state);
+
+    int32_t error_external = ARM_UC_WARNING_UNKNOWN;
+    arm_uc_monitor_result_t error_monitor = ARM_UC_MONITOR_RESULT_INITIAL;
+    arm_uc_hub_state_t next_state = ARM_UC_HUB_STATE_WAIT_FOR_ERROR_ACK;
+
+    switch (error)
+    {
+        /* Certificate Manager */
+        case ARM_UC_CM_ERR_NOT_FOUND:
+            UC_HUB_ERR_MSG("ARM_UC_CM_ERR_NOT_FOUND: %" PRIX32,
+                           (uint32_t) ARM_UC_CM_ERR_NOT_FOUND);
+            error_external = ARM_UC_WARNING_CERTIFICATE_NOT_FOUND;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_TYPE;
+            break;
+
+        /* Firmware Manager */
+        case FIRM_ERR_WRITE:
+            UC_HUB_ERR_MSG("FIRM_ERR_WRITE: %" PRIX32,
+                           (uint32_t) FIRM_ERR_WRITE);
+            error_external = ARM_UC_ERROR_WRITE_TO_STORAGE;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_STORAGE;
+            break;
+
+        case FIRM_ERR_INVALID_PARAMETER:
+            UC_HUB_ERR_MSG("FIRM_ERR_INVALID_PARAMETER: %" PRIX32,
+                           (uint32_t) FIRM_ERR_INVALID_PARAMETER);
+            error_external = ARM_UC_ERROR_WRITE_TO_STORAGE;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_STORAGE;
+            break;
+
+        case FIRM_ERR_INVALID_HASH:
+            UC_HUB_ERR_MSG("FIRM_ERR_INVALID_HASH: %" PRIX32,
+                           (uint32_t) FIRM_ERR_INVALID_HASH);
+            error_external = ARM_UC_ERROR_INVALID_HASH;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_HASH;
+            break;
+
+        /* Manifest Manager */
+        case MFST_ERR_NULL_PTR:
+            UC_HUB_ERR_MSG("MFST_ERR_NULL_PTR: %" PRIX32,
+                           (uint32_t) MFST_ERR_NULL_PTR);
+            error_external = ARM_UC_WARNING_IDENTITY_NOT_FOUND;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_TYPE;
+            break;
+
+        case MFST_ERR_GUID_VENDOR:
+            UC_HUB_ERR_MSG("MFST_ERR_GUID_VENDOR: %" PRIX32,
+                           (uint32_t) MFST_ERR_GUID_VENDOR);
+            error_external = ARM_UC_WARNING_VENDOR_MISMATCH;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_TYPE;
+            break;
+
+        case MFST_ERR_GUID_DEVCLASS:
+            UC_HUB_ERR_MSG("MFST_ERR_GUID_DEVCLASS: %" PRIX32,
+                           (uint32_t) MFST_ERR_GUID_DEVCLASS);
+            error_external = ARM_UC_WARNING_CLASS_MISMATCH;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_TYPE;
+            break;
+
+        case MFST_ERR_GUID_DEVICE:
+            UC_HUB_ERR_MSG("MFST_ERR_GUID_DEVICE: %" PRIX32,
+                           (uint32_t) MFST_ERR_GUID_DEVICE);
+            error_external = ARM_UC_WARNING_DEVICE_MISMATCH;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_TYPE;
+            break;
+
+        case MFST_ERR_CERT_INVALID:
+            UC_HUB_ERR_MSG("MFST_ERR_CERT_INVALID: %" PRIX32,
+                           (uint32_t) MFST_ERR_CERT_INVALID);
+            error_external = ARM_UC_WARNING_CERTIFICATE_INVALID;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_TYPE;
+            break;
+
+        case MFST_ERR_INVALID_SIGNATURE:
+            UC_HUB_ERR_MSG("MFST_ERR_INVALID_SIGNATURE: %" PRIX32,
+                           (uint32_t) MFST_ERR_INVALID_SIGNATURE);
+            error_external = ARM_UC_WARNING_SIGNATURE_INVALID;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_TYPE;
+            break;
+
+        /* Source Manager */
+        case SOMA_ERR_INVALID_PARAMETER:
+            UC_HUB_ERR_MSG("SOMA_ERR_INVALID_PARAMETER: %" PRIX32,
+                           (uint32_t) SOMA_ERR_INVALID_PARAMETER);
+            error_external = ARM_UC_WARNING_URI_NOT_FOUND;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_URI;
+            break;
+
+        /* Hub */
+        case HUB_ERR_INTERNAL_ERROR:
+            UC_HUB_ERR_MSG("HUB_ERR_INTERNAL_ERROR: %" PRIX32,
+                           (uint32_t) HUB_ERR_INTERNAL_ERROR);
+            error_external = ARM_UC_FATAL;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_UPDATE;
+            break;
+
+        case HUB_ERR_ROLLBACK_PROTECTION:
+            UC_HUB_ERR_MSG("HUB_ERR_ROLLBACK_PROTECTION: %" PRIX32,
+                           (uint32_t) HUB_ERR_ROLLBACK_PROTECTION);
+            error_external = ARM_UC_WARNING_ROLLBACK_PROTECTION;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_UPDATE;
+            break;
+
+        /* LWM2M source */
+        case HUB_ERR_CONNECTION:
+            UC_HUB_ERR_MSG("HUB_ERR_CONNECTION: %" PRIX32,
+                           (uint32_t) HUB_ERR_CONNECTION);
+            error_external = ARM_UC_ERROR_CONNECTION;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_CONNECTION;
+            /* Prevent a possible infinite loop: when HUB_ERR_CONNECTION is received,
+               the next state was always set to ARM_UC_HUB_STATE_UNKNOWN. However,
+               this function also sends a report which might fail, which will trigger
+               the HUB_ERR_CONNECTION event and will repeat the whole process again,
+               potentially in an inifinite loop in case of network issues. So switch
+               the state to "idle" directly to prevent this.*/
+            next_state = ARM_UC_HUB_STATE_IDLE;
+            break;
+
+        default:
+            UC_HUB_ERR_MSG("Unknown error");
+            error_external = ARM_UC_WARNING_UNKNOWN;
+            error_monitor = ARM_UC_MONITOR_RESULT_ERROR_TYPE;
+            break;
+    }
+
+    /* send error code to monitor */
+    ARM_UC_ControlCenter_ReportUpdateResult(error_monitor);
+
+    /* progress state in hub */
+    ARM_UC_HUB_setState(next_state);
+
+    /* Send the external code to the user application. */
+    if (arm_uc_error_callback_handler) {
+        arm_uc_error_callback_handler(error_external);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub_error_handler.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,38 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_HUB_ERROR_HANDLER_H
+#define ARM_UC_HUB_ERROR_HANDLER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "update_client_hub_state_machine.h"
+
+#include "update-client-common/arm_uc_common.h"
+
+void ARM_UC_HUB_AddErrorCallbackInternal(void (*callback)(int32_t error));
+
+void ARM_UC_HUB_ErrorHandler(int32_t error, arm_uc_hub_state_t state);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ARM_UC_HUB_ERROR_HANDLER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub_event_handlers.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,470 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update_client_hub_event_handlers.h"
+#include "update_client_hub_error_handler.h"
+
+#include "update_client_hub_state_machine.h"
+
+#include "update-client-common/arm_uc_common.h"
+#include "update-client-firmware-manager/arm_uc_firmware_manager.h"
+#include "update-client-manifest-manager/update-client-manifest-manager.h"
+#include "update-client-source-manager/arm_uc_source_manager.h"
+#include "update-client-control-center/arm_uc_control_center.h"
+
+/**
+ * @brief event handler registered with the firmware manager
+ *        events drive state changes of the state machine
+ */
+void ARM_UC_HUB_FirmwareManagerEventHandler(uint32_t event)
+{
+    arm_uc_hub_state_t arm_uc_hub_state = ARM_UC_HUB_getState();
+
+    switch(event)
+    {
+        /* Firmware writing setup complete */
+        case UCFM_EVENT_PREPARE_DONE:
+            UC_HUB_TRACE("UCFM_EVENT_PREPARE_DONE");
+
+            /* Storage prepared for firmware. Download first fragment. */
+            if (arm_uc_hub_state == ARM_UC_HUB_STATE_SETUP_FIRMWARE)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_FETCH_FIRST_FRAGMENT);
+            }
+            else
+            {
+                /* Invalid state, abort and report error. */
+                ARM_UC_HUB_ErrorHandler(FIRM_ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            }
+            break;
+
+        /* Firmware fragment written */
+        case UCFM_EVENT_WRITE_DONE:
+            UC_HUB_TRACE("UCFM_EVENT_WRITE_DONE");
+
+            /* Firmware fragment stored */
+
+            /* Fragment stored before network could finish,
+               i.e., network is the bottleneck:
+               Action:
+                - wait for network to complete
+            */
+            if (arm_uc_hub_state == ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_WAIT_FOR_NETWORK);
+            }
+            /* Fragment stored after network finished,
+               i.e, storage is the bottleneck:
+               Action:
+                - store fragment
+                - download next fragment
+            */
+            else if (arm_uc_hub_state == ARM_UC_HUB_STATE_WAIT_FOR_STORAGE)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD);
+            }
+            /* Last fragment stored.
+               Action:
+                - finalize storage
+            */
+            else if (arm_uc_hub_state == ARM_UC_HUB_STATE_STORE_LAST_FRAGMENT)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_FINALIZE_STORAGE);
+            }
+            else
+            {
+                /* Invalid state, abort and report error. */
+                ARM_UC_HUB_ErrorHandler(FIRM_ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            }
+            break;
+
+        /* Final firmware fragment written and commited */
+        case UCFM_EVENT_FINALIZE_DONE:
+            UC_HUB_TRACE("UCFM_EVENT_FINALIZE_DONE");
+
+            /* Firmware stored and verified. */
+            if (arm_uc_hub_state == ARM_UC_HUB_STATE_FINALIZE_STORAGE)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_STORAGE_FINALIZED);
+            }
+            else
+            {
+                /* Invalid state, abort and report error. */
+                ARM_UC_HUB_ErrorHandler(FIRM_ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            }
+            break;
+
+        /* Firmware image marked as active or installed */
+        case UCFM_EVENT_ACTIVATE_DONE:
+            UC_HUB_TRACE("UCFM_EVENT_ACTIVATE_DONE");
+
+            /* Firmware activated. Reboot system. */
+            if (arm_uc_hub_state == ARM_UC_HUB_STATE_ACTIVATE_FIRMWARE)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_REBOOT);
+            }
+            else
+            {
+                /* Invalid state, abort and report error. */
+                ARM_UC_HUB_ErrorHandler(FIRM_ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            }
+            break;
+
+        case UCFM_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE:
+            UC_HUB_TRACE("UCFM_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_DONE");
+
+            ARM_UC_HUB_setState(ARM_UC_HUB_STATE_REPORT_ACTIVE_HASH);
+            break;
+
+        case UCFM_EVENT_GET_INSTALLER_DETAILS_DONE:
+            UC_HUB_TRACE("UCFM_EVENT_GET_INSTALLER_DETAILS_DONE");
+
+            ARM_UC_HUB_setState(ARM_UC_HUB_STATE_REPORT_INSTALLER_DETAILS);
+            break;
+
+        /* Encountered error while writing firmware */
+        case UCFM_EVENT_WRITE_ERROR:
+            UC_HUB_TRACE("UCFM_EVENT_WRITE_ERROR");
+
+            if ((arm_uc_hub_state == ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD) ||
+                (arm_uc_hub_state == ARM_UC_HUB_STATE_WAIT_FOR_STORAGE) ||
+                (arm_uc_hub_state == ARM_UC_HUB_STATE_STORE_LAST_FRAGMENT))
+            {
+                /* write error. */
+                ARM_UC_HUB_ErrorHandler(FIRM_ERR_WRITE, arm_uc_hub_state);
+            }
+            else
+            {
+                /* Invalid state, abort and report error. */
+                ARM_UC_HUB_ErrorHandler(FIRM_ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            }
+            break;
+
+        /* Encountered error while committing final firmware fragment */
+        case UCFM_EVENT_FINALIZE_ERROR:
+            UC_HUB_TRACE("UCFM_EVENT_FINALIZE_ERROR");
+
+            /* Invalid state, abort and report error. */
+            ARM_UC_HUB_ErrorHandler(FIRM_ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            break;
+
+
+        /* Got an unexpected hash of the firmare image */
+        case UCFM_EVENT_FINALIZE_INVALID_HASH_ERROR:
+            UC_HUB_TRACE("UCFM_EVENT_FINALIZE_INVALID_HASH_ERROR");
+
+            /* Invalid state, abort and report error. */
+            ARM_UC_HUB_ErrorHandler(FIRM_ERR_INVALID_HASH, arm_uc_hub_state);
+            break;
+
+        /* Encountered error while trying to activate or install firmware image */
+        case UCFM_EVENT_ACTIVATE_ERROR:
+            UC_HUB_TRACE("UCFM_EVENT_ACTIVATE_ERROR");
+
+            /* Invalid state, abort and report error. */
+            ARM_UC_HUB_ErrorHandler(FIRM_ERR_ACTIVATE, arm_uc_hub_state);
+            break;
+
+        case UCFM_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_ERROR:
+            /* client should be able to proceed as normal */
+            UC_HUB_TRACE("UCFM_EVENT_GET_ACTIVE_FIRMWARE_DETAILS_ERROR");
+
+            ARM_UC_HUB_setState(ARM_UC_HUB_STATE_GET_INSTALLER_DETAILS);
+            break;
+
+        case UCFM_EVENT_GET_INSTALLER_DETAILS_ERROR:
+            /* client should be able to proceed as normal */
+            UC_HUB_TRACE("UCFM_EVENT_GET_INSTALLER_DETAILS_ERROR");
+
+            ARM_UC_HUB_setState(ARM_UC_HUB_STATE_IDLE);
+            break;
+
+        case UCFM_EVENT_INITIALIZE_DONE:
+            /* TODO Fix whole call chain to support async init */
+            /* swallow async init done event here */
+            UC_HUB_TRACE("UCFM_EVENT_INITIALIZE_DONE");
+            break;
+
+        case UCFM_EVENT_GET_FIRMWARE_DETAILS_DONE:
+            UC_HUB_TRACE("UCFM_EVENT_GET_FIRMWARE_DETAILS_DONE");
+            break;
+
+        case UCFM_EVENT_INITIALIZE_ERROR:
+            UC_HUB_TRACE("UCFM_EVENT_INITIALIZE_ERROR");
+            break;
+
+        case UCFM_EVENT_PREPARE_ERROR:
+            UC_HUB_TRACE("UCFM_EVENT_PREPARE_ERROR");
+            break;
+
+        case UCFM_EVENT_GET_FIRMWARE_DETAILS_ERROR:
+            UC_HUB_TRACE("UCFM_EVENT_GET_FIRMWARE_DETAILS_ERROR");
+            break;
+
+        default:
+            UC_HUB_TRACE("Firmware Manager: Invalid Event: %" PRIu32, event);
+
+            /* Invalid state, abort and report error. */
+            ARM_UC_HUB_ErrorHandler(FIRM_ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            break;
+    }
+}
+
+/**
+ * @brief event handler registered with the manifest manager
+ *        events drive state changes of the state machine
+ */
+void ARM_UC_HUB_ManifestManagerEventHandler(uint32_t event)
+{
+    arm_uc_hub_state_t arm_uc_hub_state = ARM_UC_HUB_getState();
+
+    if (event == ARM_UC_MM_RC_ERROR && arm_uc_hub_state == ARM_UC_HUB_STATE_INITIALIZING)
+    {
+        // TODO: An empty config store may be an error in the future.
+        if (ARM_UC_mmGetError().code == MFST_ERR_NO_MANIFEST)
+        {
+            event = ARM_UC_MM_RC_DONE;
+        }
+    }
+    switch(event)
+    {
+        /* Status: The manifest manager failed during the previous operation.
+           Extract further error information using ARM_UC_mmGetError.
+        */
+        case ARM_UC_MM_RC_ERROR:
+            UC_HUB_TRACE("ARM_UC_MM_RC_ERROR");
+
+            /* Report error. */
+            ARM_UC_HUB_ErrorHandler(ARM_UC_mmGetError().code, arm_uc_hub_state);
+            break;
+
+        /* Unused */
+        case ARM_UC_MM_RC_NONE:
+            UC_HUB_TRACE("ARM_UC_MM_RC_NONE");
+
+            /* Invalid state, abort and report error. */
+            ARM_UC_HUB_ErrorHandler(MFST_ERR_INVALID_STATE, arm_uc_hub_state);
+            break;
+
+        /* Action: The firmware manager needs the manifest specified by
+           ARM_UC_mmGetCurrentManifestDependency in order to keep processing
+           the firmware update.
+        */
+        case ARM_UC_MM_RC_NEED_DEP:
+            UC_HUB_TRACE("ARM_UC_MM_RC_NEED_DEP");
+
+            /* Invalid state, abort and report error. */
+            ARM_UC_HUB_ErrorHandler(MFST_ERR_NO_MANIFEST, arm_uc_hub_state);
+            break;
+
+        /* Action: The firmware manager needs the firmware specified by
+           ARM_UC_mmGetFirmwareInfo in order to keep processing the firmware
+           update.
+        */
+        case ARM_UC_MM_RC_NEED_FW:
+            UC_HUB_TRACE("ARM_UC_MM_RC_NEED_FW");
+
+            /* Download firmware by first reading information from manifest */
+            if(arm_uc_hub_state == ARM_UC_HUB_STATE_MANIFEST_COMPLETE)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_CHECK_VERSION);
+            }
+            else
+            {
+                /* Invalid state, abort and report error. */
+                ARM_UC_HUB_ErrorHandler(MFST_ERR_INVALID_STATE, arm_uc_hub_state);
+            }
+            break;
+
+        /* Status: The last operation completed successfully */
+        case ARM_UC_MM_RC_DONE:
+            UC_HUB_TRACE("ARM_UC_MM_RC_DONE");
+
+            /* Update Hub has been initialized. */
+            if(arm_uc_hub_state == ARM_UC_HUB_STATE_INITIALIZING)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_INITIALIZED);
+            }
+            /* Manifest processed */
+            else if(arm_uc_hub_state == ARM_UC_HUB_STATE_MANIFEST_FETCHED)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_MANIFEST_COMPLETE);
+            }
+            else
+            {
+                /* Invalid state, abort and report error. */
+                ARM_UC_HUB_ErrorHandler(MFST_ERR_INVALID_STATE, arm_uc_hub_state);
+            }
+            break;
+
+        default:
+            UC_HUB_TRACE("Manifest Manager: Invalid Event");
+
+            /* Invalid state, abort and report error. */
+            ARM_UC_HUB_ErrorHandler(MFST_ERR_BAD_EVENT, arm_uc_hub_state);
+            break;
+    }
+}
+
+/**
+ * @brief event handler registered with the source manager
+ *        events drive state changes of the state machine
+ */
+void ARM_UC_HUB_SourceManagerEventHandler(uint32_t event)
+{
+    arm_uc_hub_state_t arm_uc_hub_state = ARM_UC_HUB_getState();
+
+    switch(event)
+    {
+        /* Received notification */
+        case ARM_UC_SM_EVENT_NOTIFICATION:
+            UC_HUB_TRACE("ARM_UC_SM_EVENT_NOTIFICATION");
+
+            /* Fetch manifest */
+            if(arm_uc_hub_state == ARM_UC_HUB_STATE_IDLE)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_NOTIFIED);
+            }
+            /* No else. All notifications are ignored during an ongoing update. */
+            break;
+
+        /* Downloaded manifest */
+        case ARM_UC_SM_EVENT_MANIFEST:
+            UC_HUB_TRACE("ARM_UC_SM_EVENT_MANIFEST");
+
+            /* Process the newly downloaded manifest */
+            if (arm_uc_hub_state == ARM_UC_HUB_STATE_NOTIFIED)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_MANIFEST_FETCHED);
+            }
+            else
+            {
+                /* Invalid state, abort and report error. */
+                ARM_UC_HUB_ErrorHandler(SOMA_ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            }
+            break;
+
+        /* Downloaded firmware fragment */
+        case ARM_UC_SM_EVENT_FIRMWARE:
+            UC_HUB_TRACE("ARM_UC_SM_EVENT_FIRMWARE");
+
+            /* Received firmware fragment */
+
+            /* 1. First fragment received, source and storage idle, or,
+               2. N fragment received after storage went idle.
+               Action:
+                - store fragment
+                - download next fragment
+            */
+            if ((arm_uc_hub_state == ARM_UC_HUB_STATE_FETCH_FIRST_FRAGMENT) ||
+                (arm_uc_hub_state == ARM_UC_HUB_STATE_WAIT_FOR_NETWORK))
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD);
+            }
+            /* 1. N fragment received, storing still in progress,
+               i.e., the storage is the bottleneck:
+               - All buffers are in use, wait for storage
+            */
+            else if (arm_uc_hub_state == ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_WAIT_FOR_STORAGE);
+            }
+            /* Invalid state, abort and report error. */
+            else
+            {
+                ARM_UC_HUB_ErrorHandler(SOMA_ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            }
+            break;
+
+        /* Downloaded keytable */
+        case ARM_UC_SM_EVENT_KEYTABLE:
+            UC_HUB_TRACE("ARM_UC_SM_EVENT_KEYTABLE");
+
+            /* Invalid state, abort and report error. */
+            ARM_UC_HUB_ErrorHandler(SOMA_ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            break;
+
+        /* Source Manager encountered an error */
+        case ARM_UC_SM_EVENT_ERROR:
+            UC_HUB_TRACE("ARM_UC_SM_EVENT_ERROR");
+
+            /* Invalid state, abort and report error. */
+            ARM_UC_HUB_ErrorHandler(SOMA_ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            break;
+
+        default:
+            UC_HUB_TRACE("Source Manager: Invalid Event");
+
+            /* Invalid state, abort and report error. */
+            ARM_UC_HUB_ErrorHandler(SOMA_ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            break;
+    }
+}
+
+void ARM_UC_HUB_ControlCenterEventHandler(uint32_t event)
+{
+    arm_uc_hub_state_t arm_uc_hub_state = ARM_UC_HUB_getState();
+
+    switch(event)
+    {
+        case ARM_UCCC_EVENT_AUTHORIZE_DOWNLOAD:
+            UC_HUB_TRACE("ARM_UCCC_EVENT_AUTHORIZE_DOWNLOAD");
+
+            if (arm_uc_hub_state == ARM_UC_HUB_STATE_WAIT_FOR_DOWNLOAD_AUTHORIZATION)
+            {
+                /* Download approved. Download firmware. */
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_DOWNLOAD_AUTHORIZED);
+            }
+            break;
+
+        case ARM_UCCC_EVENT_AUTHORIZE_INSTALL:
+            UC_HUB_TRACE("ARM_UCCC_EVENT_AUTHORIZE_INSTALL");
+
+            if (arm_uc_hub_state == ARM_UC_HUB_STATE_WAIT_FOR_INSTALL_AUTHORIZATION)
+            {
+                /* Installation approved. Set firmware as active image and reboot. */
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_INSTALL_AUTHORIZED);
+            }
+            break;
+
+        case ARM_UCCC_EVENT_MONITOR_SEND_DONE:
+            UC_HUB_TRACE("ARM_UCCC_EVENT_MONITOR_SEND_DONE");
+
+            if (arm_uc_hub_state == ARM_UC_HUB_STATE_WAIT_FOR_ERROR_ACK)
+            {
+                /* Switch to 'idle' after receiving report notification */
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_IDLE);
+            }
+
+/* TODO: use timeout to ensure callback doesn't stall reboot */
+#if 0
+            if (arm_uc_hub_state == ARM_UC_HUB_STATE_INSTALL_AUTHORIZED)
+            {
+                ARM_UC_HUB_setState(ARM_UC_HUB_STATE_REBOOT);
+            }
+#endif
+            break;
+
+        default:
+            UC_HUB_TRACE("Control Center: Invalid Event");
+
+            /* Invalid state, abort and report error. */
+            ARM_UC_HUB_ErrorHandler(ERR_INVALID_PARAMETER, arm_uc_hub_state);
+            break;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub_event_handlers.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,52 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_HUB_EVENT_HANDLERS_H
+#define ARM_UC_HUB_EVENT_HANDLERS_H
+
+#include <stdint.h>
+
+/**
+ * @brief Event handler for the Firmware Manager.
+ *
+ * @param event Event ID.
+ */
+void ARM_UC_HUB_FirmwareManagerEventHandler(uint32_t event);
+
+/**
+ * @brief Event handler for the Manifest Manager.
+ *
+ * @param event Event ID.
+ */
+void ARM_UC_HUB_ManifestManagerEventHandler(uint32_t event);
+
+/**
+ * @brief Event handler for the Source Manager.
+ *
+ * @param event Event ID.
+ */
+void ARM_UC_HUB_SourceManagerEventHandler(uint32_t event);
+
+/**
+ * @brief Event handler for the Control Center.
+ *
+ * @param event Event ID.
+ */
+void ARM_UC_HUB_ControlCenterEventHandler(uint32_t event);
+
+#endif // ARM_UC_HUB_EVENT_HANDLERS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub_state_machine.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,786 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update_client_hub_state_machine.h"
+#include "update_client_hub_error_handler.h"
+#include "update-client-hub/update_client_hub.h"
+
+#include "update-client-common/arm_uc_common.h"
+#include "update-client-firmware-manager/arm_uc_firmware_manager.h"
+#include "update-client-manifest-manager/update-client-manifest-manager.h"
+#include "update-client-source-manager/arm_uc_source_manager.h"
+#include "update-client-control-center/arm_uc_control_center.h"
+#include "update-client-control-center/arm_uc_pre_shared_key.h"
+
+#include "mbedtls/aes.h"
+
+#include "pal.h"
+
+#include <inttypes.h>
+
+/*****************************************************************************/
+/* Global variables                                                          */
+/*****************************************************************************/
+
+// state of the hub state machine
+static arm_uc_hub_state_t arm_uc_hub_state = ARM_UC_HUB_STATE_UNINITIALIZED;
+
+// the call back function registered by the user to signal end of intilisation
+static void (*arm_uc_hub_init_cb)(int32_t) = NULL;
+
+// The hub uses a double buffer system to speed up firmware download and storage
+#define BUFFER_SIZE_MAX (ARM_UC_BUFFER_SIZE / 2) //  define size of the double buffers
+static uint8_t message[BUFFER_SIZE_MAX];
+static arm_uc_buffer_t front_buffer = {
+    .size_max = BUFFER_SIZE_MAX,
+    .size = 0,
+    .ptr = message
+};
+
+static uint8_t message2[BUFFER_SIZE_MAX];
+static arm_uc_buffer_t back_buffer = {
+    .size_max = BUFFER_SIZE_MAX,
+    .size = 0,
+    .ptr = message2
+};
+
+// version (timestamp) of the current running application
+static arm_uc_firmware_details_t arm_uc_active_details = { 0 };
+static bool arm_uc_active_details_available = false;
+
+// bootloader information
+static arm_uc_installer_details_t arm_uc_installer_details = { 0 };
+
+// variable to keep track of the offset into the firmware image during download
+static uint32_t firmware_offset = 0;
+
+// variable to store the firmware config during firmware manager setup
+// Initialisation with an enum silences a compiler warning for ARM ("188-D: enumerated type mixed with another type").
+static ARM_UCFM_Setup_t arm_uc_hub_firmware_config = { UCFM_MODE_UNINIT };
+
+// buffer to store the decoded firmware key
+#define PLAIN_FIRMWARE_KEY_SIZE 16
+static uint8_t plainFirmwareKey[PLAIN_FIRMWARE_KEY_SIZE];
+static arm_uc_buffer_t arm_uc_hub_plain_key = {
+    .size_max = PLAIN_FIRMWARE_KEY_SIZE,
+    .size     = PLAIN_FIRMWARE_KEY_SIZE,
+    .ptr      = plainFirmwareKey
+};
+
+static arm_uc_mmContext_t manifestManagerContext = { 0 };
+static arm_uc_mmContext_t* pManifestManagerContext = &manifestManagerContext;
+static manifest_firmware_info_t fwinfo = { 0 };
+
+// buffer to store a uri struct
+#define URI_STRING_LEN 256
+uint8_t uri_buffer[URI_STRING_LEN] = {0};
+
+static arm_uc_uri_t uri = {
+    .size_max = sizeof(uri_buffer),
+    .size     = 0,
+    .ptr      = uri_buffer,
+    .port     = 0,
+    .scheme   = URI_SCHEME_NONE,
+    .host     = NULL,
+    .path     = NULL,
+};
+
+/*****************************************************************************/
+/* Debug                                                                     */
+/*****************************************************************************/
+
+#if ARM_UC_HUB_TRACE_ENABLE
+static void arm_uc_hub_debug_output()
+{
+    printf("Manifest timestamp: %" PRIu64 "\r\n", fwinfo.timestamp);
+
+    if (uri.scheme == URI_SCHEME_HTTP)
+    {
+        printf("Firmware URL http://%s:%" PRIu16 "%s\r\n",
+            uri.host, uri.port, uri.path);
+    }
+
+    printf("Firmware size: %" PRIu32 "\r\n",fwinfo.size);
+
+    printf("Firmware hash (%" PRIu32 "): ", fwinfo.hash.size);
+    for (unsigned i = 0; i < fwinfo.hash.size; i++)
+    {
+        printf("%02" PRIx8, fwinfo.hash.ptr[i]);
+    }
+    printf("\r\n");
+
+    if (fwinfo.cipherMode == ARM_UC_MM_CIPHERMODE_PSK)
+    {
+        printf("PSK ID: ");
+        for (unsigned i = 0; i < fwinfo.psk.keyID.size; i++)
+        {
+            printf("%02" PRIx8, *(fwinfo.psk.keyID.ptr+i));
+        }
+        printf("\r\n");
+
+        printf("cipherKey(16): ");
+        for (unsigned i = 0; i < 16; i++)
+        {
+            printf("%02" PRIx8, *(fwinfo.psk.cipherKey.ptr+i));
+        }
+        printf("\r\n");
+
+        printf("Decrypted Firmware Symmetric Key(16): ");
+        for (unsigned i = 0; i < 16; i++)
+        {
+            printf("%02" PRIx8, arm_uc_hub_plain_key.ptr[i]);
+        }
+        printf("\r\n");
+
+        printf("fwinfo.initVector\r\n");
+        for (unsigned i = 0; i < 16; i++)
+        {
+            printf("%02" PRIx8, *(fwinfo.initVector.ptr+i));
+        }
+        printf("\r\n");
+    }
+
+    printf("Storage location: %" PRIu32 "\r\n",
+           arm_uc_hub_firmware_config.package_id);
+}
+#endif
+
+/*****************************************************************************/
+/* State machine                                                             */
+/*****************************************************************************/
+
+/* Short hand for simple error handling code */
+#define HANDLE_ERROR(retval, msg, ...)                  \
+    if (retval.error != ERR_NONE)                       \
+    {                                                   \
+        UC_HUB_ERR_MSG(msg " error code %s",            \
+                       ##__VA_ARGS__,                   \
+                       ARM_UC_err2Str(retval));         \
+        new_state = ARM_UC_HUB_STATE_IDLE;              \
+        break;                                          \
+    }
+
+arm_uc_hub_state_t ARM_UC_HUB_getState()
+{
+    return arm_uc_hub_state;
+}
+
+void ARM_UC_HUB_setInitializationCallback(void (*callback)(int32_t))
+{
+    arm_uc_hub_init_cb = callback;
+}
+
+/**
+ * @brief Return the active firmware details or NULL if they're not yet available.
+ */
+arm_uc_firmware_details_t* ARM_UC_HUB_getActiveFirmwareDetails(void)
+{
+    return arm_uc_active_details_available ? &arm_uc_active_details : NULL;
+}
+
+void ARM_UC_HUB_setState(arm_uc_hub_state_t new_state)
+{
+    arm_uc_error_t retval;
+
+    /* Loop until state is unchanged.
+       First loop is mandatory regardless of current state.
+    */
+    do
+    {
+        /* store new stage */
+        arm_uc_hub_state = new_state;
+
+        switch (arm_uc_hub_state)
+        {
+            /*****************************************************************/
+            /* Initialization                                                */
+            /*****************************************************************/
+            case ARM_UC_HUB_STATE_INITIALIZED:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_INITIALIZED");
+
+                /* signal that the Hub is initialized */
+                if (arm_uc_hub_init_cb)
+                {
+                    arm_uc_hub_init_cb(ARM_UC_INIT_DONE);
+                }
+
+                /* report the active firmware hash to the Cloud in parallel
+                   with the main user application.
+                */
+                arm_uc_active_details_available = false;
+                new_state = ARM_UC_HUB_STATE_GET_ACTIVE_FIRMWARE_DETAILS;
+                break;
+
+            case ARM_UC_HUB_STATE_INITIALIZING:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_INITIALIZING");
+                break;
+
+            /*****************************************************************/
+            /* Report current firmware hash                                  */
+            /*****************************************************************/
+            case ARM_UC_HUB_STATE_GET_ACTIVE_FIRMWARE_DETAILS:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_GET_ACTIVE_FIRMWARE_DETAILS");
+
+                retval = ARM_UC_FirmwareManager.GetActiveFirmwareDetails(&arm_uc_active_details);
+                HANDLE_ERROR(retval, "Firmware manager GetActiveFirmwareDetails failed");
+                break;
+
+            case ARM_UC_HUB_STATE_REPORT_ACTIVE_HASH:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_REPORT_ACTIVE_HASH");
+
+                /* copy hash to buffer */
+                memcpy(front_buffer.ptr,
+                       arm_uc_active_details.hash,
+                       ARM_UC_SHA256_SIZE);
+
+                front_buffer.size = ARM_UC_SHA256_SIZE;
+
+                /* send hash to update service */
+                ARM_UC_ControlCenter_ReportName(&front_buffer);
+
+                /* signal to the API that the firmware details are now available */
+                arm_uc_active_details_available = true;
+
+                new_state = ARM_UC_HUB_STATE_REPORT_ACTIVE_VERSION;
+                break;
+
+            /*****************************************************************/
+            /* Report current firmware version                               */
+            /*****************************************************************/
+            case ARM_UC_HUB_STATE_REPORT_ACTIVE_VERSION:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_REPORT_ACTIVE_VERSION");
+
+                UC_HUB_TRACE("Active version: %" PRIu64,
+                             arm_uc_active_details.version);
+
+                /* send timestamp to update service */
+                ARM_UC_ControlCenter_ReportVersion(arm_uc_active_details.version);
+
+                new_state = ARM_UC_HUB_STATE_GET_INSTALLER_DETAILS;
+                break;
+
+            /*****************************************************************/
+            /* Report bootloader information                                 */
+            /*****************************************************************/
+            case ARM_UC_HUB_STATE_GET_INSTALLER_DETAILS:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_GET_INSTALLER_DETAILS");
+
+                retval = ARM_UC_FirmwareManager.GetInstallerDetails(&arm_uc_installer_details);
+                HANDLE_ERROR(retval, "Firmware manager GetInstallerDetails failed");
+                break;
+
+            case ARM_UC_HUB_STATE_REPORT_INSTALLER_DETAILS:
+            {
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_REPORT_INSTALLER_DETAILS");
+
+#if 0
+                printf("bootloader: ");
+                for (uint32_t index = 0; index < 20; index++)
+                {
+                    printf("%02X", arm_uc_installer_details.arm_hash[index]);
+                }
+                printf("\r\n");
+
+                printf("layout: %" PRIu32 "\r\n", arm_uc_installer_details.layout);
+#endif
+
+                /* report installer details to mbed cloud */
+                arm_uc_buffer_t bootloader_hash = {
+                    .size_max = ARM_UC_SHA256_SIZE,
+                    .size = ARM_UC_SHA256_SIZE,
+                    .ptr = (arm_uc_installer_details.arm_hash)
+                };
+                ARM_UC_ControlCenter_ReportBootloaderHash(&bootloader_hash);
+
+                bootloader_hash.ptr = (arm_uc_installer_details.oem_hash);
+                ARM_UC_ControlCenter_ReportOEMBootloaderHash(&bootloader_hash);
+
+                /* set new state */
+                new_state = ARM_UC_HUB_STATE_IDLE;
+                break;
+            }
+
+            /*****************************************************************/
+            /* Idle                                                          */
+            /*****************************************************************/
+            case ARM_UC_HUB_STATE_IDLE:
+                UC_HUB_TRACE("ARM_UC_MONITOR_STATE_IDLE");
+
+                /* signal monitor that device has entered IDLE state */
+                ARM_UC_ControlCenter_ReportState(ARM_UC_MONITOR_STATE_IDLE);
+                break;
+
+            /*****************************************************************/
+            /* Download manifest                                             */
+            /*****************************************************************/
+            case ARM_UC_HUB_STATE_NOTIFIED:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_NOTIFIED");
+
+                /* notification received of a new manifest, hence go get said manifest */
+                retval = ARM_UC_SourceManager.GetManifest(&front_buffer, 0);
+                HANDLE_ERROR(retval, "Source manager GetManifest failed");
+                break;
+
+            case ARM_UC_HUB_STATE_MANIFEST_FETCHED:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_MANIFEST_FETCHED");
+
+                /* Save the manifest for later */
+                memcpy(&fwinfo.manifestBuffer, front_buffer.ptr,
+                    ARM_UC_util_min(sizeof(fwinfo.manifestBuffer), front_buffer.size));
+                /* Save the manifest size for later */
+                fwinfo.manifestSize = front_buffer.size;
+                /* insert the manifest we just fetched into manifest manager */
+                retval = ARM_UC_mmInsert(&pManifestManagerContext, &front_buffer, &back_buffer,  NULL);
+                if (retval.code != MFST_ERR_PENDING)
+                {
+                    HANDLE_ERROR(retval, "Manifest manager Insert failed")
+                }
+                break;
+
+            /*****************************************************************/
+            /* Rollback protection                                           */
+            /*****************************************************************/
+            case ARM_UC_HUB_STATE_MANIFEST_COMPLETE:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_MANIFEST_COMPLETE");
+
+                /* get the firmware info out of the manifest we just inserted
+                   into the manifest manager
+                */
+                retval = ARM_UC_mmFetchFirmwareInfo(&pManifestManagerContext,
+                                                    &fwinfo,
+                                                    NULL);
+                if (retval.code != MFST_ERR_PENDING)
+                {
+                    HANDLE_ERROR(retval, "Manifest manager fetch info failed")
+                }
+                break;
+
+            case ARM_UC_HUB_STATE_CHECK_VERSION:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_CHECK_VERSION");
+
+                /* only continue if timestamp is newer than active version */
+                if (fwinfo.timestamp > arm_uc_active_details.version)
+                {
+                    /* set new state */
+                    new_state = ARM_UC_HUB_STATE_PREPARE_FIRMWARE_SETUP;
+                }
+                else
+                {
+                    UC_HUB_ERR_MSG("version: %" PRIu64 " <= %" PRIu64,
+                                fwinfo.timestamp,
+                                arm_uc_active_details.version);
+
+                    /* signal warning through external handler */
+                    ARM_UC_HUB_ErrorHandler(HUB_ERR_ROLLBACK_PROTECTION,
+                                            ARM_UC_HUB_STATE_CHECK_VERSION);
+
+                    /* set new state */
+                    new_state = ARM_UC_HUB_STATE_IDLE;
+                }
+                break;
+
+            /*****************************************************************/
+            /* Parse manifest                                                */
+            /*****************************************************************/
+            case ARM_UC_HUB_STATE_PREPARE_FIRMWARE_SETUP:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_PREPARE_FIRMWARE_SETUP");
+
+                /* store pointer to hash */
+                arm_uc_hub_firmware_config.hash = &fwinfo.hash;
+
+                /* parse the url string into a arm_uc_uri_t struct */
+                retval = arm_uc_str2uri(fwinfo.uri.ptr,
+                                        fwinfo.uri.size,
+                                        &uri);
+
+                /* URI-based errors are propagated to monitor */
+                if (retval.error != ERR_NONE)
+                {
+                    /* make sure that the URI string is always 0-terminated */
+                    fwinfo.uri.ptr[fwinfo.uri.size_max - 1] = '\0';
+                    UC_HUB_ERR_MSG("Unable to parse URI string %s", fwinfo.uri.ptr);
+
+                    /* signal warning through external handler */
+                    ARM_UC_HUB_ErrorHandler(SOMA_ERR_INVALID_PARAMETER,
+                                            ARM_UC_HUB_STATE_PREPARE_FIRMWARE_SETUP);
+
+                    /* set new state */
+                    new_state = ARM_UC_HUB_STATE_IDLE;
+                    break;
+                }
+
+                /* store firmware size */
+                arm_uc_hub_firmware_config.package_size = fwinfo.size;
+
+                /* read cryptography mode to determine if firmware is encrypted */
+                switch(fwinfo.cipherMode)
+                {
+                    case ARM_UC_MM_CIPHERMODE_NONE:
+                        arm_uc_hub_firmware_config.mode = UCFM_MODE_NONE_SHA_256;
+                        break;
+
+                    case ARM_UC_MM_CIPHERMODE_PSK:
+                        {
+                            /* Get pre-shared-key from the Control Center */
+                            /* TODO: this call should be asynchronous */
+                            const uint8_t* arm_uc_pre_shared_key = NULL;
+                            retval = ARM_UC_PreSharedKey_GetKey(&arm_uc_pre_shared_key, 128);
+                            HANDLE_ERROR(retval, "Unable to get PSK");
+
+                            /* Decode the firmware key to be used to decode the firmware */
+                            UC_HUB_TRACE("Decoding firmware AES key...");
+                            mbedtls_aes_context ctx;
+                            mbedtls_aes_init(&ctx);
+                            mbedtls_aes_setkey_dec(&ctx, arm_uc_pre_shared_key, 128);
+                            mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_DECRYPT, fwinfo.psk.cipherKey.ptr, arm_uc_hub_plain_key.ptr);
+
+                            arm_uc_hub_firmware_config.mode = UCFM_MODE_AES_CTR_128_SHA_256;
+                            arm_uc_hub_firmware_config.key  = &arm_uc_hub_plain_key;
+                            arm_uc_hub_firmware_config.iv   = &fwinfo.initVector;
+                        }
+                        break;
+
+                    case ARM_UC_MM_CIPHERMODE_CERT_CIPHERKEY:
+                    case ARM_UC_MM_CIPHERMODE_CERT_KEYTABLE:
+                    default:
+                        retval.code = MFST_ERR_CRYPTO_MODE;
+                        HANDLE_ERROR(retval, "Unsupported AES Key distribution mode...");
+                        break;
+                }
+
+                /* check if storage ID has been set */
+                if (fwinfo.strgId.size == 0 || fwinfo.strgId.ptr == NULL)
+                {
+                    /* no storage ID set, use default value 0 */
+                    arm_uc_hub_firmware_config.package_id = 0;
+                }
+                else
+                {
+                    /* check if storage ID is "default" */
+                    uint32_t location = arm_uc_strnstrn(fwinfo.strgId.ptr,
+                                                        fwinfo.strgId.size,
+                                                        (const uint8_t*) "default",
+                                                        7);
+
+                    if (location != UINT32_MAX)
+                    {
+                        arm_uc_hub_firmware_config.package_id = 0;
+                    }
+                    else
+                    {
+                        /* parse storage ID */
+                        bool success = false;
+                        arm_uc_hub_firmware_config.package_id =
+                            arm_uc_str2uint32(fwinfo.strgId.ptr,
+                                              fwinfo.strgId.size,
+                                              &success);
+                    }
+                }
+
+#if ARM_UC_HUB_TRACE_ENABLE
+                arm_uc_hub_debug_output();
+#endif
+
+                /* Set new state */
+                new_state = ARM_UC_HUB_STATE_REQUEST_DOWNLOAD_AUTHORIZATION;
+                break;
+
+            /*****************************************************************/
+            /* Download authorization                                        */
+            /*****************************************************************/
+            case ARM_UC_HUB_STATE_REQUEST_DOWNLOAD_AUTHORIZATION:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_REQUEST_DOWNLOAD_AUTHORIZATION");
+
+                /* Signal control center */
+                ARM_UC_ControlCenter_GetAuthorization(ARM_UCCC_REQUEST_DOWNLOAD);
+
+                /* Set new state */
+                new_state = ARM_UC_HUB_STATE_WAIT_FOR_DOWNLOAD_AUTHORIZATION;
+                break;
+
+            case ARM_UC_HUB_STATE_WAIT_FOR_DOWNLOAD_AUTHORIZATION:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_WAIT_FOR_DOWNLOAD_AUTHORIZATION");
+                break;
+
+            case ARM_UC_HUB_STATE_DOWNLOAD_AUTHORIZED:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_DOWNLOAD_AUTHORIZED");
+
+                /* Set new state */
+                new_state = ARM_UC_HUB_STATE_SETUP_FIRMWARE;
+                break;
+
+            /*****************************************************************/
+            /* Download firmware                                             */
+            /*****************************************************************/
+
+            /* The firmware is downloaded in fragments. While one fragment is
+               written to storage, the next fragment is being downloaded.
+
+               In the ARM_UC_HUB_STATE_FETCH_FIRST_FRAGMENT state, the first
+               fragment is being downloaded. Once completed, the first fragment
+               will be in the front_buffer and both the network stack and
+               storage stack will be idle.
+
+               In the ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD state, the front and
+               back buffers are swapped. The front buffer is being used for
+               downloading the next fragment while the back buffer is being
+               written to storage.
+
+               ARM_UC_FirmwareManager.Write and
+               ARM_UC_SourceManager.GetFirmwareFragment will both finish
+               asynchronously generating two events:
+               ARM_UC_SM_EVENT_FIRMWARE and UCFM_EVENT_UPDATE_DONE.
+
+               If the ARM_UC_SM_EVENT_FIRMWARE event is generated first, the
+               system enters the ARM_UC_HUB_STATE_WAIT_FOR_STORAGE state.
+               If the UCFM_EVENT_UPDATE_DONE event is generated first, the
+               system enters the ARM_UC_HUB_STATE_WAIT_FOR_NETWORK state.
+               The second generated event will move the system back to the
+               ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD state.
+
+               The download will stop once the fragment offset is larger than
+               the firmware size written in the manifest. This moves the system
+               to the ARM_UC_HUB_STATE_STORE_LAST_FRAGMENT state.
+
+               Once the last fragment is written, the newly written firmware
+               committed in the ARM_UC_HUB_STATE_FINALIZE_STORAGE state.
+            */
+            case ARM_UC_HUB_STATE_SETUP_FIRMWARE:
+                {
+                    UC_HUB_TRACE("ARM_UC_HUB_STATE_SETUP_FIRMWARE");
+
+                    /* store the firmware info in the manifest_firmware_info_t struct */
+                    arm_uc_firmware_details_t arm_uc_hub_firmware_details = { 0 };
+
+                    /* use manifest timestamp as firmware header version */
+                    arm_uc_hub_firmware_details.version = fwinfo.timestamp;
+                    arm_uc_hub_firmware_details.size    = fwinfo.size;
+
+                    /* copy hash */
+                    memcpy(arm_uc_hub_firmware_details.hash,
+                        fwinfo.hash.ptr,
+                        ARM_UC_SHA256_SIZE);
+
+    #if 0
+                    memcpy(arm_uc_hub_firmware_details.campaign,
+                        configuration.campaign,
+                        ARM_UC_GUID_SIZE);
+    #endif
+
+                    /* setup the firmware manager to get ready for firmware storage */
+                    retval = ARM_UC_FirmwareManager.Prepare(&arm_uc_hub_firmware_config,
+                                                            &arm_uc_hub_firmware_details,
+                                                            &front_buffer);
+                    HANDLE_ERROR(retval, "ARM_UC_FirmwareManager Setup failed")
+                }
+                break;
+
+            case ARM_UC_HUB_STATE_FETCH_FIRST_FRAGMENT:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_FETCH_FIRST_FRAGMENT");
+
+                /* set state to downloading when trying to fetch the first chunk of firmware */
+                UC_HUB_TRACE("Setting Monitor State: ARM_UC_MONITOR_STATE_DOWNLOADING");
+                ARM_UC_ControlCenter_ReportState(ARM_UC_MONITOR_STATE_DOWNLOADING);
+
+                /* reset download values */
+                front_buffer.size = 0;
+                back_buffer.size = 0;
+                firmware_offset = 0;
+
+                /* Check firmware size before entering the download state machine.
+                   An empty firmware is used for erasing a slot.
+                */
+                if (firmware_offset < fwinfo.size)
+                {
+                    /* get first firmware fragment */
+                    UC_HUB_TRACE("Getting next chunk at offset %" PRIu32,
+                                 firmware_offset);
+                    retval = ARM_UC_SourceManager.GetFirmwareFragment(&uri,
+                                                                      &front_buffer,
+                                                                      firmware_offset);
+                    HANDLE_ERROR(retval, "GetFirmwareFragment failed")
+                }
+                else
+                {
+                    /* No download is necessary, send next state to monitor service
+                       and close storage slot.
+                    */
+                    UC_HUB_TRACE("Firmware empty, skip download phase and finalize");
+                    UC_HUB_TRACE("Setting Monitor State: ARM_UC_MONITOR_STATE_DOWNLOADED");
+                    ARM_UC_ControlCenter_ReportState(ARM_UC_MONITOR_STATE_DOWNLOADED);
+                    new_state = ARM_UC_HUB_STATE_FINALIZE_STORAGE;
+                }
+                break;
+
+            case ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD");
+
+                /* swap the front and back buffers
+                   the back buffer contained just downloaded firmware chunk
+                   the front buffer can now be cleared and used to download new chunk
+                */
+                {
+                    arm_uc_buffer_t temp_buf_ptr = front_buffer;
+                    front_buffer = back_buffer;
+                    back_buffer = temp_buf_ptr;
+                }
+
+                UC_HUB_TRACE("Fragment: %" PRIu32 " %" PRIu32, firmware_offset, back_buffer.size);
+
+                /* increase offset by the amount that we just downloaded */
+                firmware_offset += back_buffer.size;
+
+                /* store the downloaded chunk in the back buffer */
+                if (back_buffer.size > 0)
+                {
+                    retval = ARM_UC_FirmwareManager.Write(&back_buffer);
+                    HANDLE_ERROR(retval, "ARM_UC_FirmwareManager Update failed")
+                }
+
+                /* go fetch a new chunk using the front buffer if more are expected */
+                if (firmware_offset < fwinfo.size)
+                {
+                    front_buffer.size = 0;
+                    UC_HUB_TRACE("Getting next chunk at offset: %" PRIu32, firmware_offset);
+                    retval = ARM_UC_SourceManager.GetFirmwareFragment(&uri, &front_buffer, firmware_offset);
+                    HANDLE_ERROR(retval, "GetFirmwareFragment failed")
+                }
+                else
+                {
+                    UC_HUB_TRACE("Store last fragment");
+                    new_state = ARM_UC_HUB_STATE_STORE_LAST_FRAGMENT;
+                }
+
+                /* report progress */
+                ARM_UC_ControlCenter_ReportProgress(firmware_offset, fwinfo.size);
+                break;
+
+            case ARM_UC_HUB_STATE_WAIT_FOR_STORAGE:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_WAIT_FOR_STORAGE");
+                break;
+
+            case ARM_UC_HUB_STATE_WAIT_FOR_NETWORK:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_WAIT_FOR_NETWORK");
+                break;
+
+            case ARM_UC_HUB_STATE_STORE_LAST_FRAGMENT:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_STORE_LAST_FRAGMENT");
+
+                /* set state to downloaded when the full size of the firmware
+                   have been fetched.
+                */
+                UC_HUB_TRACE("Setting Monitor State: ARM_UC_MONITOR_STATE_DOWNLOADED");
+                ARM_UC_ControlCenter_ReportState(ARM_UC_MONITOR_STATE_DOWNLOADED);
+                break;
+
+            case ARM_UC_HUB_STATE_FINALIZE_STORAGE:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_FINALIZE_STORAGE");
+
+                retval = ARM_UC_FirmwareManager.Finalize(&front_buffer, &back_buffer);
+                HANDLE_ERROR(retval, "ARM_UC_FirmwareManager Finalize failed")
+                break;
+
+            /*****************************************************************/
+            /* Install authorization                                         */
+            /*****************************************************************/
+            case ARM_UC_HUB_STATE_STORAGE_FINALIZED:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_STORAGE_FINALIZED");
+
+                /* Signal control center */
+                ARM_UC_ControlCenter_GetAuthorization(ARM_UCCC_REQUEST_INSTALL);
+
+                /* Set new state */
+                new_state = ARM_UC_HUB_STATE_WAIT_FOR_INSTALL_AUTHORIZATION;
+                break;
+
+            case ARM_UC_HUB_STATE_WAIT_FOR_INSTALL_AUTHORIZATION:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_WAIT_FOR_INSTALL_AUTHORIZATION");
+                break;
+
+            case ARM_UC_HUB_STATE_INSTALL_AUTHORIZED:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_INSTALL_AUTHORIZED");
+
+                UC_HUB_TRACE("Setting Monitor State: ARM_UC_MONITOR_STATE_UPDATING");
+                ARM_UC_ControlCenter_ReportState(ARM_UC_MONITOR_STATE_UPDATING);
+
+/* TODO: set timeout on ReportState before relying on callback to progress state machine */
+                new_state = ARM_UC_HUB_STATE_ACTIVATE_FIRMWARE;
+                break;
+
+            case ARM_UC_HUB_STATE_ACTIVATE_FIRMWARE:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_ACTIVATE_FIRMWARE");
+
+                /* Firmware verification passes, activate firmware image.
+                */
+                ARM_UC_FirmwareManager.Activate(arm_uc_hub_firmware_config.package_id);
+                break;
+
+            case ARM_UC_HUB_STATE_REBOOT:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_REBOOT");
+
+                /* Firmware activated, now reboot the system to apply
+                   the new image.
+                */
+                pal_osReboot();
+
+                /* Reboot not implemented on this platform.
+                   Report new firmware hash and continue operation.
+                */
+                new_state = ARM_UC_HUB_STATE_GET_ACTIVE_FIRMWARE_DETAILS;
+                break;
+
+            /*****************************************************************/
+            /* Error                                                         */
+            /*****************************************************************/
+            case ARM_UC_HUB_STATE_ERROR_FIRMWARE_MANAGER:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_ERROR_FIRMWARE_MANAGER");
+                new_state = ARM_UC_HUB_STATE_IDLE;
+                break;
+
+            case ARM_UC_HUB_STATE_ERROR_MANIFEST_MANAGER:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_ERROR_MANIFEST_MANAGER");
+                new_state = ARM_UC_HUB_STATE_IDLE;
+                break;
+
+            case ARM_UC_HUB_STATE_ERROR_SOURCE_MANAGER:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_ERROR_SOURCE_MANAGER");
+                new_state = ARM_UC_HUB_STATE_IDLE;
+                break;
+
+            case ARM_UC_HUB_STATE_ERROR_CONTROL_CENTER:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_ERROR_CONTROL_CENTER");
+                new_state = ARM_UC_HUB_STATE_IDLE;
+                break;
+
+            case ARM_UC_HUB_STATE_WAIT_FOR_ERROR_ACK:
+                UC_HUB_TRACE("ARM_UC_HUB_STATE_WAIT_FOR_ERROR_ACK");
+                /* Don't change state. The only place where this state is set is in
+                   update_client_hub_error_handler.c, right after reporting the update
+                   result, so we wait for a "report done" event (ARM_UCCC_EVENT_MONITOR_SEND_DONE
+                   in arm_uc_hub_event_handlers.c). The handler for this particular
+                   event will then set the state to 'idle' */
+                break;
+
+            default:
+                new_state = ARM_UC_HUB_STATE_IDLE;
+                break;
+        }
+    }
+    while (arm_uc_hub_state != new_state);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/source/update_client_hub_state_machine.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,100 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_HUB_STATE_MACHINE_H
+#define ARM_UC_HUB_STATE_MACHINE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "update-client-common/arm_uc_common.h"
+
+/**
+ * States in the Update Hub.
+ */
+typedef enum {
+    ARM_UC_HUB_STATE_UNINITIALIZED,
+    ARM_UC_HUB_STATE_INITIALIZING,
+    ARM_UC_HUB_STATE_INITIALIZED,
+    ARM_UC_HUB_STATE_GET_ACTIVE_FIRMWARE_DETAILS,
+    ARM_UC_HUB_STATE_REPORT_ACTIVE_HASH,
+    ARM_UC_HUB_STATE_REPORT_ACTIVE_VERSION,
+    ARM_UC_HUB_STATE_GET_INSTALLER_DETAILS,
+    ARM_UC_HUB_STATE_REPORT_INSTALLER_DETAILS,
+    ARM_UC_HUB_STATE_IDLE,
+    ARM_UC_HUB_STATE_NOTIFIED,
+    ARM_UC_HUB_STATE_CERT_STORED,
+    ARM_UC_HUB_STATE_MANIFEST_FETCHED,
+    ARM_UC_HUB_STATE_MANIFEST_COMPLETE,
+    ARM_UC_HUB_STATE_CHECK_VERSION,
+    ARM_UC_HUB_STATE_PREPARE_FIRMWARE_SETUP,
+    ARM_UC_HUB_STATE_REQUEST_DOWNLOAD_AUTHORIZATION,
+    ARM_UC_HUB_STATE_WAIT_FOR_DOWNLOAD_AUTHORIZATION,
+    ARM_UC_HUB_STATE_DOWNLOAD_AUTHORIZED,
+    ARM_UC_HUB_STATE_SETUP_FIRMWARE,
+    ARM_UC_HUB_STATE_FETCH_FIRST_FRAGMENT,
+    ARM_UC_HUB_STATE_STORE_AND_DOWNLOAD,
+    ARM_UC_HUB_STATE_WAIT_FOR_STORAGE,
+    ARM_UC_HUB_STATE_WAIT_FOR_NETWORK,
+    ARM_UC_HUB_STATE_STORE_LAST_FRAGMENT,
+    ARM_UC_HUB_STATE_FINALIZE_STORAGE,
+    ARM_UC_HUB_STATE_STORAGE_FINALIZED,
+    ARM_UC_HUB_STATE_WAIT_FOR_INSTALL_AUTHORIZATION,
+    ARM_UC_HUB_STATE_INSTALL_AUTHORIZED,
+    ARM_UC_HUB_STATE_ACTIVATE_FIRMWARE,
+    ARM_UC_HUB_STATE_REBOOT,
+    ARM_UC_HUB_STATE_ERROR_FIRMWARE_MANAGER,
+    ARM_UC_HUB_STATE_ERROR_MANIFEST_MANAGER,
+    ARM_UC_HUB_STATE_ERROR_SOURCE_MANAGER,
+    ARM_UC_HUB_STATE_ERROR_CONTROL_CENTER,
+    ARM_UC_HUB_STATE_WAIT_FOR_ERROR_ACK,
+} arm_uc_hub_state_t;
+
+/**
+ * @brief Read internal state.
+ * @return State
+ */
+arm_uc_hub_state_t ARM_UC_HUB_getState(void);
+
+/**
+ * @brief Set internal state.
+ * @details Setting the state will perform actions related to that state.
+ *
+ * @param state New state.
+ */
+void ARM_UC_HUB_setState(arm_uc_hub_state_t state);
+
+/**
+ * @brief Set callback function for when the Update Client is initialized.
+ *
+ * @param callback Function pointer.
+ */
+void ARM_UC_HUB_setInitializationCallback(void (*callback)(int32_t));
+
+/**
+ * @brief Return the active firmware details or NULL if they're not yet available.
+ */
+arm_uc_firmware_details_t* ARM_UC_HUB_getActiveFirmwareDetails(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ARM_UC_HUB_STATE_MACHINE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/update-client-hub/update_client_certificate.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,27 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UC_HUB_CERTIFICATE_H
+#define ARM_UC_HUB_CERTIFICATE_H
+
+#warning This file is deprecated. \
+         Use update-client-control-center/arm_uc_certificate.h instead
+
+#include "update-client-control-center/arm_uc_certificate.h"
+
+#endif // ARM_UC_HUB_CERTIFICATE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/update-client-hub/update_client_hub.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,273 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_CLIENT_HUB_H
+#define ARM_UPDATE_CLIENT_HUB_H
+
+#include "update-client-common/arm_uc_common.h"
+#include "update-client-source/arm_uc_source.h"
+#include "update-client-monitor/arm_uc_monitor.h"
+#include "update-client-control-center/arm_uc_control_center.h"
+#include "update-client-paal/arm_uc_paal_update.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+    /**
+     * Initialization return codes.
+     */
+    enum {
+        ARM_UC_INIT_DONE
+    };
+
+    /**
+     * @brief Start the initialization of the hub.
+     * @details When initilisation finishes, the user callback function
+     *          will be called. The "event" parameter to the callback
+     *          is currently a placeholder that always returns ARM_UC_INIT_DONE.
+     *
+     * @param  function to be called when initilisation is finished.
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_HUB_Initialize(void (*callback)(int32_t));
+
+    /**
+     * @brief Process events in the event queue.
+     * @details The update client is driven by events in an atomic queue,
+     *          the user need to call this function periodically to process
+     *          events in the queue and hence move the client forward.
+     *
+     * @return Error code.
+     * @note Here's a code snippet to suggest how this API might be used by callers:
+     * \code
+     * int main() {
+     *     retval = ARM_UC_Hub.Initialize(init_finish_cb);
+     *     while(true) {
+     *         ARM_UC_Hub.ProcessEvents();
+     *         __WFI();
+     *     }
+     * }
+     * \endcode
+     */
+    arm_uc_error_t ARM_UC_HUB_ProcessEvents(void);
+
+    /**
+     * @brief Register callback function for when callbacks are added to an
+     *        empty queue.
+     * @details This function is called at least once (maybe more) when
+     *          callbacks are added to an empty queue. Useful for scheduling
+     *          when the queue needs to be processed.
+     * @param handler Function pointer to function to be called when elements are
+     *        added to an empty queue.
+     */
+    arm_uc_error_t ARM_UC_HUB_AddNotificationHandler(void (*handler)(void));
+
+    /**
+     * @brief Add sources to the update client.
+     * @details Sources are transport methods for manifest and firmwares.
+     *
+     * @param sources Pointer to an array of source pointers.
+     * @param size Number of elements in the pointer array.
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_HUB_SetSources(const ARM_UPDATE_SOURCE* sources[],
+                                         uint8_t size);
+
+    /**
+     * @brief Set implementation for storing firmware.
+     * @details Storage abstraction for handling different storage medium.
+     *
+     * @param implementation Function pointer struct to Update PAL implementation.
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_HUB_SetStorage(const ARM_UC_PAAL_UPDATE* implementation);
+
+    /**
+     * @brief Add monitor to the update client.
+     * @details Monitors send the update status and results.
+     *
+     * @param  monitor The monitor to be added to the update client.
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_HUB_AddMonitor(const ARM_UPDATE_MONITOR* monitor);
+
+    /**
+     * @brief Temporary error reporting function.
+     * @details This function will be absorbed into the add monitor call.
+     *
+     * @param callback Error reporting function.
+     */
+    void ARM_UC_HUB_AddErrorCallback(void (*callback)(int32_t error));
+
+    /**
+     * @brief Authorize request.
+     * @details Function is called when the user application authorizes
+     *          requests from the Update Client.
+     *
+     * @param request Requests are passed through the callback function.
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_Authorize(arm_uc_request_t request);
+
+    /**
+     * @brief Set callback for receiving download progress.
+     * @details User application call for setting callback handler.
+     *          The callback function takes the progreess in percent as argument.
+     *
+     * @param callback Function pointer to the progress function.
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_SetProgressHandler(void (*callback)(uint32_t progress, uint32_t total));
+
+    /**
+     * @brief Set callback function for authorizing requests.
+     * @details User application call for setting callback handler.
+     *          The callback function takes an enum request and an authorization
+     *          function pointer. To authorize the given request, the caller
+     *          invokes the authorization function.
+     *
+     * @param callback Function pointer to the authorization function.
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_SetAuthorizeHandler(void (*callback)(int32_t));
+
+    /**
+     * @brief Override update authorization handler.
+     * @details Force download and update to progress regardless of authorization
+     *          handler. This function is used for unblocking an update in a buggy
+     *          application.
+     */
+    void ARM_UC_OverrideAuthorization(void);
+
+    /**
+     * @brief Add certificate.
+     * @details [long description]
+     *
+     * @param certificate Pointer to certiface being added.
+     * @param certificate_length Certificate length.
+     * @param fingerprint Pointer to the fingerprint of the certificate being added.
+     * @param fingerprint_length Fingerprint length.
+     * @param callback Callback handler for certificate insertion events.
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_AddCertificate(const uint8_t* certificate,
+                                         uint16_t certificate_length,
+                                         const uint8_t* fingerprint,
+                                         uint16_t fingerprint_length,
+                                         void (*callback)(arm_uc_error_t, const arm_uc_buffer_t*));
+
+    /**
+     * @brief Set pointer to pre-shared-key with the given size.
+     *
+     * @param key Pointer to pre-shared-key.
+     * @param bits Key size in bits.
+     *
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_AddPreSharedKey(const uint8_t* key, uint16_t bits);
+
+    /**
+     * @brief Function for setting the vendor ID.
+     * @details The ID is copied to a 16 byte struct. Any data after the first
+     *          16 bytes will be ignored.
+     * @param id Pointer to ID.
+     * @param length Length of ID.
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_SetVendorId(const uint8_t* id, uint8_t length);
+
+    /**
+     * @brief Function for setting the class ID.
+     * @details The ID is copied to a 16 byte struct. Any data after the first
+     *          16 bytes will be ignored.
+     * @param id Pointer to ID.
+     * @param length Length of ID.
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_SetClassId(const uint8_t* id, uint8_t length);
+
+    /**
+     * @brief Function for setting the device ID.
+     * @details The ID is copied to a 16 byte struct. Any data after the first
+     *          16 bytes will be ignored.
+     * @param id Pointer to ID.
+     * @param length Length of ID.
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_SetDeviceId(const uint8_t* id, uint8_t length);
+
+    /**
+     * @brief Function for reporting the vendor ID.
+     * @details 16 bytes are copied into the supplied buffer.
+     * @param id Pointer to storage for ID. MUST be at least 16 bytes long.
+     * @param id_max the size of the ID buffer
+     * @param id_size pointer to a variable to receive the size of the ID
+     *                written into the buffer (always 16).
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_GetVendorId(uint8_t* id,
+                                      const size_t id_max,
+                                      size_t* id_size);
+
+    /**
+     * @brief Function for reporting the class ID.
+     * @details 16 bytes are copied into the supplied buffer.
+     * @param id Pointer to storage for ID. MUST be at least 16 bytes long.
+     * @param id_max the size of the ID buffer
+     * @param id_size pointer to a variable to receive the size of the ID
+     *                written into the buffer (always 16).
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_GetClassId(uint8_t* id,
+                                      const size_t id_max,
+                                      size_t* id_size);
+
+    /**
+     * @brief Function for reporting the device ID.
+     * @details 16 bytes are copied into the supplied buffer.
+     * @param id Pointer to storage for ID. MUST be at least 16 bytes long.
+     * @param id_max the size of the ID buffer
+     * @param id_size pointer to a variable to receive the size of the ID
+     *                written into the buffer (always 16).
+     * @return Error code.
+     */
+    arm_uc_error_t ARM_UC_GetDeviceId(uint8_t* id,
+                                      const size_t id_max,
+                                      size_t* id_size);
+
+
+    /**
+     * @brief Delete any global allocations.
+     */
+    arm_uc_error_t ARM_UC_HUB_Uninitialize(void);
+
+    /**
+     * @brief Return the details of the active firmware.
+     * @param details Pointer to the firmware details structure.
+     * @return ARM_UC_HUB_ERR_NOT_AVAILABLE if the active firmware details
+     *         are not yet available, ERR_INVALID_PARAMETER if "details" is
+     *         NULL or ERR_NONE for success.
+     */
+    arm_uc_error_t ARM_UC_API_GetActiveFirmwareDetails(arm_uc_firmware_details_t* details);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ARM_UPDATE_CLIENT_HUB_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed-cloud-client/update-client-hub/update-client-hub/update_client_public.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,24 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2017 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef ARM_UPDATE_CLIENT_PUBLIC_H
+#define ARM_UPDATE_CLIENT_PUBLIC_H
+
+#include "update-client-common/arm_uc_public.h"
+
+#endif /* ARM_UPDATE_CLIENT_PUBLIC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed_cloud_client_resource.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,205 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "mbed.h"
+#include "mbed_cloud_client_resource.h"
+#include "simple-mbed-cloud-client.h"
+
+void path_to_ids(const char* path, unsigned int *object_id,
+                 unsigned int *instance_id, unsigned int *resource_id) {
+    int len = strlen(path);
+    char *buffer = new char[len + 1];
+    buffer[len] = '\0';
+    strncpy(buffer, path, len);
+    unsigned int index = 0;
+    char * pch = strtok (buffer, "/");
+
+    unsigned int *ptr;
+    while (pch != NULL && index < 3) {
+        switch (index) {
+            case 0:
+                ptr = object_id;
+            break;
+
+            case 1:
+                ptr = instance_id;
+            break;
+
+            case 2:
+                ptr = resource_id;
+            break;
+        }
+
+        *ptr = atoi(pch);
+        pch = strtok (NULL, "/");
+        index++;
+    }
+
+    delete[] buffer;
+}
+
+MbedCloudClientResource::MbedCloudClientResource(SimpleMbedCloudClient *client, const char *path, const char *name)
+: client(client),
+  resource(NULL),
+  path(path),
+  name(name),
+  putCallback(NULL),
+  postCallback(NULL),
+  notificationCallback(NULL),
+  internalPostCallback(this, &MbedCloudClientResource::internal_post_callback),
+  internalPutCallback(this, &MbedCloudClientResource::internal_put_callback),
+  internalNotificationCallback(this, &MbedCloudClientResource::internal_notification_callback)
+{
+}
+
+void MbedCloudClientResource::observable(bool observable) {
+    this->isObservable = observable;
+}
+
+void MbedCloudClientResource::methods(unsigned int methodMask) {
+    this->methodMask = methodMask;
+}
+
+void MbedCloudClientResource::attach_put_callback(Callback<void(MbedCloudClientResource*, m2m::String)> callback) {
+    this->putCallback = callback;
+}
+
+void MbedCloudClientResource::attach_post_callback(Callback<void(MbedCloudClientResource*, const uint8_t*, uint16_t)> callback) {
+    this->postCallback = callback;
+}
+
+void MbedCloudClientResource::attach_notification_callback(Callback<void(MbedCloudClientResource*, const NoticationDeliveryStatus)> callback) {
+    this->notificationCallback = callback;
+}
+
+void MbedCloudClientResource::detach_put_callback() {
+    this->putCallback = NULL;
+}
+
+void MbedCloudClientResource::detach_post_callback() {
+    this->postCallback = NULL;
+}
+
+void MbedCloudClientResource::detach_notification_callback() {
+    this->notificationCallback = NULL;
+}
+
+void MbedCloudClientResource::set_value(int value) {
+    this->value = "";
+    this->value.append_int(value);
+
+    if (this->resource) {
+        this->resource->set_value((uint8_t*)this->value.c_str(), this->value.size());
+    }
+}
+
+void MbedCloudClientResource::set_value(const char *value) {
+    this->value = value;
+
+    if (this->resource) {
+        this->resource->set_value((uint8_t*)this->value.c_str(), strlen(value));
+    }
+}
+
+void MbedCloudClientResource::set_value(float value) {
+    char str[25];
+    int length = sprintf(str, "%g", value);
+
+    if (this->resource) {
+        this->resource->set_value((uint8_t*)str, length);
+    }
+}
+
+m2m::String MbedCloudClientResource::get_value() {
+    if (this->resource) {
+        return this->resource->get_value_string();
+    } else {
+        return this->value;
+    }
+}
+
+void MbedCloudClientResource::internal_post_callback(void *params) {
+    if (!postCallback) return;
+
+    if (params) { // data can be NULL!
+        M2MResource::M2MExecuteParameter* parameters = static_cast<M2MResource::M2MExecuteParameter*>(params);
+
+        // extract the data that was sent
+        const uint8_t* buffer = parameters->get_argument_value();
+        uint16_t length = parameters->get_argument_value_length();
+
+        postCallback(this, buffer, length);
+    }
+}
+
+void MbedCloudClientResource::internal_put_callback(const char* resource) {
+    if (!putCallback) return;
+
+    putCallback(this, this->get_value());
+}
+
+void MbedCloudClientResource::internal_notification_callback(const M2MBase& m2mbase, const NoticationDeliveryStatus status) {
+    if (!notificationCallback) return;
+
+    notificationCallback(this, status);
+}
+
+const char * MbedCloudClientResource::delivery_status_to_string(const NoticationDeliveryStatus status) {
+    switch(status) {
+        case NOTIFICATION_STATUS_INIT: return "Init";
+        case NOTIFICATION_STATUS_BUILD_ERROR: return "Build error";
+        case NOTIFICATION_STATUS_RESEND_QUEUE_FULL: return "Resend queue full";
+        case NOTIFICATION_STATUS_SENT: return "Sent";
+        case NOTIFICATION_STATUS_DELIVERED: return "Delivered";
+        case NOTIFICATION_STATUS_SEND_FAILED: return "Send failed";
+        case NOTIFICATION_STATUS_SUBSCRIBED: return "Subscribed";
+        case NOTIFICATION_STATUS_UNSUBSCRIBED: return "Unsubscribed";
+        default: return "Unknown";
+    }
+}
+
+M2MResource *MbedCloudClientResource::get_m2m_resource() {
+    return resource;
+}
+
+void MbedCloudClientResource::get_data(mcc_resource_def *resourceDef) {
+    path_to_ids(this->path.c_str(), &(resourceDef->object_id), &(resourceDef->instance_id), &(resourceDef->resource_id));
+    resourceDef->name = this->name;
+    resourceDef->method_mask = this->methodMask;
+    resourceDef->observable = this->isObservable;
+    resourceDef->value = this->get_value();
+    resourceDef->put_callback = &(this->internalPutCallback);
+    resourceDef->post_callback = &(this->internalPostCallback);
+    resourceDef->notification_callback = &(this->internalNotificationCallback);
+}
+
+void MbedCloudClientResource::set_m2m_resource(M2MResource *res) {
+    this->resource = res;
+}
+
+int MbedCloudClientResource::get_value_int() {
+    if (!this->resource) return 0;
+
+    return this->resource->get_value_int();
+}
+
+float MbedCloudClientResource::get_value_float() {
+    if (!this->resource) return 0.0f;
+
+    return atof(this->get_value().c_str());
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/mbed_cloud_client_resource.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,98 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef MBED_CLOUD_CLIENT_RESOURCE_H
+#define MBED_CLOUD_CLIENT_RESOURCE_H
+
+#include "mbed.h"
+#include "simple-mbed-cloud-client.h"
+#include "mbed-client/m2mstring.h"
+
+namespace M2MMethod {
+
+enum M2MMethod {
+    GET    = 0x01,
+    PUT    = 0x02,
+    POST   = 0x04,
+    DELETE = 0x08
+};
+
+};
+
+struct mcc_resource_def {
+    unsigned int object_id;
+    unsigned int instance_id;
+    unsigned int resource_id;
+    String name;
+    unsigned int method_mask;
+    String value;
+    bool observable;
+    Callback<void(const char*)> *put_callback;
+    Callback<void(void*)> *post_callback;
+    Callback<void(const M2MBase&, const NoticationDeliveryStatus)> *notification_callback;
+};
+
+class SimpleMbedCloudClient;
+
+class MbedCloudClientResource {
+    public:
+        MbedCloudClientResource(SimpleMbedCloudClient *client, const char *path, const char *name);
+
+        void observable(bool observable);
+        void methods(unsigned int methodMask);
+        void attach_put_callback(Callback<void(MbedCloudClientResource*, m2m::String)> callback);
+        void attach_post_callback(Callback<void(MbedCloudClientResource*, const uint8_t*, uint16_t)> callback);
+        void attach_notification_callback(Callback<void(MbedCloudClientResource*, const NoticationDeliveryStatus)> callback);
+        void detach_put_callback();
+        void detach_post_callback();
+        void detach_notification_callback();
+        void set_value(int value);
+        void set_value(const char *value);
+        void set_value(float value);
+        m2m::String get_value();
+        int get_value_int();
+        float get_value_float();
+
+        void get_data(mcc_resource_def *resourceDef);
+        void set_m2m_resource(M2MResource *res);
+        M2MResource* get_m2m_resource();
+
+        static const char * delivery_status_to_string(const NoticationDeliveryStatus status);
+
+    private:
+        void internal_post_callback(void* params);
+        void internal_put_callback(const char* resource);
+        void internal_notification_callback(const M2MBase& m2mbase, const NoticationDeliveryStatus status);
+
+        SimpleMbedCloudClient *client;
+        M2MResource *resource;
+        m2m::String path;
+        m2m::String name;
+        m2m::String value;
+        bool isObservable;
+        unsigned int methodMask;
+
+        Callback<void(MbedCloudClientResource*, m2m::String)> putCallback;
+        Callback<void(MbedCloudClientResource*, const uint8_t*, uint16_t)> postCallback;
+        Callback<void(MbedCloudClientResource*, const NoticationDeliveryStatus)> notificationCallback;
+        Callback<void(void*)> internalPostCallback;
+        Callback<void(const char*)> internalPutCallback;
+        Callback<void(const M2MBase&, const NoticationDeliveryStatus)> internalNotificationCallback;
+};
+
+#endif // MBED_CLOUD_CLIENT_RESOURCE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/memory_tests.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,222 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifdef TARGET_LIKE_MBED
+
+#ifdef MBED_HEAP_STATS_ENABLED
+// used by print_heap_stats only
+#include "mbed_stats.h"
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include "mbed-client/m2mbase.h"
+#endif
+
+// fixup the compilation on AMRCC for PRIu32
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include "memory_tests.h"
+
+#include "mbed-client/m2mblockmessage.h"
+#include "mbed-client/m2mdevice.h"
+#include "mbed-client/m2mfirmware.h"
+#include "mbed-client/m2minterfacefactory.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mserver.h"
+#include "mbed-client/m2msecurity.h"
+#include "source/include/m2mreporthandler.h"
+
+#include "mbed.h"
+#include "mbed_stats.h"
+
+#include <assert.h>
+
+void heap_stats()
+{
+#ifdef MBED_HEAP_STATS_ENABLED
+    mbed_stats_heap_t stats;
+    mbed_stats_heap_get(&stats);
+    printf("**** current_size: %" PRIu32 "\n", stats.current_size);
+    printf("**** max_size    : %" PRIu32 "\n", stats.max_size);
+#endif // MBED_HEAP_STATS_ENABLED
+}
+
+void m2mobject_test_set(M2MObjectList& object_list)
+{
+#ifdef MBED_HEAP_STATS_ENABLED
+    printf("*************************************\n");
+
+    mbed_stats_heap_t stats;
+    mbed_stats_heap_get(&stats);
+
+    uint32_t initial = stats.current_size;
+
+    const int object_count = 1;
+    const int object_id_range_start = 90;
+    const int object_id_range_end = object_id_range_start + object_count;
+
+    const int object_instance_count = 5;
+    const int resource_count = 5;
+
+    int total_object_count = 0;
+    int total_object_instance_count = 0;
+    int total_resource_count = 0;
+
+    for (int object_id = object_id_range_start; object_id < object_id_range_end; object_id++) {
+
+        char buff[64];
+        sprintf(buff, "%d", object_id);
+        M2MObject *obj = M2MInterfaceFactory::create_object(buff);
+
+        for (int object_instance_id = 0; object_instance_id < object_instance_count; object_instance_id++) {
+
+            M2MObjectInstance* obj_inst = obj->create_object_instance(object_instance_id);
+
+            assert(obj_inst != NULL);
+            total_object_instance_count++;
+            for (int resource_id = 0; resource_id < resource_count; resource_id++) {
+                String res_name;
+                String res_type;
+
+                res_name.append_int(resource_id);
+                res_type.append_int(resource_id);
+
+                M2MResource* resource = obj_inst->create_dynamic_resource(res_name, res_type,
+                                                                        M2MResourceInstance::INTEGER, true);
+
+                assert(resource != NULL);
+
+                resource->set_operation(M2MBase::GET_ALLOWED);
+                resource->set_value(7);
+
+                total_resource_count++;
+            }
+        }
+
+        object_list.push_back(obj);
+        total_object_count++;
+    }
+
+    printf("objects       : %d\n", total_object_count);
+    printf("obj instances : %d\n", total_object_instance_count);
+    printf("resources     : %d\n", total_resource_count);
+
+    mbed_stats_heap_get(&stats);
+    printf("heap used     : %" PRIu32 "\n", stats.current_size - initial);
+
+    printf("*************************************\n");
+#endif // MBED_HEAP_STATS_ENABLED
+}
+
+// Note: the mbed-os needs to be compiled with MBED_HEAP_STATS_ENABLED to get
+// functional heap stats, or the mbed_stats_heap_get() will return just zeroes.
+void m2mobject_stats()
+{
+#ifdef MBED_HEAP_STATS_ENABLED
+    printf("\n*** M2M object sizes in bytes ***\n");
+    printf("M2MBase: %" PRIu32 "\n", sizeof(M2MBase));
+    printf("M2MObject: %" PRIu32 "\n", sizeof(M2MObject));
+    printf("M2MObjectInstance: %" PRIu32 "\n", sizeof(M2MObjectInstance));
+    printf("M2MResource: %" PRIu32 "\n", sizeof(M2MResource));
+    printf("M2MResourceInstance: %" PRIu32 "\n", sizeof(M2MResourceInstance));
+    printf("M2MDevice: %" PRIu32 "\n", sizeof(M2MDevice));
+    printf("M2MFirmware: %" PRIu32 "\n", sizeof(M2MFirmware));
+    printf("M2MServer: %" PRIu32 "\n", sizeof(M2MServer));
+    printf("M2MSecurity: %" PRIu32 "\n", sizeof(M2MSecurity));
+    printf("M2MBlockMessage: %" PRIu32 "\n", sizeof(M2MBlockMessage));
+    printf("M2MReportHandler: %" PRIu32 "\n", sizeof(M2MReportHandler));
+    printf("*************************************\n\n");
+
+    mbed_stats_heap_t stats;
+    mbed_stats_heap_get(&stats);
+
+    printf("*** M2M heap stats in bytes***\n");
+    uint32_t initial = stats.current_size;
+
+    // M2MDevice
+    M2MDevice *device_object = M2MInterfaceFactory::create_device();
+    assert(device_object);
+    mbed_stats_heap_get(&stats);
+    printf("M2MDevice heap size: %" PRIu32 "\n", stats.current_size - initial);
+    M2MDevice::delete_instance();
+    mbed_stats_heap_get(&stats);
+    if (initial != stats.current_size) {
+        printf("M2MDevice leaked: %" PRIu32 "bytes\n", stats.current_size - initial);
+    }
+
+    // M2MServer
+    initial = stats.current_size;
+    M2MServer *server = M2MInterfaceFactory::create_server();
+    mbed_stats_heap_get(&stats);
+    printf("M2MServer heap size: %" PRIu32 "\n", stats.current_size - initial);
+    delete server;
+    mbed_stats_heap_get(&stats);
+    if (initial != stats.current_size) {
+        printf("M2MServer leaked: %" PRIu32 "bytes\n", stats.current_size - initial);
+    }
+
+    // M2MSecurity
+    initial = stats.current_size;
+    M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer);
+    mbed_stats_heap_get(&stats);
+    printf("M2MSecurity heap size: %" PRIu32 "\n", stats.current_size - initial);
+    M2MSecurity::delete_instance();
+    mbed_stats_heap_get(&stats);
+    if (initial != stats.current_size) {
+        printf("M2MSecurity leaked: %" PRIu32 "bytes\n", stats.current_size - initial);
+    }
+
+    // M2MFirmware
+    initial = stats.current_size;
+    M2MFirmware *firmware = M2MInterfaceFactory::create_firmware();
+    assert(firmware);
+    mbed_stats_heap_get(&stats);
+    printf("M2MFirmware heap size: %" PRIu32 "\n", stats.current_size - initial);
+    M2MFirmware::delete_instance();
+    mbed_stats_heap_get(&stats);
+    if (initial != stats.current_size) {
+        printf("M2MFirmware leaked: %" PRIu32 "bytes\n", stats.current_size - initial);
+    }
+
+    // Basic object creation
+    initial = stats.current_size;
+    uint32_t before_object = initial;
+    M2MObject *obj = M2MInterfaceFactory::create_object("1");
+    mbed_stats_heap_get(&stats);
+    printf("M2MObject heap size: %" PRIu32 "\n", stats.current_size - initial);
+    initial = stats.current_size;
+
+    M2MObjectInstance* obj_inst = obj->create_object_instance();
+    mbed_stats_heap_get(&stats);
+    printf("M2MObjectInstance heap size: %" PRIu32 "\n", stats.current_size - initial);
+
+    initial = stats.current_size;
+    M2MResource* res = obj_inst->create_dynamic_resource("1", "1", M2MResourceInstance::STRING, false);
+    assert(res);
+    mbed_stats_heap_get(&stats);
+    printf("M2MResource heap size: %" PRIu32 "\n", stats.current_size - initial);
+
+    delete obj;
+    mbed_stats_heap_get(&stats);
+    if (before_object != stats.current_size) {
+        printf("Resource leaked: %" PRIu32 "bytes\n", stats.current_size - before_object);
+    }
+    printf("*************************************\n\n");
+#endif // MBED_HEAP_STATS_ENABLED
+}
+#endif // TARGET_LIKE_MBED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/memory_tests.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,33 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef __MEMORY_TESTS_H__
+#define __MEMORY_TESTS_H__
+
+#include "mbed-client/m2minterface.h"
+#include "mbed.h"
+
+// A function for creating a batch of resources for memory consumption purposes.
+void m2mobject_test_set(M2MObjectList& object_list);
+
+// Print into serial the m2m object sizes and heap allocation sizes.
+void m2mobject_stats();
+
+void heap_stats();
+
+#endif // !__MEMORY_TESTS_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/pal_plat_rot_insecure.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,52 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "pal_plat_rtos.h"
+
+#define PAL_DEVICE_KEY_SIZE_IN_BYTES 16
+
+//THIS CODE IS FOR TESTING PURPOSES ONLY. DO NOT USE IN PRODUCTION ENVIRONMENTS. REPLACE WITH A PROPER IMPLEMENTATION BEFORE USE
+palStatus_t  __attribute__((weak)) pal_plat_osGetRoT128Bit(uint8_t *keyBuf, size_t keyLenBytes)
+{
+#if defined (__CC_ARM)          /* ARM compiler. */
+    #warning("PAL_INSECURE- You are using insecure Root Of Trust implementation, DO NOT USE IN PRODUCTION ENVIRONMENTS. REPLACE WITH A PROPER IMPLEMENTATION BEFORE USE")
+#else
+    #pragma message ("You are using insecure Root Of Trust implementation, DO NOT USE IN PRODUCTION ENVIRONMENTS. REPLACE WITH A PROPER IMPLEMENTATION BEFORE USE")
+#endif
+    static bool runOnce = true;
+    if (runOnce) {
+
+        PAL_LOG(WARN, "You are using insecure Root Of Trust implementation");
+        runOnce = false;
+    }
+
+    if (keyLenBytes < PAL_DEVICE_KEY_SIZE_IN_BYTES)	{
+        return PAL_ERR_BUFFER_TOO_SMALL;
+    }
+
+    if (NULL == keyBuf) {
+        return PAL_ERR_NULL_POINTER;
+    }
+
+    for (int i=0; i < PAL_DEVICE_KEY_SIZE_IN_BYTES; i++) {
+        keyBuf[i] = i;
+    }
+
+    return PAL_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/resource.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,94 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "mbed-cloud-client/MbedCloudClient.h"
+#include "m2mresource.h"
+#include "mbed-client/m2minterface.h"
+#include <stdio.h>
+#include <string.h>
+#include "mbed.h"
+
+static void notification_delivery_status_cb_thunk(const M2MBase& base,
+                                                  const NoticationDeliveryStatus status,
+                                                  void *client_args) {
+    ((Callback<void(const M2MBase& base, const NoticationDeliveryStatus status)>*)client_args)->call(base, status);
+}
+
+M2MResource* add_resource(M2MObjectList *list, uint16_t object_id, uint16_t instance_id,
+                          uint16_t resource_id, const char *resource_type, M2MResourceInstance::ResourceType data_type,
+                          M2MBase::Operation allowed, const char *value, bool observable, Callback<void(const char*)> *put_cb,
+                          Callback<void(void*)> *post_cb,
+                          Callback<void(const M2MBase&, const NoticationDeliveryStatus)> *notification_status_cb)
+{
+    M2MObject *object = NULL;
+    M2MObjectInstance* object_instance = NULL;
+    M2MResource* resource = NULL;
+    char name[6];
+
+    //check if object already exists.
+    if (!list->empty()) {
+        M2MObjectList::const_iterator it;
+        it = list->begin();
+        for ( ; it != list->end(); it++ ) {
+            if ((*it)->name_id() == object_id) {
+                object = (*it);
+                break;
+            }
+        }
+    }
+    //Create new object if needed.
+    if (!object) {
+        snprintf(name, 6, "%d", object_id);
+        object = M2MInterfaceFactory::create_object(name);
+        list->push_back(object);
+    } else {
+        //check if instance already exists.
+        object_instance = object->object_instance(instance_id);
+    }
+    //Create new instance if needed.
+    if (!object_instance) {
+        object_instance = object->create_object_instance(instance_id);
+    }
+    //create the recource.
+    snprintf(name, 6, "%d", resource_id);
+    resource = object_instance->create_dynamic_resource(name, resource_type, data_type, observable);
+    //Set value if available.
+    if (strcmp(value, "") != 0) {
+        resource->set_value((const unsigned char*)value, strlen(value));
+    }
+    //Set allowed operations for accessing the resource.
+    resource->set_operation(allowed);
+    if (observable) {
+        resource->set_notification_delivery_status_cb(notification_delivery_status_cb_thunk, notification_status_cb);
+    }
+
+    if (put_cb) {
+        resource->set_value_updated_function(
+            FP1<void, const char*>(put_cb,
+                (void (Callback<void(const char*)>::*)(const char*))
+                    &Callback<void(const char*)>::call));
+    }
+
+    if (post_cb) {
+        resource->set_execute_function(FP1<void, void*>(post_cb,
+            (void (Callback<void(void*)>::*)(void*))
+                &Callback<void(void*)>::call));
+    }
+
+    return resource;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/resource.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,65 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef RESOURCE_H
+#define RESOURCE_H
+
+
+/**
+ * \brief Helper function for creating different kind of resources.
+ *        The path of the resource will be "object_id/instance_id/resource_id"
+ *        For example if object_id = 1, instance_id = 2, resource_id = 3
+ *        the path would be 1/2/3
+ *
+ * \param list Pointer to the object list,
+ *             contains objects to be registered to the server.
+ * \param object_id Name of the object in integer format.
+ * \param instance_id Name of the instance in integer format.
+ * \param resource_id Name of the resource in integer format.
+ * \param resource_type Resource type name.
+ * \param data_type Data type of the resource value.
+ * \param allowed Methods allowed for accessing this resource.
+ * \param value Resource value as a null terminated string.
+ *              May be set as NULL.
+ * \param observable Resource set observable if true.
+ * \param cb Function pointer to either:
+ *           value_updated_callback2 if allowed & GET_PUT_ALLOWED
+ *           OR
+ *           execute_callback_2 in if allowed & POST_ALLOWED.
+ *           In other cases this parameter is ignored.
+ *
+ *        NOTE: This function is not designed to support setting both
+ *              GET_PUT_ALLOWED and POST_ALLOWED for parameter allowed
+ *              at the same time.
+ * \param notification_status_cb Function pointer to notification_delivery_status_cb
+ *          if resource is set to be observable.
+ */
+M2MResource* add_resource(M2MObjectList *list,
+                          uint16_t object_id,
+                          uint16_t instance_id,
+                          uint16_t resource_id,
+                          const char *resource_type,
+                          M2MResourceInstance::ResourceType data_type,
+                          M2MBase::Operation allowed,
+                          const char *value,
+                          bool observable,
+                          Callback<void(const char*)> *put_cb,
+                          Callback<void(void*)> *post_cb,
+                          Callback<void(const M2MBase&, const NoticationDeliveryStatus)> *notification_status_cb);
+
+#endif //RESOURCE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/simple-mbed-cloud-client.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,397 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include "simple-mbed-cloud-client.h"
+#include "mbed-cloud-client/MbedCloudClient.h"
+#include "m2mdevice.h"
+#include "m2mresource.h"
+#include "mbed-client/m2minterface.h"
+#include "key_config_manager.h"
+#include "resource.h"
+#include "mbed-client/m2mvector.h"
+#include "mbed_cloud_client_resource.h"
+#include "factory_configurator_client.h"
+#include "update_client_hub.h"
+
+#ifdef MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#include MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#endif
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+#include "update_ui_example.h"
+#endif
+
+#ifdef MBED_HEAP_STATS_ENABLED
+#include "memory_tests.h"
+#endif
+
+#ifndef DEFAULT_FIRMWARE_PATH
+#define DEFAULT_FIRMWARE_PATH       "/sd/firmware"
+#endif
+
+BlockDevice *arm_uc_blockdevice;
+
+SimpleMbedCloudClient::SimpleMbedCloudClient(NetworkInterface *net, BlockDevice *bd, FileSystem *fs) :
+    _registered(false),
+    _register_called(false),
+    _register_and_connect_called(false),
+    _registered_cb(NULL),
+    _unregistered_cb(NULL),
+    _net(net),
+    _bd(bd),
+    _fs(fs)
+{
+    arm_uc_blockdevice = bd;
+}
+
+SimpleMbedCloudClient::~SimpleMbedCloudClient() {
+    for (unsigned int i = 0; _resources.size(); i++) {
+        delete _resources[i];
+    }
+}
+
+int SimpleMbedCloudClient::init() {
+    // Requires DAPLink 245+ (https://github.com/ARMmbed/DAPLink/pull/364)
+    // Older versions: workaround to prevent possible deletion of credentials:
+    wait(1);
+
+    extern const uint8_t arm_uc_vendor_id[];
+    extern const uint16_t arm_uc_vendor_id_size;
+    extern const uint8_t arm_uc_class_id[];
+    extern const uint16_t arm_uc_class_id_size;
+
+    ARM_UC_SetVendorId(arm_uc_vendor_id, arm_uc_vendor_id_size);
+    ARM_UC_SetClassId(arm_uc_class_id, arm_uc_class_id_size);
+
+    // Initialize the FCC
+    fcc_status_e fcc_status = fcc_init();
+    if(fcc_status != FCC_STATUS_SUCCESS) {
+        printf("[Simple Cloud Client] Factory Client Configuration failed with status %d. \n", fcc_status);
+        return 1;
+    }
+
+    fcc_status = fcc_verify_device_configured_4mbed_cloud();
+
+    if (fcc_status == FCC_STATUS_KCM_STORAGE_ERROR) {
+        int mount_result = mount_storage();
+        if (mount_result != 0) {
+            printf("[Simple Cloud Client] Failed to mount file system with status %d. \n", mount_result);
+#if !defined(MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR) || MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR == 0
+            return 1;
+#endif
+        } else {
+            // Retry with mounted filesystem.
+            fcc_status = fcc_verify_device_configured_4mbed_cloud();
+        }
+    }
+
+    // This is designed to simplify user-experience by auto-formatting the
+    // primary storage if no valid certificates exist.
+    // This should never be used for any kind of production devices.
+#if defined(MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR) && MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR == 1
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        if (reformat_storage() != 0) {
+            return 1;
+        }
+
+        reset_storage();
+    }
+#else
+    if (fcc_status != FCC_STATUS_SUCCESS) {
+        printf("[Simple Cloud Client] Device not configured for mbed Cloud - try re-formatting your storage device or set MBED_CONF_APP_FORMAT_STORAGE_LAYER_ON_ERROR to 1\n");
+        return 1;
+    }
+#endif
+
+    // Resets storage to an empty state.
+    // Use this function when you want to clear storage from all the factory-tool generated data and user data.
+    // After this operation device must be injected again by using factory tool or developer certificate.
+#ifdef RESET_STORAGE
+    reset_storage();
+#endif
+
+    // Deletes existing firmware images from storage.
+    // This deletes any existing firmware images during application startup.
+    // This compilation flag is currently implemented only for mbed OS.
+#ifdef RESET_FIRMWARE
+    palStatus_t status = PAL_SUCCESS;
+    status = pal_fsRmFiles(DEFAULT_FIRMWARE_PATH);
+    if(status == PAL_SUCCESS) {
+        printf("[Simple Cloud Client] Firmware storage erased.\n");
+    } else if (status == PAL_ERR_FS_NO_PATH) {
+        printf("[Simple Cloud Client] Firmware path not found/does not exist.\n");
+    } else {
+        printf("[Simple Cloud Client] Firmware storage erasing failed with %" PRId32, status);
+        return 1;
+    }
+#endif
+
+#if MBED_CONF_APP_DEVELOPER_MODE == 1
+    printf("[Simple Cloud Client] Starting developer flow\n");
+    fcc_status = fcc_developer_flow();
+    if (fcc_status == FCC_STATUS_KCM_FILE_EXIST_ERROR) {
+        printf("[Simple Cloud Client] Developer credentials already exist\n");
+    } else if (fcc_status != FCC_STATUS_SUCCESS) {
+        printf("[Simple Cloud Client] Failed to load developer credentials - is the storage device active and accessible?\n");
+        return 1;
+    }
+#endif
+
+    return 0;
+}
+
+bool SimpleMbedCloudClient::call_register() {
+    // need to unregister first before calling this function again
+    if (_register_called) return false;
+
+    _cloud_client.on_registered(this, &SimpleMbedCloudClient::client_registered);
+    _cloud_client.on_unregistered(this, &SimpleMbedCloudClient::client_unregistered);
+    _cloud_client.on_error(this, &SimpleMbedCloudClient::error);
+
+    bool setup = _cloud_client.setup(_net);
+    _register_called = true;
+    if (!setup) {
+        printf("[Simple Cloud Client] Client setup failed\n");
+        return false;
+    }
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+    /* Set callback functions for authorizing updates and monitoring progress.
+       Code is implemented in update_ui_example.cpp
+       Both callbacks are completely optional. If no authorization callback
+       is set, the update process will procede immediately in each step.
+    */
+    update_ui_set_cloud_client(&_cloud_client);
+    _cloud_client.set_update_authorize_handler(update_authorize);
+    _cloud_client.set_update_progress_handler(update_progress);
+#endif
+    return true;
+}
+
+void SimpleMbedCloudClient::close() {
+    _cloud_client.close();
+}
+
+void SimpleMbedCloudClient::register_update() {
+    _cloud_client.register_update();
+}
+
+void SimpleMbedCloudClient::client_registered() {
+    _registered = true;
+    static const ConnectorClientEndpointInfo* endpoint = NULL;
+    if (endpoint == NULL) {
+        endpoint = _cloud_client.endpoint_info();
+        if (endpoint && _registered_cb) {
+            _registered_cb(endpoint);
+        }
+    }
+#ifdef MBED_HEAP_STATS_ENABLED
+    heap_stats();
+#endif
+}
+
+void SimpleMbedCloudClient::client_unregistered() {
+    _registered = false;
+    _register_called = false;
+
+    if (_unregistered_cb) {
+        _unregistered_cb();
+    }
+
+#ifdef MBED_HEAP_STATS_ENABLED
+    heap_stats();
+#endif
+}
+
+void SimpleMbedCloudClient::error(int error_code) {
+    const char *error;
+    switch(error_code) {
+        case MbedCloudClient::ConnectErrorNone:
+            error = "MbedCloudClient::ConnectErrorNone";
+            break;
+        case MbedCloudClient::ConnectAlreadyExists:
+            error = "MbedCloudClient::ConnectAlreadyExists";
+            break;
+        case MbedCloudClient::ConnectBootstrapFailed:
+            error = "MbedCloudClient::ConnectBootstrapFailed";
+            break;
+        case MbedCloudClient::ConnectInvalidParameters:
+            error = "MbedCloudClient::ConnectInvalidParameters";
+            break;
+        case MbedCloudClient::ConnectNotRegistered:
+            error = "MbedCloudClient::ConnectNotRegistered";
+            break;
+        case MbedCloudClient::ConnectTimeout:
+            error = "MbedCloudClient::ConnectTimeout";
+            break;
+        case MbedCloudClient::ConnectNetworkError:
+            error = "MbedCloudClient::ConnectNetworkError";
+            break;
+        case MbedCloudClient::ConnectResponseParseFailed:
+            error = "MbedCloudClient::ConnectResponseParseFailed";
+            break;
+        case MbedCloudClient::ConnectUnknownError:
+            error = "MbedCloudClient::ConnectUnknownError";
+            break;
+        case MbedCloudClient::ConnectMemoryConnectFail:
+            error = "MbedCloudClient::ConnectMemoryConnectFail";
+            break;
+        case MbedCloudClient::ConnectNotAllowed:
+            error = "MbedCloudClient::ConnectNotAllowed";
+            break;
+        case MbedCloudClient::ConnectSecureConnectionFailed:
+            error = "MbedCloudClient::ConnectSecureConnectionFailed";
+            break;
+        case MbedCloudClient::ConnectDnsResolvingFailed:
+            error = "MbedCloudClient::ConnectDnsResolvingFailed";
+            break;
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+        case MbedCloudClient::UpdateWarningCertificateNotFound:
+            error = "MbedCloudClient::UpdateWarningCertificateNotFound";
+            break;
+        case MbedCloudClient::UpdateWarningIdentityNotFound:
+            error = "MbedCloudClient::UpdateWarningIdentityNotFound";
+            break;
+        case MbedCloudClient::UpdateWarningCertificateInvalid:
+            error = "MbedCloudClient::UpdateWarningCertificateInvalid";
+            break;
+        case MbedCloudClient::UpdateWarningSignatureInvalid:
+            error = "MbedCloudClient::UpdateWarningSignatureInvalid";
+            break;
+        case MbedCloudClient::UpdateWarningVendorMismatch:
+            error = "MbedCloudClient::UpdateWarningVendorMismatch";
+            break;
+        case MbedCloudClient::UpdateWarningClassMismatch:
+            error = "MbedCloudClient::UpdateWarningClassMismatch";
+            break;
+        case MbedCloudClient::UpdateWarningDeviceMismatch:
+            error = "MbedCloudClient::UpdateWarningDeviceMismatch";
+            break;
+        case MbedCloudClient::UpdateWarningURINotFound:
+            error = "MbedCloudClient::UpdateWarningURINotFound";
+            break;
+        case MbedCloudClient::UpdateWarningRollbackProtection:
+            error = "MbedCloudClient::UpdateWarningRollbackProtection";
+            break;
+        case MbedCloudClient::UpdateWarningUnknown:
+            error = "MbedCloudClient::UpdateWarningUnknown";
+            break;
+        case MbedCloudClient::UpdateErrorWriteToStorage:
+            error = "MbedCloudClient::UpdateErrorWriteToStorage";
+            break;
+        case MbedCloudClient::UpdateErrorInvalidHash:
+            error = "MbedCloudClient::UpdateErrorInvalidHash";
+            break;
+#endif
+        default:
+            error = "UNKNOWN";
+    }
+
+    // @todo: move this into user space
+    printf("\n[Simple Cloud Client] Error occurred : %s\n", error);
+    printf("[Simple Cloud Client] Error code : %d\n", error_code);
+    printf("[Simple Cloud Client] Error details : %s\n",_cloud_client.error_description());
+}
+
+bool SimpleMbedCloudClient::is_client_registered() {
+    return _registered;
+}
+
+bool SimpleMbedCloudClient::is_register_called() {
+    return _register_called;
+}
+
+bool SimpleMbedCloudClient::register_and_connect() {
+    if (_register_and_connect_called) return false;
+
+    mcc_resource_def resourceDef;
+
+    for (int i = 0; i < _resources.size(); i++) {
+        _resources[i]->get_data(&resourceDef);
+        M2MResource *res = add_resource(&_obj_list, resourceDef.object_id, resourceDef.instance_id,
+                    resourceDef.resource_id, resourceDef.name.c_str(), M2MResourceInstance::STRING,
+                    (M2MBase::Operation)resourceDef.method_mask, resourceDef.value.c_str(), resourceDef.observable,
+                    resourceDef.put_callback, resourceDef.post_callback, resourceDef.notification_callback);
+        _resources[i]->set_m2m_resource(res);
+    }
+    _cloud_client.add_objects(_obj_list);
+
+    _register_and_connect_called = true;
+
+    // Start registering to the cloud.
+    bool retval = call_register();
+
+    // Print memory statistics if the MBED_HEAP_STATS_ENABLED is defined.
+    #ifdef MBED_HEAP_STATS_ENABLED
+        printf("[Simple Cloud Client] Register being called\r\n");
+        heap_stats();
+    #endif
+
+    return retval;
+}
+
+void SimpleMbedCloudClient::on_registered(Callback<void(const ConnectorClientEndpointInfo*)> cb) {
+    _registered_cb = cb;
+}
+
+void SimpleMbedCloudClient::on_unregistered(Callback<void()> cb) {
+    _unregistered_cb = cb;
+}
+
+MbedCloudClient& SimpleMbedCloudClient::get_cloud_client() {
+    return _cloud_client;
+}
+
+MbedCloudClientResource* SimpleMbedCloudClient::create_resource(const char *path, const char *name) {
+    MbedCloudClientResource *resource = new MbedCloudClientResource(this, path, name);
+    _resources.push_back(resource);
+    return resource;
+}
+
+int SimpleMbedCloudClient::reformat_storage()
+{
+    int reformat_result = -1;
+    printf("[Simple Cloud Client] Autoformatting the storage.\n");
+    if (_bd) {
+        reformat_result = _fs->reformat(_bd);
+        if (reformat_result != 0) {
+            printf("[Simple Cloud Client] Autoformatting failed with error %d\n", reformat_result);
+        }
+    }
+    return reformat_result;
+}
+
+void SimpleMbedCloudClient::reset_storage()
+{
+    printf("[Simple Cloud Client] Reset storage to an empty state.\n");
+    fcc_status_e delete_status = fcc_storage_delete();
+    if (delete_status != FCC_STATUS_SUCCESS) {
+        printf("[Simple Cloud Client] Failed to delete storage - %d\n", delete_status);
+    }
+}
+
+int SimpleMbedCloudClient::mount_storage()
+{
+    int mount_result = -1;
+    printf("[Simple Cloud Client] Initializing storage.\n");
+    if (_bd) {
+        mount_result = _fs->mount(_bd);
+    }
+    return mount_result;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/simple-mbed-cloud-client.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,73 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef SIMPLEMBEDCLOUDCLIENT_H
+#define SIMPLEMBEDCLOUDCLIENT_H
+#include <stdio.h>
+#include "mbed-cloud-client/MbedCloudClient.h"
+#include "m2mdevice.h"
+#include "m2mresource.h"
+#include "mbed-client/m2minterface.h"
+#include "mbed-client/m2mvector.h"
+#include "mbed_cloud_client_resource.h"
+#include "mbed.h"
+#include "NetworkInterface.h"
+
+class MbedCloudClientResource;
+
+class SimpleMbedCloudClient {
+
+public:
+
+    SimpleMbedCloudClient(NetworkInterface *net, BlockDevice *bd, FileSystem *fs);
+    ~SimpleMbedCloudClient();
+
+    int init();
+    bool call_register();
+    void close();
+    void register_update();
+    void client_registered();
+    void client_unregistered();
+    void error(int error_code);
+    bool is_client_registered();
+    bool is_register_called();
+    bool register_and_connect();
+    MbedCloudClient& get_cloud_client();
+    MbedCloudClientResource* create_resource(const char *path, const char *name);
+    void on_registered(Callback<void(const ConnectorClientEndpointInfo*)> cb);
+    void on_unregistered(Callback<void()> cb);
+
+private:
+    int reformat_storage();
+    void reset_storage();
+    int mount_storage();
+
+    M2MObjectList                                       _obj_list;
+    MbedCloudClient                                     _cloud_client;
+    bool                                                _registered;
+    bool                                                _register_called;
+    bool                                                _register_and_connect_called;
+    Vector<MbedCloudClientResource*>                    _resources;
+    Callback<void(const ConnectorClientEndpointInfo*)>  _registered_cb;
+    Callback<void()>                                    _unregistered_cb;
+    NetworkInterface *                                  _net;
+    BlockDevice *                                       _bd;
+    FileSystem *                                        _fs;
+};
+
+#endif // SIMPLEMBEDCLOUDCLIENT_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/sotp_fs_config_MbedOS.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,31 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef PAL_HEADER_SOTP_FS
+#define PAL_HEADER_SOTP_FS
+
+#define PAL_USE_HW_ROT 0
+#define PAL_USE_HW_RTC 0
+#define PAL_USE_HW_TRNG 1
+#define PAL_SIMULATOR_FLASH_OVER_FILE_SYSTEM 0
+#define PAL_USE_INTERNAL_FLASH 1
+#define PAL_USE_SECURE_TIME 1
+
+#include "mbedOS_default.h"
+
+#endif //PAL_HEADER_SOTP_FS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/update_ui_example.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,140 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#include "update_ui_example.h"
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+
+#include <stdio.h>
+#include <stdint.h>
+
+static MbedCloudClient* _client;
+
+#ifdef ARM_UPDATE_CLIENT_VERSION_VALUE
+#if ARM_UPDATE_CLIENT_VERSION_VALUE > 101000
+void update_ui_set_cloud_client(MbedCloudClient* client)
+{
+    _client = client;
+}
+
+void update_authorize(int32_t request)
+{
+    switch (request)
+    {
+        /* Cloud Client wishes to download new firmware. This can have a negative
+           impact on the performance of the rest of the system.
+
+           The user application is supposed to pause performance sensitive tasks
+           before authorizing the download.
+
+           Note: the authorization call can be postponed and called later.
+           This doesn't affect the performance of the Cloud Client.
+        */
+        case MbedCloudClient::UpdateRequestDownload:
+            printf("Firmware download requested\r\n");
+            printf("Authorization granted\r\n");
+            _client->update_authorize(MbedCloudClient::UpdateRequestDownload);
+            break;
+
+        /* Cloud Client wishes to reboot and apply the new firmware.
+
+           The user application is supposed to save all current work before rebooting.
+
+           Note: the authorization call can be postponed and called later.
+           This doesn't affect the performance of the Cloud Client.
+        */
+        case MbedCloudClient::UpdateRequestInstall:
+            printf("Firmware install requested\r\n");
+            printf("Authorization granted\r\n");
+            _client->update_authorize(MbedCloudClient::UpdateRequestInstall);
+            break;
+
+        default:
+            printf("Error - unknown request\r\n");
+            break;
+    }
+}
+#endif
+#endif
+
+void update_progress(uint32_t progress, uint32_t total)
+{
+    uint8_t percent = progress * 100 / total;
+
+/* only show progress bar if debug trace is disabled */
+#if (!defined(MBED_CONF_MBED_TRACE_ENABLE) || MBED_CONF_MBED_TRACE_ENABLE == 0) \
+    && !ARM_UC_ALL_TRACE_ENABLE \
+    && !ARM_UC_HUB_TRACE_ENABLE
+
+    printf("\rDownloading: [");
+    for (uint8_t index = 0; index < 50; index++)
+    {
+        if (index < percent / 2)
+        {
+            printf("+");
+        }
+        else if (index == percent / 2)
+        {
+            static uint8_t old_max = 0;
+            static uint8_t counter = 0;
+
+            if (index == old_max)
+            {
+                counter++;
+            }
+            else
+            {
+                old_max = index;
+                counter = 0;
+            }
+
+            switch (counter % 4)
+            {
+                case 0:
+                    printf("/");
+                    break;
+                case 1:
+                    printf("-");
+                    break;
+                case 2:
+                    printf("\\");
+                    break;
+                case 3:
+                default:
+                    printf("|");
+                    break;
+            }
+        }
+        else
+        {
+            printf(" ");
+        }
+    }
+    printf("] %d %%", percent);
+    fflush(stdout);
+#else
+    printf("Downloading: %d %%\r\n", percent);
+#endif
+
+    if (progress == total)
+    {
+        printf("\r\nDownload completed\r\n");
+    }
+}
+
+#endif // MBED_CLOUD_CLIENT_SUPPORT_UPDATE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple-mbed-cloud-client/update_ui_example.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,52 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifndef UPDATE_UI_EXAMPLE_H
+#define UPDATE_UI_EXAMPLE_H
+
+#include "mbed-cloud-client/MbedCloudClient.h"
+
+#ifdef MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+
+#ifdef ARM_UPDATE_CLIENT_VERSION_VALUE
+#if ARM_UPDATE_CLIENT_VERSION_VALUE > 101000
+/**
+ * @brief Function for authorizing firmware downloads and reboots.
+ * @param request The request under consideration.
+ */
+void update_authorize(int32_t request);
+#endif
+#endif
+
+/**
+ * @brief Callback function for reporting the firmware download progress.
+ * @param progress Received bytes.
+ * @param total Total amount of bytes to be received.
+ */
+void update_progress(uint32_t progress, uint32_t total);
+
+/**
+ * @brief Set the cloud client instance for the update UI to use
+ * @param[in] client pointer to the cloud client instance
+ */
+void update_ui_set_cloud_client(MbedCloudClient* client);
+
+
+#endif // MBED_CLOUD_CLIENT_SUPPORT_UPDATE
+
+#endif // UPDATE_UI_EXAMPLE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/update_default_resources.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,41 @@
+// ----------------------------------------------------------------------------
+// Copyright 2016-2018 ARM Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// 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.
+// ----------------------------------------------------------------------------
+
+#ifdef MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#include MBED_CLOUD_CLIENT_USER_CONFIG_FILE
+#endif
+
+#include <stdint.h>
+
+#ifdef MBED_CLOUD_DEV_UPDATE_ID
+const uint8_t arm_uc_vendor_id[16] = { "dev_manufacturer" };
+const uint16_t arm_uc_vendor_id_size = sizeof(arm_uc_vendor_id);
+
+const uint8_t arm_uc_class_id[16]  = { "dev_model_number" };
+const uint16_t arm_uc_class_id_size = sizeof(arm_uc_class_id);
+#endif
+
+#ifdef MBED_CLOUD_DEV_UPDATE_CERT
+const uint8_t arm_uc_default_fingerprint[32] = { 0 };
+const uint16_t arm_uc_default_fingerprint_size =
+    sizeof(arm_uc_default_fingerprint);
+
+const uint8_t arm_uc_default_certificate[1] = { 0 };
+const uint16_t arm_uc_default_certificate_size =
+    sizeof(arm_uc_default_certificate);
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362.lib	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/wifi-ism43362/#49d0f834dc420c98631fc33777aace9a31d8d584
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/FETCH_HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+49d0f834dc420c98631fc33777aace9a31d8d584		branch 'master' of https://github.com/ARMmbed/wifi-ism43362
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+ref: refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/ORIG_HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+49d0f834dc420c98631fc33777aace9a31d8d584
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/config	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,11 @@
+[core]
+	repositoryformatversion = 0
+	filemode = true
+	bare = false
+	logallrefupdates = true
+[remote "origin"]
+	fetch = +refs/heads/*:refs/remotes/origin/*
+	url = https://github.com/ARMmbed/wifi-ism43362/
+[branch "master"]
+	remote = origin
+	merge = refs/heads/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/description	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+Unnamed repository; edit this file 'description' to name the repository.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/hooks/applypatch-msg.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.  The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+	exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/hooks/commit-msg.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message.  The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit.  The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+	 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
+	echo >&2 Duplicate Signed-off-by lines.
+	exit 1
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/hooks/post-update.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/hooks/pre-applypatch.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+	exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/hooks/pre-commit.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments.  The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+	against=HEAD
+else
+	# Initial commit: diff against an empty tree object
+	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+	# Note that the use of brackets around a tr range is ok here, (it's
+	# even required, for portability to Solaris 10's /usr/bin/tr), since
+	# the square bracket bytes happen to fall in the designated range.
+	test $(git diff --cached --name-only --diff-filter=A -z $against |
+	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+	echo "Error: Attempt to add a non-ascii file name."
+	echo
+	echo "This can cause problems if you want to work"
+	echo "with people on other platforms."
+	echo
+	echo "To be portable it is advisable to rename the file ..."
+	echo
+	echo "If you know what you are doing you can disable this"
+	echo "check using:"
+	echo
+	echo "  git config hooks.allownonascii true"
+	echo
+	exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/hooks/pre-rebase.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+	topic="refs/heads/$2"
+else
+	topic=`git symbolic-ref HEAD` ||
+	exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+	;;
+*)
+	exit 0 ;# we do not interrupt others.
+	;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master.  Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+	echo >&2 "No such branch $topic"
+	exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+	echo >&2 "$topic is fully merged to master; better remove it."
+	exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next?  If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master           ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+	not_in_topic=`git rev-list "^$topic" master`
+	if test -z "$not_in_topic"
+	then
+		echo >&2 "$topic is already up-to-date with master"
+		exit 1 ;# we could allow it, but there is no point.
+	else
+		exit 0
+	fi
+else
+	not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+	/usr/bin/perl -e '
+		my $topic = $ARGV[0];
+		my $msg = "* $topic has commits already merged to public branch:\n";
+		my (%not_in_next) = map {
+			/^([0-9a-f]+) /;
+			($1 => 1);
+		} split(/\n/, $ARGV[1]);
+		for my $elem (map {
+				/^([0-9a-f]+) (.*)$/;
+				[$1 => $2];
+			} split(/\n/, $ARGV[2])) {
+			if (!exists $not_in_next{$elem->[0]}) {
+				if ($msg) {
+					print STDERR $msg;
+					undef $msg;
+				}
+				print STDERR " $elem->[1]\n";
+			}
+		}
+	' "$topic" "$not_in_next" "$not_in_master"
+	exit 1
+fi
+
+<<\DOC_END
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+   merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+   it is deleted.  If you need to build on top of it to correct
+   earlier mistakes, a new topic branch is created by forking at
+   the tip of the "master".  This is not strictly necessary, but
+   it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+   branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next".  Young
+    topic branches can have stupid mistakes you would rather
+    clean up before publishing, and things that have not been
+    merged into other branches can be easily rebased without
+    affecting other people.  But once it is published, you would
+    not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+    Then you can delete it.  More importantly, you should not
+    build on top of it -- other people may already want to
+    change things related to the topic as patches against your
+    "master", so if you need further changes, it is better to
+    fork the topic (perhaps with the same name) afresh from the
+    tip of "master".
+
+Let's look at this example:
+
+		   o---o---o---o---o---o---o---o---o---o "next"
+		  /       /           /           /
+		 /   a---a---b A     /           /
+		/   /               /           /
+	       /   /   c---c---c---c B         /
+	      /   /   /             \         /
+	     /   /   /   b---b C     \       /
+	    /   /   /   /             \     /
+    ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished.  It has been fully merged up to "master" and "next",
+   and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+	git rev-list ^master ^topic next
+	git rev-list ^master        next
+
+	if these match, topic has not merged in next at all.
+
+To compute (2):
+
+	git rev-list master..topic
+
+	if this is empty, it is fully merged to "master".
+
+DOC_END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/hooks/prepare-commit-msg.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source.  The hook's purpose is to edit the commit
+# message file.  If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples.  The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output.  It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited.  This is rarely a good idea.
+
+case "$2,$3" in
+  merge,)
+    /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+#   /usr/bin/perl -i.bak -pe '
+#      print "\n" . `git diff --cached --name-status -r`
+#	 if /^#/ && $first++ == 0' "$1" ;;
+
+  *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/hooks/update.sample	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+#   This boolean sets whether unannotated tags will be allowed into the
+#   repository.  By default they won't be.
+# hooks.allowdeletetag
+#   This boolean sets whether deleting tags will be allowed in the
+#   repository.  By default they won't be.
+# hooks.allowmodifytag
+#   This boolean sets whether a tag may be modified after creation. By default
+#   it won't be.
+# hooks.allowdeletebranch
+#   This boolean sets whether deleting branches will be allowed in the
+#   repository.  By default they won't be.
+# hooks.denycreatebranch
+#   This boolean sets whether remotely creating branches will be denied
+#   in the repository.  By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+	echo "Don't run this script from the command line." >&2
+	echo " (if you want, you could supply GIT_DIR then run" >&2
+	echo "  $0 <ref> <oldrev> <newrev>)" >&2
+	exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+	echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+	exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+	echo "*** Project description file hasn't been set" >&2
+	exit 1
+	;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+	newrev_type=delete
+else
+	newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+	refs/tags/*,commit)
+		# un-annotated tag
+		short_refname=${refname##refs/tags/}
+		if [ "$allowunannotated" != "true" ]; then
+			echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+			echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,delete)
+		# delete tag
+		if [ "$allowdeletetag" != "true" ]; then
+			echo "*** Deleting a tag is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/tags/*,tag)
+		# annotated tag
+		if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+		then
+			echo "*** Tag '$refname' already exists." >&2
+			echo "*** Modifying a tag is not allowed in this repository." >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,commit)
+		# branch
+		if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+			echo "*** Creating a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/heads/*,delete)
+		# delete branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	refs/remotes/*,commit)
+		# tracking branch
+		;;
+	refs/remotes/*,delete)
+		# delete tracking branch
+		if [ "$allowdeletebranch" != "true" ]; then
+			echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+			exit 1
+		fi
+		;;
+	*)
+		# Anything else (is there anything else?)
+		echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+		exit 1
+		;;
+esac
+
+# --- Finished
+exit 0
Binary file wifi-ism43362/.git/index has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/info/exclude	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,25 @@
+.hg
+.git
+.svn
+.CVS
+.cvs
+*.orig
+.build
+.export
+.msub
+.meta
+.ctags*
+*.uvproj
+*.uvopt
+*.project
+*.cproject
+*.launch
+*.ewp
+*.eww
+Makefile
+Debug
+*.htm
+*.settings
+mbed_settings.py
+*.py[cod]
+# subrepo ignores
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/logs/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,5 @@
+0000000000000000000000000000000000000000 49d0f834dc420c98631fc33777aace9a31d8d584 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378401 +0000	clone: from https://github.com/ARMmbed/wifi-ism43362/
+49d0f834dc420c98631fc33777aace9a31d8d584 9ee7fb19814e46b6e90b1eaec26ef36b523ec024 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378401 +0000	checkout: moving from master to 9ee7fb19814e46b6e90b1eaec26ef36b523ec024
+9ee7fb19814e46b6e90b1eaec26ef36b523ec024 49d0f834dc420c98631fc33777aace9a31d8d584 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378699 +0000	checkout: moving from 9ee7fb19814e46b6e90b1eaec26ef36b523ec024 to master
+49d0f834dc420c98631fc33777aace9a31d8d584 9ee7fb19814e46b6e90b1eaec26ef36b523ec024 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539379271 +0000	checkout: moving from master to 9ee7fb19814e46b6e90b1eaec26ef36b523ec024
+9ee7fb19814e46b6e90b1eaec26ef36b523ec024 49d0f834dc420c98631fc33777aace9a31d8d584 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539379283 +0000	checkout: moving from 9ee7fb19814e46b6e90b1eaec26ef36b523ec024 to master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/logs/refs/heads/master	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 49d0f834dc420c98631fc33777aace9a31d8d584 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378401 +0000	clone: from https://github.com/ARMmbed/wifi-ism43362/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/logs/refs/remotes/origin/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+0000000000000000000000000000000000000000 49d0f834dc420c98631fc33777aace9a31d8d584 www-data <www-data@developer-sjc-indigo-compiler.local.mbed.org> 1539378401 +0000	clone: from https://github.com/ARMmbed/wifi-ism43362/
Binary file wifi-ism43362/.git/objects/pack/pack-8bf1447bb4ae1bb2894fa2c84da739c66001d7d1.idx has changed
Binary file wifi-ism43362/.git/objects/pack/pack-8bf1447bb4ae1bb2894fa2c84da739c66001d7d1.pack has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/packed-refs	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,3 @@
+# pack-refs with: peeled 
+49d0f834dc420c98631fc33777aace9a31d8d584 refs/remotes/origin/master
+43817d8fe90469c57d5b21f7a8a1acb66d890392 refs/tags/v1.0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/refs/heads/master	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+49d0f834dc420c98631fc33777aace9a31d8d584
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.git/refs/remotes/origin/HEAD	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,1 @@
+ref: refs/remotes/origin/master
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/.meta	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<root>
+  <node _type="integer" _key="update">0</node>
+</root>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/ATParser.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,454 @@
+/* Copyright (c) 2015 ARM Limited
+ *
+ * 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.
+ *
+ * @section DESCRIPTION
+ *
+ * Parser for the AT command syntax
+ *
+ */
+
+#include "ATParser.h"
+#include "mbed_debug.h"
+
+#ifdef LF
+#undef LF
+#define LF  10
+#else
+#define LF  10
+#endif
+
+#ifdef CR
+#undef CR
+#define CR  13
+#else
+#define CR  13
+#endif
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+// activate / de-activate debug
+#define dbg_on           0
+#define AT_DATA_PRINT    0
+#define AT_COMMAND_PRINT 0
+#define AT_HEXA_DATA     0
+
+ATParser::ATParser(BufferedSpi &serial_spi, const char *delimiter, int buffer_size, int timeout) :
+    _serial_spi(&serial_spi),
+    _buffer_size(buffer_size), _in_prev(0), _oobs(NULL)
+{
+    _buffer = new char[buffer_size];
+    setTimeout(timeout);
+    setDelimiter(delimiter);
+}
+
+
+// getc/putc handling with timeouts
+int ATParser::putc(char c)
+{
+    return _serial_spi->putc(c);
+}
+
+int ATParser::getc()
+{
+    return _serial_spi->getc();
+}
+
+void ATParser::flush()
+{
+    _bufferMutex.lock();
+    while (_serial_spi->readable()) {
+        _serial_spi->getc();
+    }
+    _bufferMutex.unlock();
+}
+
+// read/write handling with timeouts
+int ATParser::write(const char *data, int size_of_data, int size_in_buff)
+{
+    int i = 0;
+    _bufferMutex.lock();
+    debug_if(dbg_on, "ATParser write: %d BYTES\r\n", size_of_data);
+    debug_if(AT_DATA_PRINT, "ATParser write: (ASCII) ", size_of_data);
+    for (; i < size_of_data; i++) {
+        debug_if(AT_DATA_PRINT, "%c", data[i]);
+        if (putc(data[i]) < 0) {
+            debug_if(AT_DATA_PRINT, "\r\n");
+            _bufferMutex.unlock();
+            return -1;
+        }
+    }
+    debug_if(AT_DATA_PRINT, "\r\n");
+
+    _serial_spi->buffsend(size_of_data + size_in_buff);
+    _bufferMutex.unlock();
+
+    return (size_of_data + size_in_buff);
+}
+
+int ATParser::read(char *data)
+{
+    int readsize;
+    int i = 0;
+
+    _bufferMutex.lock();
+
+    //this->flush();
+    if (!_serial_spi->readable()) {
+        readsize = _serial_spi->read();
+    } else {
+        debug_if(dbg_on, "Pending data when reading from WIFI\r\n");
+        return -1;
+    }
+
+    debug_if(dbg_on, "ATParser read: %d data avail in SPI\r\n", readsize);
+
+    if (readsize < 0) {
+        _bufferMutex.unlock();
+        return -1;
+    }
+
+    for (i = 0 ; i < readsize; i++) {
+        int c = getc();
+        if (c < 0) {
+            _bufferMutex.unlock();
+            return -1;
+        }
+        data[i] = c;
+    }
+
+#if AT_HEXA_DATA
+    debug_if(AT_DATA_PRINT, "ATParser read: (HEXA) ");
+    for (i = 0; i < readsize; i++) {
+        debug_if(AT_DATA_PRINT, "%2X ", data[i]);
+        if ((i + 1) % 20 == 0) {
+            debug_if(AT_DATA_PRINT, "\r\n");
+        }
+    }
+    debug_if(AT_DATA_PRINT, "\r\n");
+#endif
+    debug_if(AT_DATA_PRINT, "ATParser read: (ASCII) ");
+    for (i = 0; i < readsize; i++) {
+        debug_if(AT_DATA_PRINT, "%c", data[i]);
+    }
+    debug_if(AT_DATA_PRINT, "\r\n");
+
+    _bufferMutex.unlock();
+
+    return (readsize);
+}
+
+// printf/scanf handling
+int ATParser::vprintf(const char *format, va_list args)
+{
+    _bufferMutex.lock();
+    if (vsprintf(_buffer, format, args) < 0) {
+        _bufferMutex.unlock();
+        return false;
+    }
+
+    int i = 0;
+    for (; _buffer[i]; i++) {
+        if (putc(_buffer[i]) < 0) {
+            _bufferMutex.unlock();
+            return -1;
+        }
+    }
+    _bufferMutex.unlock();
+
+    return i;
+}
+
+int ATParser::vscanf(const char *format, va_list args)
+{
+    // Since format is const, we need to copy it into our buffer to
+    // add the line's null terminator and clobber value-matches with asterisks.
+    //
+    // We just use the beginning of the buffer to avoid unnecessary allocations.
+    int i = 0;
+    int offset = 0;
+
+    _bufferMutex.lock();
+
+    while (format[i]) {
+        if (format[i] == '%' && format[i + 1] != '%' && format[i + 1] != '*') {
+            _buffer[offset++] = '%';
+            _buffer[offset++] = '*';
+            i++;
+        } else {
+            _buffer[offset++] = format[i++];
+        }
+    }
+
+    // Scanf has very poor support for catching errors
+    // fortunately, we can abuse the %n specifier to determine
+    // if the entire string was matched.
+    _buffer[offset++] = '%';
+    _buffer[offset++] = 'n';
+    _buffer[offset++] = 0;
+
+    // To workaround scanf's lack of error reporting, we actually
+    // make two passes. One checks the validity with the modified
+    // format string that only stores the matched characters (%n).
+    // The other reads in the actual matched values.
+    //
+    // We keep trying the match until we succeed or some other error
+    // derails us.
+    int j = 0;
+
+    while (true) {
+        // Ran out of space
+        if (j + 1 >= _buffer_size - offset) {
+            _bufferMutex.unlock();
+            return false;
+        }
+        // Recieve next character
+        int c = getc();
+        if (c < 0) {
+            _bufferMutex.unlock();
+            return -1;
+        }
+        _buffer[offset + j++] = c;
+        _buffer[offset + j] = 0;
+
+        // Check for match
+        int count = -1;
+        sscanf(_buffer + offset, _buffer, &count);
+
+        // We only succeed if all characters in the response are matched
+        if (count == j) {
+            // Store the found results
+            vsscanf(_buffer + offset, format, args);
+            _bufferMutex.unlock();
+            return j;
+        }
+    }
+}
+
+
+// Command parsing with line handling
+bool ATParser::vsend(const char *command, va_list args)
+{
+    int i = 0, j = 0;
+    _bufferMutex.lock();
+    // Create and send command
+    if (vsprintf(_buffer, command, args) < 0) {
+        _bufferMutex.unlock();
+        return false;
+    }
+    /* get buffer length */
+    for (i = 0; _buffer[i]; i++) {
+    }
+
+    for (j = 0; _delimiter[j]; j++) {
+        _buffer[i + j] = _delimiter[j];
+    }
+    _buffer[i + j] = 0; // only to get a clean debug log
+
+    bool ret = !(_serial_spi->buffwrite(_buffer, i + j) < 0);
+
+    debug_if(AT_COMMAND_PRINT, "AT> %s\n", _buffer);
+    _bufferMutex.unlock();
+    return ret;
+}
+
+bool ATParser::vrecv(const char *response, va_list args)
+{
+    _bufferMutex.lock();
+
+    if (!_serial_spi->readable()) {
+        // debug_if(dbg_on, "NO DATA, read again\r\n");
+        if (_serial_spi->read() < 0) {
+            return false;
+        }
+    }
+    // else {
+    //      debug_if(dbg_on, "Pending data\r\n");
+    // }
+
+restart:
+    _aborted = false;
+    // Iterate through each line in the expected response
+    while (response[0]) {
+        // Since response is const, we need to copy it into our buffer to
+        // add the line's null terminator and clobber value-matches with asterisks.
+        //
+        // We just use the beginning of the buffer to avoid unnecessary allocations.
+        int i = 0;
+        int offset = 0;
+        bool whole_line_wanted = false;
+
+        while (response[i]) {
+            if (response[i] == '%' && response[i + 1] != '%' && response[i + 1] != '*') {
+                _buffer[offset++] = '%';
+                _buffer[offset++] = '*';
+                i++;
+            } else {
+                _buffer[offset++] = response[i++];
+                // Find linebreaks, taking care not to be fooled if they're in a %[^\n] conversion specification
+                if (response[i - 1] == '\n' && !(i >= 3 && response[i - 3] == '[' && response[i - 2] == '^')) {
+                    whole_line_wanted = true;
+                    break;
+                }
+            }
+        }
+
+        // Scanf has very poor support for catching errors
+        // fortunately, we can abuse the %n specifier to determine
+        // if the entire string was matched.
+        _buffer[offset++] = '%';
+        _buffer[offset++] = 'n';
+        _buffer[offset++] = 0;
+
+        // debug_if(dbg_on, "ATParser vrecv: AT? ====%s====\n", _buffer);
+        // To workaround scanf's lack of error reporting, we actually
+        // make two passes. One checks the validity with the modified
+        // format string that only stores the matched characters (%n).
+        // The other reads in the actual matched values.
+        //
+        // We keep trying the match until we succeed or some other error
+        // derails us.
+        int j = 0;
+
+        while (true) {
+            // Recieve next character
+            int c = getc();
+            if (c < 0) {
+                debug_if(dbg_on, "AT(Timeout)\n");
+                _bufferMutex.unlock();
+                return false;
+            }
+
+            // debug_if(AT_DATA_PRINT, "%2X ", c);
+
+            _buffer[offset + j++] = c;
+            _buffer[offset + j] = 0;
+
+            // Check for oob data
+            for (struct oob *oob = _oobs; oob; oob = oob->next) {
+                if ((unsigned)j == oob->len && memcmp(
+                            oob->prefix, _buffer + offset, oob->len) == 0) {
+                    debug_if(dbg_on, "AT! %s\n", oob->prefix);
+                    oob->cb();
+
+                    if (_aborted) {
+                        debug_if(dbg_on, "AT(Aborted)\n");
+                        _bufferMutex.unlock();
+                        return false;
+                    }
+                    // oob may have corrupted non-reentrant buffer,
+                    // so we need to set it up again
+                    goto restart;
+                }
+            }
+
+            // Check for match
+            int count = -1;
+            if (whole_line_wanted && c != '\n') {
+                // Don't attempt scanning until we get delimiter if they included it in format
+                // This allows recv("Foo: %s\n") to work, and not match with just the first character of a string
+                // (scanf does not itself match whitespace in its format string, so \n is not significant to it)
+            } else {
+                sscanf(_buffer + offset, _buffer, &count);
+            }
+
+            // We only succeed if all characters in the response are matched
+            if (count == j) {
+                debug_if(AT_COMMAND_PRINT, "AT= ====%s====\n", _buffer + offset);
+                // Reuse the front end of the buffer
+                memcpy(_buffer, response, i);
+                _buffer[i] = 0;
+
+                // Store the found results
+                vsscanf(_buffer + offset, _buffer, args);
+
+                // Jump to next line and continue parsing
+                response += i;
+                break;
+            }
+
+            // Clear the buffer when we hit a newline or ran out of space
+            // running out of space usually means we ran into binary data
+            if ((c == '\n')) {
+                // debug_if(dbg_on, "New line AT<<< %s", _buffer+offset);
+                j = 0;
+            }
+            if ((j + 1 >= (_buffer_size - offset))) {
+
+                debug_if(dbg_on, "Out of space AT<<< %s, j=%d", _buffer + offset, j);
+                j = 0;
+            }
+        }
+    }
+
+    _bufferMutex.unlock();
+
+    return true;
+}
+
+
+// Mapping to vararg functions
+int ATParser::printf(const char *format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    int res = vprintf(format, args);
+    va_end(args);
+    return res;
+}
+
+int ATParser::scanf(const char *format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    int res = vscanf(format, args);
+    va_end(args);
+    return res;
+}
+
+bool ATParser::send(const char *command, ...)
+{
+    va_list args;
+    va_start(args, command);
+    bool res = vsend(command, args);
+    va_end(args);
+    return res;
+}
+
+bool ATParser::recv(const char *response, ...)
+{
+    va_list args;
+    va_start(args, response);
+    bool res = vrecv(response, args);
+    va_end(args);
+    return res;
+}
+
+
+// oob registration
+void ATParser::oob(const char *prefix, Callback<void()> cb)
+{
+    struct oob *oob = new struct oob;
+    oob->len = strlen(prefix);
+    oob->prefix = prefix;
+    oob->cb = cb;
+    oob->next = _oobs;
+    _oobs = oob;
+}
+
+void ATParser::abort()
+{
+    _aborted = true;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/ATParser.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,246 @@
+/* Copyright (c) 2015 ARM Limited
+ *
+ * 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.
+ *
+ * @section DESCRIPTION
+ *
+ * Parser for the AT command syntax
+ *
+ */
+#ifndef AT_PARSER_H
+#define AT_PARSER_H
+
+#include "mbed.h"
+#include <cstdarg>
+#include <vector>
+#include "BufferedSpi.h"
+#include "Callback.h"
+
+#define DEFAULT_SPI_TIMEOUT 60000 /* 1 minute */
+
+/**
+* Parser class for parsing AT commands
+*
+* Here are some examples:
+* @code
+* ATParser at = ATParser(serial, "\r\n");
+* int value;
+* char buffer[100];
+*
+* at.send("AT") && at.recv("OK");
+* at.send("AT+CWMODE=%d", 3) && at.recv("OK");
+* at.send("AT+CWMODE?") && at.recv("+CWMODE:%d\r\nOK", &value);
+* at.recv("+IPD,%d:", &value);
+* at.read(buffer, value);
+* at.recv("OK");
+* @endcode
+*/
+class ATParser {
+private:
+    // Serial information
+    BufferedSpi *_serial_spi;
+    int _buffer_size;
+    char *_buffer;
+    Mutex _bufferMutex;
+
+    // Parsing information
+    const char *_delimiter;
+    int _delim_size;
+    char _in_prev;
+    volatile bool _aborted;
+
+    struct oob {
+        unsigned len;
+        const char *prefix;
+        mbed::Callback<void()> cb;
+        oob *next;
+    };
+    oob *_oobs;
+
+public:
+    /**
+    * Constructor
+    *
+    * @param serial spi interface to use for AT commands
+    * @param buffer_size size of internal buffer for transaction
+    * @param timeout timeout of the connection
+    * @param delimiter string of characters to use as line delimiters
+    */
+    ATParser(BufferedSpi &serial_spi, const char *delimiter = "\r\n", int buffer_size = 1440, int timeout = DEFAULT_SPI_TIMEOUT);
+
+    /**
+    * Destructor
+    */
+    ~ATParser()
+    {
+        while (_oobs) {
+            struct oob *oob = _oobs;
+            _oobs = oob->next;
+            delete oob;
+        }
+        delete[] _buffer;
+    }
+
+    /**
+    * Allows timeout to be changed between commands
+    *
+    * @param timeout timeout of the connection
+    */
+    void setTimeout(int timeout)
+    {
+        _serial_spi->setTimeout(timeout);
+    }
+
+    /**
+    * Sets string of characters to use as line delimiters
+    *
+    * @param delimiter string of characters to use as line delimiters
+    */
+    void setDelimiter(const char *delimiter)
+    {
+        _delimiter = delimiter;
+        _delim_size = strlen(delimiter);
+    }
+
+    /**
+     * Sends an AT command
+     *
+     * Sends a formatted command using printf style formatting
+     * @see printf
+     *
+     * @param command printf-like format string of command to send which
+     *                is appended with a newline
+     * @param ... all printf-like arguments to insert into command
+     * @return true only if command is successfully sent
+     */
+    bool send(const char *command, ...);
+
+    bool vsend(const char *command, va_list args);
+
+    /**
+     * Receive an AT response
+     *
+     * Receives a formatted response using scanf style formatting
+     * @see scanf
+     *
+     * Responses are parsed line at a time.
+     * Any received data that does not match the response is ignored until
+     * a timeout occurs.
+     *
+     * @param response scanf-like format string of response to expect
+     * @param ... all scanf-like arguments to extract from response
+     * @return true only if response is successfully matched
+     */
+    bool recv(const char *response, ...);
+    bool vrecv(const char *response, va_list args);
+
+
+    /**
+     * Write a single byte to the underlying stream
+     *
+     * @param c The byte to write
+     * @return The byte that was written or -1 during a timeout
+     */
+    int putc(char c);
+
+    /**
+     * Get a single byte from the underlying stream
+     *
+     * @return The byte that was read or -1 during a timeout
+     */
+    int getc();
+
+    /**
+     * Write an array of bytes to the underlying stream
+     * assuming the header of the command is already in _txbuffer
+     *
+     * @param data the array of bytes to write
+     * @param size_of_data number of bytes in data array
+     * @param size_in_buff number of bytes already in the internal buff
+     * @return number of bytes written or -1 on failure
+     */
+    int write(const char *data, int size_of_data, int size_in_buff);
+
+    /**
+     * Read an array of bytes from the underlying stream
+     *
+     * @param data the destination for the read bytes
+     * @param size number of bytes to read
+     * @return number of bytes read or -1 on failure
+     */
+    int read(char *data);
+
+    /**
+     * Direct printf to underlying stream
+     * @see printf
+     *
+     * @param format format string to pass to printf
+     * @param ... arguments to printf
+     * @return number of bytes written or -1 on failure
+     */
+    int printf(const char *format, ...);
+    int vprintf(const char *format, va_list args);
+
+    /**
+    * Direct scanf on underlying stream
+    * @see ::scanf
+    *
+    * @param format format string to pass to scanf
+    * @param ... arguments to scanf
+    * @return number of bytes read or -1 on failure
+    */
+    int scanf(const char *format, ...);
+
+    int vscanf(const char *format, va_list args);
+
+    /**
+     * Attach a callback for out-of-band data
+     *
+     * @param prefix string on when to initiate callback
+     * @param func callback to call when string is read
+     * @note out-of-band data is only processed during a scanf call
+     */
+    void oob(const char *prefix, mbed::Callback<void()> func);
+
+    /**
+     * Flushes the underlying stream
+     */
+    void flush();
+
+    /**
+     * Abort current recv
+     *
+     * Can be called from oob handler to interrupt the current
+     * recv operation.
+     */
+    void abort();
+
+    /**
+    * Process out-of-band data
+    *
+    * Process out-of-band data in the receive buffer. This function
+    * returns immediately if there is no data to process.
+    *
+    * @return true if oob data processed, false otherwise
+    */
+    bool process_oob(void);
+    /**
+    * Get buffer_size
+    */
+    int get_size(void)
+    {
+        return _buffer_size;
+    }
+
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/BufferedSpi/Buffer/MyBuffer.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,86 @@
+
+/**
+ * @file    Buffer.cpp
+ * @brief   Software Buffer - Templated Ring Buffer for most data types
+ * @author  sam grove
+ * @version 1.0
+ * @see
+ *
+ * Copyright (c) 2013
+ *
+ * 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.
+ */
+
+#include "MyBuffer.h"
+
+template <class T>
+MyBuffer<T>::MyBuffer(uint32_t size)
+{
+    _buf = new T [size];
+    _size = size;
+    clear();
+
+    return;
+}
+
+template <class T>
+MyBuffer<T>::~MyBuffer()
+{
+    delete [] _buf;
+
+    return;
+}
+
+template <class T>
+uint32_t MyBuffer<T>::getSize()
+{
+    return this->_size;
+}
+
+template <class T>
+uint32_t MyBuffer<T>::getNbAvailable()
+{
+    if (_wloc >= _rloc) {
+        return (_wloc - _rloc);
+    } else {
+        return (_size - _rloc + _wloc);
+    }
+}
+
+template <class T>
+void MyBuffer<T>::clear(void)
+{
+    _wloc = 0;
+    _rloc = 0;
+    memset(_buf, 0, _size);
+
+    return;
+}
+
+template <class T>
+uint32_t MyBuffer<T>::peek(char c)
+{
+    return 1;
+}
+
+// make the linker aware of some possible types
+template class MyBuffer<uint8_t>;
+template class MyBuffer<int8_t>;
+template class MyBuffer<uint16_t>;
+template class MyBuffer<int16_t>;
+template class MyBuffer<uint32_t>;
+template class MyBuffer<int32_t>;
+template class MyBuffer<uint64_t>;
+template class MyBuffer<int64_t>;
+template class MyBuffer<char>;
+template class MyBuffer<wchar_t>;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/BufferedSpi/Buffer/MyBuffer.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,164 @@
+
+/**
+ * @file    Buffer.h
+ * @brief   Software Buffer - Templated Ring Buffer for most data types
+ * @author  sam grove
+ * @version 1.0
+ * @see
+ *
+ * Copyright (c) 2013
+ *
+ * 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.
+ */
+
+#ifndef MYBUFFER_H
+#define MYBUFFER_H
+
+#include <stdint.h>
+#include <string.h>
+
+/** A templated software ring buffer
+ *
+ * Example:
+ * @code
+ *  #include "mbed.h"
+ *  #include "MyBuffer.h"
+ *
+ *  MyBuffer <char> buf;
+ *
+ *  int main()
+ *  {
+ *      buf = 'a';
+ *      buf.put('b');
+ *      char *head = buf.head();
+ *      puts(head);
+ *
+ *      char whats_in_there[2] = {0};
+ *      int pos = 0;
+ *
+ *      while(buf.available())
+ *      {
+ *          whats_in_there[pos++] = buf;
+ *      }
+ *      printf("%c %c\n", whats_in_there[0], whats_in_there[1]);
+ *      buf.clear();
+ *      error("done\n\n\n");
+ *  }
+ * @endcode
+ */
+
+template <typename T>
+class MyBuffer {
+private:
+    T   *_buf;
+    volatile uint32_t   _wloc;
+    volatile uint32_t   _rloc;
+    uint32_t            _size;
+
+public:
+    /** Create a Buffer and allocate memory for it
+     *  @param size The size of the buffer
+     */
+    MyBuffer(uint32_t size = 0x100);
+
+    /** Get the size of the ring buffer
+     * @return the size of the ring buffer
+     */
+    uint32_t getSize();
+    uint32_t getNbAvailable();
+
+    /** Destry a Buffer and release it's allocated memory
+     */
+    ~MyBuffer();
+
+    /** Add a data element into the buffer
+     *  @param data Something to add to the buffer
+     */
+    void put(T data);
+
+    /** Remove a data element from the buffer
+     *  @return Pull the oldest element from the buffer
+     */
+    T get(void);
+
+    /** Get the address to the head of the buffer
+     *  @return The address of element 0 in the buffer
+     */
+    T *head(void);
+
+    /** Reset the buffer to 0. Useful if using head() to parse packeted data
+     */
+    void clear(void);
+
+    /** Determine if anything is readable in the buffer
+     *  @return 1 if something can be read, 0 otherwise
+     */
+    uint32_t available(void);
+
+    /** Overloaded operator for writing to the buffer
+     *  @param data Something to put in the buffer
+     *  @return
+     */
+    MyBuffer &operator= (T data)
+    {
+        put(data);
+        return *this;
+    }
+
+    /** Overloaded operator for reading from the buffer
+     *  @return Pull the oldest element from the buffer
+     */
+    operator int(void)
+    {
+        return get();
+    }
+
+    uint32_t peek(char c);
+
+};
+
+template <class T>
+inline void MyBuffer<T>::put(T data)
+{
+    _buf[_wloc++] = data;
+    _wloc %= (_size - 1);
+
+    return;
+}
+
+template <class T>
+inline T MyBuffer<T>::get(void)
+{
+    T data_pos = _buf[_rloc++];
+    _rloc %= (_size - 1);
+
+    return data_pos;
+}
+
+template <class T>
+inline T *MyBuffer<T>::head(void)
+{
+    T *data_pos = &_buf[0];
+
+    return data_pos;
+}
+
+template <class T>
+inline uint32_t MyBuffer<T>::available(void)
+{
+    return (_wloc == _rloc) ? 0 : 1;
+    //return 1;
+}
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedPrint.c	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014-2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * 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.
+ */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "mbed_error.h"
+
+size_t BufferedSpiThunk(void *buf_serial, const void *s, size_t length);
+
+int BufferedPrintfC(void *stream, int size, const char* format, va_list arg)
+{
+    int r;
+    char buffer[512];
+    if (size >= 512) {
+        return -1;
+    }
+    memset(buffer, 0, size);
+    r = vsprintf(buffer, format, arg);
+    // this may not hit the heap but should alert the user anyways
+    if(r > (int32_t) size) {
+        error("%s %d buffer overwrite (max_buf_size: %d exceeded: %d)!\r\n", __FILE__, __LINE__, size, r);
+        return 0;
+    }
+    if ( r > 0 ) {
+        BufferedSpiThunk(stream, buffer, r);
+    }
+    return r;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedSpi.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,333 @@
+/**
+ * @file    BufferedSpi.cpp
+ * @brief   Software Buffer - Extends mbed SPI functionallity
+ * @author  Armelle Duboc
+ * @version 1.0
+ * @see
+ *
+ * Copyright (c) STMicroelectronics 2017
+ *
+ * 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.
+ */
+
+#include "BufferedSpi.h"
+#include <stdarg.h>
+#include "mbed_debug.h"
+#include "mbed_error.h"
+
+// change to true to add few SPI debug lines
+#define local_debug false
+
+extern "C" int BufferedPrintfC(void *stream, int size, const char *format, va_list arg);
+
+void BufferedSpi::DatareadyRising(void)
+{
+    if (_cmddata_rdy_rising_event == 1) {
+        _cmddata_rdy_rising_event = 0;
+    }
+}
+
+int BufferedSpi::wait_cmddata_rdy_high(void)
+{
+    Timer timer;
+    timer.start();
+
+    /* wait for dataready = 1 */
+    while (dataready.read() == 0) {
+        if (timer.read_ms() > _timeout) {
+            debug_if(local_debug, "ERROR: SPI write timeout\r\n");
+            return -1;
+        }
+    }
+
+    _cmddata_rdy_rising_event = 1;
+
+    return 0;
+}
+
+int BufferedSpi::wait_cmddata_rdy_rising_event(void)
+{
+    Timer timer;
+    timer.start();
+
+    while (_cmddata_rdy_rising_event == 1) {
+        if (timer.read_ms() > _timeout) {
+            _cmddata_rdy_rising_event = 0;
+            if (dataready.read() == 1) {
+                debug_if(local_debug, "ERROR: We missed rising event !! (timemout=%d)\r\n", _timeout);
+            }
+            debug_if(local_debug, "ERROR: SPI read timeout\r\n");
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+BufferedSpi::BufferedSpi(PinName mosi, PinName miso, PinName sclk, PinName _nss, PinName _datareadypin,
+                         uint32_t buf_size, uint32_t tx_multiple, const char *name)
+    : SPI(mosi, miso, sclk, NC), nss(_nss),  _txbuf((uint32_t)(tx_multiple * buf_size)), _rxbuf(buf_size), dataready(_datareadypin)
+{
+    this->_buf_size = buf_size;
+    this->_tx_multiple = tx_multiple;
+    this->_sigio_event = 0;
+
+    _datareadyInt = new InterruptIn(_datareadypin);
+    _datareadyInt->rise(callback(this, &BufferedSpi::DatareadyRising));
+
+    _cmddata_rdy_rising_event = 1;
+
+    return;
+}
+
+BufferedSpi::~BufferedSpi(void)
+{
+
+    return;
+}
+
+void BufferedSpi::frequency(int hz)
+{
+    SPI::frequency(hz);
+}
+
+void BufferedSpi::format(int bits, int mode)
+{
+    SPI::format(bits, mode);
+}
+
+void BufferedSpi::disable_nss()
+{
+    nss = 1;
+    wait_us(15);
+}
+
+void BufferedSpi::enable_nss()
+{
+    nss = 0;
+    wait_us(15);
+}
+
+int BufferedSpi::readable(void)
+{
+    return _rxbuf.available();  // note: look if things are in the buffer
+}
+
+int BufferedSpi::writeable(void)
+{
+    return 1;   // buffer allows overwriting by design, always true
+}
+
+int BufferedSpi::getc(void)
+{
+    if (_rxbuf.available()) {
+        return _rxbuf;
+    } else {
+        return -1;
+    }
+}
+
+int BufferedSpi::putc(int c)
+{
+    _txbuf = (char)c;
+
+    return c;
+}
+
+void BufferedSpi::flush_txbuf(void)
+{
+    _txbuf.clear();
+}
+
+int BufferedSpi::puts(const char *s)
+{
+    if (s != NULL) {
+        const char *ptr = s;
+
+        while (*(ptr) != 0) {
+            _txbuf = *(ptr++);
+        }
+        _txbuf = '\n';  // done per puts definition
+        BufferedSpi::txIrq();                // only write to hardware in one place
+        return (ptr - s) + 1;
+    }
+    return 0;
+}
+
+extern "C" size_t BufferedSpiThunk(void *buf_spi, const void *s, size_t length)
+{
+    BufferedSpi *buffered_spi = (BufferedSpi *)buf_spi;
+    return buffered_spi->buffwrite(s, length);
+}
+
+int BufferedSpi::printf(const char *format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int r = BufferedPrintfC((void *)this, this->_buf_size, format, arg);
+    va_end(arg);
+    return r;
+}
+
+ssize_t BufferedSpi::buffwrite(const void *s, size_t length)
+{
+    /* flush buffer from previous message */
+    this->flush_txbuf();
+
+    if (wait_cmddata_rdy_high() < 0) {
+        debug_if(local_debug, "BufferedSpi::buffwrite timeout (%d)\r\n", _timeout);
+        return -1;
+    }
+
+    this->enable_nss();
+
+    if (s != NULL && length > 0) {
+        /* 1st fill _txbuf */
+        const char *ptr = (const char *)s;
+        const char *end = ptr + length;
+
+        while (ptr != end) {
+            _txbuf = *(ptr++);
+        }
+        if (length & 1) { /* padding to send the last char */
+            _txbuf = '\n';
+            length++;
+        }
+
+        /* 2nd write in SPI */
+        BufferedSpi::txIrq();                // only write to hardware in one place
+
+        this->disable_nss();
+        return ptr - (const char *)s;
+    }
+    this->disable_nss();
+
+    return 0;
+}
+
+ssize_t BufferedSpi::buffsend(size_t length)
+{
+    /* wait for dataready = 1 */
+    if (wait_cmddata_rdy_high() < 0) {
+        debug_if(local_debug, "BufferedSpi::buffsend timeout (%d)\r\n", _timeout);
+        return -1;
+    }
+
+    this->enable_nss();
+
+    /* _txbuffer is already filled with data to send */
+    /* check if _txbuffer needs padding to send the last char */
+    if (length & 1) {
+        _txbuf = '\n';
+        length++;
+    }
+    BufferedSpi::txIrq();                // only write to hardware in one place
+
+    this->disable_nss();
+
+    return length;
+}
+
+ssize_t BufferedSpi::read()
+{
+    return this->read(0);
+}
+
+ssize_t BufferedSpi::read(uint32_t max)
+{
+    uint32_t len = 0;
+    uint8_t FirstRemoved = 1;
+    int tmp;
+
+    disable_nss();
+
+    /* wait for data ready is up */
+    if (wait_cmddata_rdy_rising_event() != 0) {
+        debug_if(local_debug, "BufferedSpi::read timeout (%d)\r\n", _timeout);
+        return -1;
+    }
+
+    enable_nss();
+    while (dataready.read() == 1 && (len < (_buf_size - 2))) {
+        tmp = SPI::write(0xAA);  // dummy write to receive 2 bytes
+
+        if (!((len == 0) && (tmp == 0x0A0D) && (FirstRemoved))) {
+            /* do not take into account the 2 firts \r \n char in the buffer */
+            if ((max == 0) || (len < max)) {
+                _rxbuf = (char)(tmp & 0x00FF);
+                _rxbuf = (char)((tmp >> 8) & 0xFF);
+                len += 2;
+            }
+        } else {
+            FirstRemoved = 0;
+        }
+    }
+    disable_nss();
+
+    if (len >= _buf_size) {
+        debug_if(local_debug, "firmware ERROR ES_WIFI_ERROR_STUFFING_FOREVER\r\n");
+        return -1;
+    }
+
+    debug_if(local_debug, "SPI READ %d BYTES\r\n", len);
+
+    return len;
+}
+
+void BufferedSpi::txIrq(void)
+{
+    /* write everything available in the _txbuffer */
+    int value = 0;
+    int dbg_cnt = 0;
+    while (_txbuf.available() && (_txbuf.getNbAvailable() > 0)) {
+        value = _txbuf.get();
+        if (_txbuf.available() && ((_txbuf.getNbAvailable() % 2) != 0)) {
+            value |= ((_txbuf.get() << 8) & 0XFF00);
+            SPI::write(value);
+            dbg_cnt++;
+        }
+    }
+    debug_if(local_debug, "SPI Sent %d BYTES\r\n", 2 * dbg_cnt);
+    // disable the TX interrupt when there is nothing left to send
+    BufferedSpi::attach(NULL, BufferedSpi::TxIrq);
+    // trigger callback if necessary
+    if (_cbs[TxIrq]) {
+        _cbs[TxIrq]();
+    }
+    return;
+}
+
+void BufferedSpi::prime(void)
+{
+    BufferedSpi::txIrq();                // only write to hardware in one place
+    return;
+}
+
+void BufferedSpi::attach(Callback<void()> func, IrqType type)
+{
+    _cbs[type] = func;
+}
+
+void BufferedSpi::sigio(Callback<void()> func)
+{
+    core_util_critical_section_enter();
+    _sigio_cb = func;
+    if (_sigio_cb) {
+        if (_sigio_event == 1) {
+            _sigio_cb();
+            _sigio_event = 0;
+        }
+    }
+    core_util_critical_section_exit();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ATParser/BufferedSpi/BufferedSpi.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,234 @@
+
+/**
+ * @file    BufferedSpi.h
+ * @brief   Software Buffer - Extends mbed SPI functionallity
+ * @author  Armelle Duboc
+ * @version 1.0
+ * @see
+ *
+ * Copyright (c) STMicroelectronics 2017
+ *
+ * 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.
+ */
+
+#ifndef BUFFEREDSPI_H
+#define BUFFEREDSPI_H
+
+#include "mbed.h"
+#include "MyBuffer.h"
+
+/** A spi port (SPI) for communication with wifi device
+ *
+ * Can be used for Full Duplex communication, or Simplex by specifying
+ * one pin as NC (Not Connected)
+ *
+ * Example:
+ * @code
+ *  #include "mbed.h"
+ *  #include "BufferedSerial.h"
+ *
+ *  BufferedSerial pc(USBTX, USBRX);
+ *
+ *  int main()
+ *  {
+ *      while(1)
+ *      {
+ *          Timer s;
+ *
+ *          s.start();
+ *          pc.printf("Hello World - buffered\n");
+ *          int buffered_time = s.read_us();
+ *          wait(0.1f); // give time for the buffer to empty
+ *
+ *          s.reset();
+ *          printf("Hello World - blocking\n");
+ *          int polled_time = s.read_us();
+ *          s.stop();
+ *          wait(0.1f); // give time for the buffer to empty
+ *
+ *          pc.printf("printf buffered took %d us\n", buffered_time);
+ *          pc.printf("printf blocking took %d us\n", polled_time);
+ *          wait(0.5f);
+ *      }
+ *  }
+ * @endcode
+ */
+
+/**
+ *  @class BufferedSpi
+ *  @brief Software buffers and interrupt driven tx and rx for Serial
+ */
+class BufferedSpi : public SPI {
+private:
+    DigitalOut    nss;
+    MyBuffer <char> _txbuf;
+    uint32_t      _buf_size;
+    uint32_t      _tx_multiple;
+    volatile int _timeout;
+    void txIrq(void);
+    void prime(void);
+
+    InterruptIn *_datareadyInt;
+    volatile int _cmddata_rdy_rising_event;
+    void DatareadyRising(void);
+    int wait_cmddata_rdy_rising_event(void);
+    int wait_cmddata_rdy_high(void);
+
+
+    Callback<void()> _cbs[2];
+
+    Callback<void()> _sigio_cb;
+    uint8_t          _sigio_event;
+
+public:
+    MyBuffer <char> _rxbuf;
+    DigitalIn dataready;
+    enum IrqType {
+        RxIrq = 0,
+        TxIrq,
+
+        IrqCnt
+    };
+
+    /** Create a BufferedSpi Port, connected to the specified transmit and receive pins
+     *  @param SPI mosi pin
+     *  @param SPI miso pin
+     *  @param SPI sclk pin
+     *  @param SPI nss pin
+     *  @param Dataready pin
+     *  @param buf_size printf() buffer size
+     *  @param tx_multiple amount of max printf() present in the internal ring buffer at one time
+     *  @param name optional name
+    */
+    BufferedSpi(PinName mosi, PinName miso, PinName sclk, PinName nss, PinName datareadypin, uint32_t buf_size = 2500, uint32_t tx_multiple = 1, const char *name = NULL);
+
+    /** Destroy a BufferedSpi Port
+     */
+    virtual ~BufferedSpi(void);
+
+    /** call to SPI frequency Function
+     */
+    virtual void frequency(int hz);
+
+    /** clear the transmit buffer
+     */
+    virtual void flush_txbuf(void);
+
+    /** call to SPI format function
+     */
+    virtual void format(int bits, int mode);
+
+    virtual void enable_nss(void);
+
+    virtual void disable_nss(void);
+
+    /** Check on how many bytes are in the rx buffer
+     *  @return 1 if something exists, 0 otherwise
+     */
+    virtual int readable(void);
+
+    /** Check to see if the tx buffer has room
+     *  @return 1 always has room and can overwrite previous content if too small / slow
+     */
+    virtual int writeable(void);
+
+    /** Get a single byte from the BufferedSpi Port.
+     *  Should check readable() before calling this.
+     *  @return A byte that came in on the SPI Port
+     */
+    virtual int getc(void);
+
+    /** Write a single byte to the BufferedSpi Port.
+     *  @param c The byte to write to the SPI Port
+     *  @return The byte that was written to the SPI Port Buffer
+     */
+    virtual int putc(int c);
+
+    /** Write a string to the BufferedSpi Port. Must be NULL terminated
+     *  @param s The string to write to the Spi Port
+     *  @return The number of bytes written to the Spi Port Buffer
+     */
+    virtual int puts(const char *s);
+
+    /** Write a formatted string to the BufferedSpi Port.
+     *  @param format The string + format specifiers to write to the Spi Port
+     *  @return The number of bytes written to the Spi Port Buffer
+     */
+    virtual int printf(const char *format, ...);
+
+    /** Write data to the Buffered Spi Port
+     *  @param s A pointer to data to send
+     *  @param length The amount of data being pointed to
+     *  @return The number of bytes written to the Spi Port Buffer
+     */
+    virtual ssize_t buffwrite(const void *s, std::size_t length);
+
+    /** Send datas to the Spi port that are already present
+     *  in the internal _txbuffer
+     *  @param length
+     *  @return the number of bytes written on the SPI port
+     */
+    virtual ssize_t buffsend(size_t length);
+
+    /** Read data from the Spi Port to the _rxbuf
+     *  @param max: optional. = max sieze of the input read
+     *  @return The number of bytes read from the SPI port and written to the _rxbuf
+     */
+    virtual ssize_t read();
+    virtual ssize_t read(uint32_t max);
+
+    /**
+    * Allows timeout to be changed between commands
+    *
+    * @param timeout timeout of the connection in ms
+    */
+    void setTimeout(int timeout)
+    {
+        /*  this is a safe guard timeout at SPI level in case module is stuck */
+        _timeout = timeout;
+    }
+
+    /** Register a callback once any data is ready for sockets
+     *  @param func     Function to call on state change
+     */
+    virtual void sigio(Callback<void()> func);
+
+    /** Attach a function to call whenever a serial interrupt is generated
+     *  @param func A pointer to a void function, or 0 to set as none
+     *  @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty)
+     */
+    virtual void attach(Callback<void()> func, IrqType type = RxIrq);
+
+    /** Attach a member function to call whenever a serial interrupt is generated
+     *  @param obj pointer to the object to call the member function on
+     *  @param method pointer to the member function to call
+     *  @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty)
+     */
+    template <typename T>
+    void attach(T *obj, void (T::*method)(), IrqType type = RxIrq)
+    {
+        attach(Callback<void()>(obj, method), type);
+    }
+
+    /** Attach a member function to call whenever a serial interrupt is generated
+     *  @param obj pointer to the object to call the member function on
+     *  @param method pointer to the member function to call
+     *  @param type Which serial interrupt to attach the member function to (Serial::RxIrq for receive, TxIrq for transmit buffer empty)
+     */
+    template <typename T>
+    void attach(T *obj, void (*method)(T *), IrqType type = RxIrq)
+    {
+        attach(Callback<void()>(obj, method), type);
+    }
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ISM43362.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,699 @@
+/* ISM43362 Example
+*
+* Copyright (c) STMicroelectronics 2018
+ *
+ * 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.
+ */
+#include <string.h>
+#include "ISM43362.h"
+#include "mbed_debug.h"
+
+// activate / de-activate debug
+#define ism_debug 0
+
+ISM43362::ISM43362(PinName mosi, PinName miso, PinName sclk, PinName nss, PinName resetpin, PinName datareadypin, PinName wakeup, bool debug)
+    : _bufferspi(mosi, miso, sclk, nss, datareadypin),
+      _parser(_bufferspi),
+      _resetpin(resetpin),
+      _packets(0), _packets_end(&_packets)
+{
+    DigitalOut wakeup_pin(wakeup);
+    _bufferspi.format(16, 0); /* 16bits, ploarity low, phase 1Edge, master mode */
+    _bufferspi.frequency(20000000); /* up to 20 MHz */
+    _active_id = 0xFF;
+    _FwVersionId = 0;
+
+    _ism_debug = debug || ism_debug;
+    reset();
+}
+
+/**
+  * @brief  Parses and returns number from string.
+  * @param  ptr: pointer to string
+  * @param  cnt: pointer to the number of parsed digit
+  * @retval integer value.
+  */
+#define CHARISHEXNUM(x)                 (((x) >= '0' && (x) <= '9') || \
+                                         ((x) >= 'a' && (x) <= 'f') || \
+                                         ((x) >= 'A' && (x) <= 'F'))
+#define CHARISNUM(x)                    ((x) >= '0' && (x) <= '9')
+#define CHAR2NUM(x)                     ((x) - '0')
+
+
+extern "C" int32_t ParseNumber(char *ptr, uint8_t *cnt)
+{
+    uint8_t minus = 0, i = 0;
+    int32_t sum = 0;
+
+    if (*ptr == '-') {                                      /* Check for minus character */
+        minus = 1;
+        ptr++;
+        i++;
+    }
+    if (*ptr == 'C') {  /* input string from get_firmware_version is Cx.x.x.x */
+        ptr++;
+    }
+
+    while (CHARISNUM(*ptr) || (*ptr == '.')) { /* Parse number */
+        if (*ptr == '.') {
+            ptr++; // next char
+        } else {
+            sum = 10 * sum + CHAR2NUM(*ptr);
+            ptr++;
+            i++;
+        }
+    }
+
+    if (cnt != NULL) {                   /* Save number of characters used for number */
+        *cnt = i;
+    }
+    if (minus) {                         /* Minus detected */
+        return 0 - sum;
+    }
+    return sum;                          /* Return number */
+}
+
+uint32_t ISM43362::get_firmware_version(void)
+{
+    char tmp_buffer[250];
+    char *ptr, *ptr2;
+    char _fw_version[16];
+
+    /* Use %[^\n] instead of %s to allow having spaces in the string */
+    if (!(_parser.send("I?") && _parser.recv("%[^\n^\r]\r\n", tmp_buffer) && check_response())) {
+        debug_if(_ism_debug, "ISM43362: get_firmware_version is FAIL\r\n");
+        return 0;
+    }
+    debug_if(_ism_debug, "ISM43362: get_firmware_version = %s\r\n", tmp_buffer);
+
+    // Get the first version in the string
+    ptr = strtok((char *)tmp_buffer, ",");
+    ptr = strtok(NULL, ",");
+    ptr2 = strtok(NULL, ",");
+    if (ptr == NULL) {
+        debug_if(_ism_debug, "ISM43362: get_firmware_version decoding is FAIL\r\n");
+        return 0;
+    }
+    strncpy(_fw_version, ptr, ptr2 - ptr);
+    _FwVersionId = ParseNumber(_fw_version, NULL);
+
+    return _FwVersionId;
+}
+
+bool ISM43362::reset(void)
+{
+    char tmp_buffer[100];
+    debug_if(_ism_debug, "ISM43362: Reset Module\r\n");
+    _resetpin = 0;
+    wait_ms(10);
+    _resetpin = 1;
+    wait_ms(500);
+
+    /* Wait for prompt line : the string is "> ". */
+    /* As the space char is not detected by sscanf function in parser.recv, */
+    /* we need to use %[\n] */
+    if (!_parser.recv(">%[^\n]", tmp_buffer)) {
+        debug_if(_ism_debug, "ISM43362: Reset Module failed\r\n");
+        return false;
+    }
+    return true;
+}
+
+void ISM43362::print_rx_buff(void)
+{
+    char tmp[150] = {0};
+    uint16_t i = 0;
+    debug_if(_ism_debug, "ISM43362: ");
+    while (i  < 150) {
+        int c = _parser.getc();
+        if (c < 0) {
+            break;
+        }
+        tmp[i] = c;
+        debug_if(_ism_debug, "0x%2X ", c);
+        i++;
+    }
+    debug_if(_ism_debug, "\n");
+    debug_if(_ism_debug, "ISM43362: Buffer content =====%s=====\r\n", tmp);
+}
+
+/*  checks the standard OK response of the WIFI module, shouldbe:
+ *  \r\nDATA\r\nOK\r\n>sp
+ *  or
+ *  \r\nERROR\r\nUSAGE\r\n>sp
+ *  function returns true if OK, false otherwise. In case of error,
+ *  print error content then flush buffer */
+bool ISM43362::check_response(void)
+{
+    char tmp_buffer[100];
+    if (!_parser.recv("OK\r\n")) {
+        print_rx_buff();
+        _parser.flush();
+        return false;
+    }
+
+    /*  Then we should get the prompt: "> " */
+    /* As the space char is not detected by sscanf function in parser.recv, */
+    /* we need to use %[\n] */
+    if (!_parser.recv(">%[^\n]", tmp_buffer)) {
+        debug_if(_ism_debug, "ISM43362: Missing prompt in WIFI resp\r\n");
+        print_rx_buff();
+        _parser.flush();
+        return false;
+    }
+
+    /*  Inventek module do stuffing / padding of data with 0x15,
+     *  in case buffer contains such */
+    while (1) {
+        int c = _parser.getc();
+        if (c == 0x15) {
+            // debug_if(_ism_debug, "ISM43362: Flush char 0x%x\n", c);
+            continue;
+        } else {
+            /*  How to put it back if needed ? */
+            break;
+        }
+    }
+    return true;
+}
+
+bool ISM43362::dhcp(bool enabled)
+{
+    return (_parser.send("C4=%d", enabled ? 1 : 0) && check_response());
+}
+
+int ISM43362::connect(const char *ap, const char *passPhrase, ism_security_t ap_sec)
+{
+    char tmp[256];
+
+    if (!(_parser.send("C1=%s", ap) && check_response())) {
+        return NSAPI_ERROR_PARAMETER;
+    }
+
+    if (!(_parser.send("C2=%s", passPhrase) && check_response())) {
+        return NSAPI_ERROR_PARAMETER;
+    }
+
+    /* Check security level is acceptable */
+    if (ap_sec > ISM_SECURITY_WPA_WPA2) {
+        debug_if(_ism_debug, "ISM43362: Unsupported security level %d\n", ap_sec);
+        return NSAPI_ERROR_UNSUPPORTED;
+    }
+
+    if (!(_parser.send("C3=%d", ap_sec) && check_response())) {
+        return NSAPI_ERROR_PARAMETER;
+    }
+
+    if (_parser.send("C0")) {
+        while (_parser.recv("%[^\n]\n", tmp)) {
+            if (strstr(tmp, "OK")) {
+                _parser.flush();
+                return NSAPI_ERROR_OK;
+            }
+            if (strstr(tmp, "JOIN")) {
+                if (strstr(tmp, "Failed")) {
+                    _parser.flush();
+                    return NSAPI_ERROR_AUTH_FAILURE;
+                }
+            }
+        }
+    }
+
+    return NSAPI_ERROR_NO_CONNECTION;
+}
+
+bool ISM43362::disconnect(void)
+{
+    return (_parser.send("CD") && check_response());
+}
+
+const char *ISM43362::getIPAddress(void)
+{
+    char tmp_ip_buffer[250];
+    char *ptr, *ptr2;
+
+    /* Use %[^\n] instead of %s to allow having spaces in the string */
+    if (!(_parser.send("C?")
+            && _parser.recv("%[^\n^\r]\r\n", tmp_ip_buffer)
+            && check_response())) {
+        debug_if(_ism_debug, "ISM43362: getIPAddress LINE KO: %s\n", tmp_ip_buffer);
+        return 0;
+    }
+
+    /* Get the IP address in the result */
+    /* TODO : check if the begining of the string is always = "eS-WiFi_AP_C47F51011231," */
+    ptr = strtok((char *)tmp_ip_buffer, ",");
+    ptr = strtok(NULL, ",");
+    ptr = strtok(NULL, ",");
+    ptr = strtok(NULL, ",");
+    ptr = strtok(NULL, ",");
+    ptr = strtok(NULL, ",");
+    ptr2 = strtok(NULL, ",");
+    if (ptr == NULL) {
+        return 0;
+    }
+    strncpy(_ip_buffer, ptr, ptr2 - ptr);
+
+    tmp_ip_buffer[59] = 0;
+    debug_if(_ism_debug, "ISM43362: receivedIPAddress: %s\n", _ip_buffer);
+
+    return _ip_buffer;
+}
+
+const char *ISM43362::getMACAddress(void)
+{
+    if (!(_parser.send("Z5") && _parser.recv("%s\r\n", _mac_buffer) && check_response())) {
+        debug_if(_ism_debug, "ISM43362: receivedMacAddress LINE KO: %s\n", _mac_buffer);
+        return 0;
+    }
+
+    debug_if(_ism_debug, "ISM43362: receivedMacAddress:%s, size=%d\r\n", _mac_buffer, sizeof(_mac_buffer));
+
+    return _mac_buffer;
+}
+
+const char *ISM43362::getGateway()
+{
+    char tmp[250];
+    /* Use %[^\n] instead of %s to allow having spaces in the string */
+    if (!(_parser.send("C?") && _parser.recv("%[^\n^\r]\r\n", tmp) && check_response())) {
+        debug_if(_ism_debug, "ISM43362: getGateway LINE KO: %s\r\n", tmp);
+        return 0;
+    }
+
+    /* Extract the Gateway in the received buffer */
+    char *ptr;
+    ptr = strtok(tmp, ",");
+    for (int i = 0; i < 7; i++) {
+        if (ptr == NULL) {
+            break;
+        }
+        ptr = strtok(NULL, ",");
+    }
+
+    strncpy(_gateway_buffer, ptr, sizeof(_gateway_buffer));
+
+    debug_if(_ism_debug, "ISM43362: getGateway: %s\r\n", _gateway_buffer);
+
+    return _gateway_buffer;
+}
+
+const char *ISM43362::getNetmask()
+{
+    char tmp[250];
+    /* Use %[^\n] instead of %s to allow having spaces in the string */
+    if (!(_parser.send("C?") && _parser.recv("%[^\n^\r]\r\n", tmp) && check_response())) {
+        debug_if(_ism_debug, "ISM43362: getNetmask LINE KO: %s\n", tmp);
+        return 0;
+    }
+
+    /* Extract Netmask in the received buffer */
+    char *ptr;
+    ptr = strtok(tmp, ",");
+    for (int i = 0; i < 6; i++) {
+        if (ptr == NULL) {
+            break;
+        }
+        ptr = strtok(NULL, ",");
+    }
+
+    strncpy(_netmask_buffer, ptr, sizeof(_netmask_buffer));
+
+    debug_if(_ism_debug, "ISM43362: getNetmask: %s\r\n", _netmask_buffer);
+
+    return _netmask_buffer;
+}
+
+int8_t ISM43362::getRSSI()
+{
+    int8_t rssi;
+    char tmp[25];
+
+    if (!(_parser.send("CR") && _parser.recv("%s\r\n", tmp) && check_response())) {
+        debug_if(_ism_debug, "ISM43362: getRSSI LINE KO: %s\r\n", tmp);
+        return 0;
+    }
+
+    rssi = ParseNumber(tmp, NULL);
+
+    debug_if(_ism_debug, "ISM43362: getRSSI: %d\r\n", rssi);
+
+    return rssi;
+}
+/**
+  * @brief  Parses Security type.
+  * @param  ptr: pointer to string
+  * @retval Encryption type.
+  */
+extern "C" nsapi_security_t ParseSecurity(char *ptr)
+{
+    if (strstr(ptr, "Open")) {
+        return NSAPI_SECURITY_NONE;
+    } else if (strstr(ptr, "WEP")) {
+        return NSAPI_SECURITY_WEP;
+    } else if (strstr(ptr, "WPA2 AES")) {
+        return NSAPI_SECURITY_WPA2;
+    } else if (strstr(ptr, "WPA WPA2")) {
+        return NSAPI_SECURITY_WPA_WPA2;
+    } else if (strstr(ptr, "WPA2 TKIP")) {
+        return NSAPI_SECURITY_UNKNOWN;    // no match in mbed
+    } else if (strstr(ptr, "WPA2")) {
+        return NSAPI_SECURITY_WPA2;    // catch any other WPA2 formula
+    } else if (strstr(ptr, "WPA")) {
+        return NSAPI_SECURITY_WPA;
+    } else {
+        return NSAPI_SECURITY_UNKNOWN;
+    }
+}
+
+/**
+  * @brief  Convert char in Hex format to integer.
+  * @param  a: character to convert
+  * @retval integer value.
+  */
+extern "C"  uint8_t Hex2Num(char a)
+{
+    if (a >= '0' && a <= '9') {                             /* Char is num */
+        return a - '0';
+    } else if (a >= 'a' && a <= 'f') {                      /* Char is lowercase character A - Z (hex) */
+        return (a - 'a') + 10;
+    } else if (a >= 'A' && a <= 'F') {                      /* Char is uppercase character A - Z (hex) */
+        return (a - 'A') + 10;
+    }
+
+    return 0;
+}
+
+/**
+  * @brief  Extract a hex number from a string.
+  * @param  ptr: pointer to string
+  * @param  cnt: pointer to the number of parsed digit
+  * @retval Hex value.
+  */
+extern "C" uint32_t ParseHexNumber(char *ptr, uint8_t *cnt)
+{
+    uint32_t sum = 0;
+    uint8_t i = 0;
+
+    while (CHARISHEXNUM(*ptr)) {         /* Parse number */
+        sum <<= 4;
+        sum += Hex2Num(*ptr);
+        ptr++;
+        i++;
+    }
+
+    if (cnt != NULL) {                  /* Save number of characters used for number */
+        *cnt = i;
+    }
+    return sum;                         /* Return number */
+}
+
+bool ISM43362::isConnected(void)
+{
+    return getIPAddress() != 0;
+}
+
+int ISM43362::scan(WiFiAccessPoint *res, unsigned limit)
+{
+    unsigned cnt = 0, num = 0;
+    char *ptr;
+    char tmp[256];
+
+    if (!(_parser.send("F0"))) {
+        debug_if(_ism_debug, "ISM43362: scan error\r\n");
+        return 0;
+    }
+
+    /* Parse the received buffer and fill AP buffer */
+    /* Use %[^\n] instead of %s to allow having spaces in the string */
+    while (_parser.recv("#%[^\n]\n", tmp)) {
+        if (limit != 0 && cnt >= limit) {
+            /* reached end */
+            break;
+        }
+        nsapi_wifi_ap_t ap = {0};
+        debug_if(_ism_debug, "ISM43362: received:%s\n", tmp);
+        ptr = strtok(tmp, ",");
+        num = 0;
+        while (ptr != NULL) {
+            switch (num++) {
+                case 0: /* Ignore index */
+                case 4: /* Ignore Max Rate */
+                case 5: /* Ignore Network Type */
+                case 7: /* Ignore Radio Band */
+                    break;
+                case 1:
+                    ptr[strlen(ptr) - 1] = 0;
+                    strncpy((char *)ap.ssid,  ptr + 1, 32);
+                    break;
+                case 2:
+                    for (int i = 0; i < 6; i++) {
+                        ap.bssid[i] = ParseHexNumber(ptr + (i * 3), NULL);
+                    }
+                    break;
+                case 3:
+                    ap.rssi = ParseNumber(ptr, NULL);
+                    break;
+                case 6:
+                    ap.security = ParseSecurity(ptr);
+                    break;
+                case 8:
+                    ap.channel = ParseNumber(ptr, NULL);
+                    num = 1;
+                    break;
+                default:
+                    break;
+            }
+            ptr = strtok(NULL, ",");
+        }
+        if (res != NULL) {
+            res[cnt] = WiFiAccessPoint(ap);
+        }
+        cnt++;
+    }
+
+    /* We may stop before having read all the APs list, so flush the rest of
+     * it as well as OK commands */
+    _parser.flush();
+
+    debug_if(_ism_debug, "ISM43362: End of Scan: cnt=%d\n", cnt);
+
+    return cnt;
+
+}
+
+bool ISM43362::open(const char *type, int id, const char *addr, int port)
+{
+    /* TODO : This is the implementation for the client socket, need to check if need to create openserver too */
+    //IDs only 0-3
+    if ((id < 0) || (id > 3)) {
+        debug_if(_ism_debug, "ISM43362: open: wrong id\n");
+        return false;
+    }
+    /* Set communication socket */
+    _active_id = id;
+    if (!(_parser.send("P0=%d", id) && check_response())) {
+        debug_if(_ism_debug, "ISM43362: open: P0 issue\n");
+        return false;
+    }
+    /* Set protocol */
+    if (!(_parser.send("P1=%s", type) && check_response())) {
+        debug_if(_ism_debug, "ISM43362: open: P1 issue\n");
+        return false;
+    }
+    /* Set address */
+    if (!(_parser.send("P3=%s", addr) && check_response())) {
+        debug_if(_ism_debug, "ISM43362: open: P3 issue\n");
+        return false;
+    }
+    if (!(_parser.send("P4=%d", port) && check_response())) {
+        debug_if(_ism_debug, "ISM43362: open: P4 issue\n");
+        return false;
+    }
+    /* Start client */
+    if (!(_parser.send("P6=1") && check_response())) {
+        debug_if(_ism_debug, "ISM43362: open: P6 issue\n");
+        return false;
+    }
+
+    /* request as much data as possible - i.e. module max size */
+    if (!(_parser.send("R1=%d", ES_WIFI_MAX_RX_PACKET_SIZE) && check_response())) {
+        debug_if(_ism_debug, "ISM43362: open: R1 issue\n");
+        return -1;
+    }
+
+    /* Non blocking mode : set Read Transport Timeout to 1ms */
+    if (!(_parser.send("R2=1") && check_response())) {
+        debug_if(_ism_debug, "ISM43362: open: R2 issue\n");
+        return -1;
+    }
+
+    debug_if(_ism_debug, "ISM43362: open ok with id %d type %s addr %s port %d\n", id, type, addr, port);
+
+    return true;
+}
+
+bool ISM43362::dns_lookup(const char *name, char *ip)
+{
+    char tmp[30];
+
+    if (!(_parser.send("D0=%s", name) && _parser.recv("%s\r\n", tmp)
+            && check_response())) {
+        debug_if(_ism_debug, "ISM43362 dns_lookup: D0 issue: %s\n", tmp);
+        return 0;
+    }
+
+    strncpy(ip, tmp, sizeof(tmp));
+
+    debug_if(_ism_debug, "ISM43362 dns_lookup: %s ok\n", ip);
+    return 1;
+}
+
+bool ISM43362::send(int id, const void *data, uint32_t amount)
+{
+    // The Size limit has to be checked on caller side.
+    if (amount > ES_WIFI_MAX_TX_PACKET_SIZE) {
+        debug_if(_ism_debug, "ISM43362 send: max issue\n");
+        return false;
+    }
+
+    /* Activate the socket id in the wifi module */
+    if ((id < 0) || (id > 3)) {
+        return false;
+    }
+    if (_active_id != id) {
+        _active_id = id;
+        if (!(_parser.send("P0=%d", id) && check_response())) {
+            debug_if(_ism_debug, "ISM43362 send: P0 issue\n");
+            return false;
+        }
+    }
+
+    /* set Write Transport Packet Size */
+    int i = _parser.printf("S3=%d\r", (int)amount);
+    if (i < 0) {
+        debug_if(_ism_debug, "ISM43362 send: S3 issue\n");
+        return false;
+    }
+    i = _parser.write((const char *)data, amount, i);
+    if (i < 0) {
+        return false;
+    }
+
+    if (!check_response()) {
+        return false;
+    }
+
+    debug_if(_ism_debug, "ISM43362 send: id %d amount %d\n", id, amount);
+    return true;
+}
+
+int ISM43362::check_recv_status(int id, void *data)
+{
+    int read_amount;
+
+    debug_if(_ism_debug, "ISM43362 check_recv_status: id %d\r\n", id);
+
+    /* Activate the socket id in the wifi module */
+    if ((id < 0) || (id > 3)) {
+        debug_if(_ism_debug, "ISM43362 check_recv_status: ERROR with id %d\r\n", id);
+        return -1;
+    }
+
+    if (_active_id != id) {
+        _active_id = id;
+        if (!(_parser.send("P0=%d", id) && check_response())) {
+            return -1;
+        }
+    }
+
+
+    if (!_parser.send("R0")) {
+        return -1;
+    }
+    read_amount = _parser.read((char *)data);
+
+    if (read_amount < 0) {
+        debug_if(_ism_debug, "ISM43362 check_recv_status: ERROR in data RECV, timeout?\r\n");
+        return -1; /* nothing to read */
+    }
+
+    /*  If there are spurious 0x15 at the end of the data, this is an error
+     *  we hall can get rid off of them :-(
+     *  This should not happen, but let's try to clean-up anyway
+     */
+    char *cleanup = (char *) data;
+    while ((read_amount > 0) && (cleanup[read_amount - 1] == 0x15)) {
+        // debug_if(_ism_debug, "ISM43362 check_recv_status: spurious 0X15 trashed\r\n");
+        /* Remove the trailling char then search again */
+        read_amount--;
+    }
+
+    if ((read_amount >= 6) && (strncmp("OK\r\n> ", (char *)data, 6) == 0)) {
+        // debug_if(_ism_debug, "ISM43362 check_recv_status: recv 2 nothing to read=%d\r\n", read_amount);
+        // read_amount -= 6;
+        return 0; /* nothing to read */
+    } else if ((read_amount >= 8) && (strncmp((char *)((uint32_t) data + read_amount - 8), "\r\nOK\r\n> ", 8)) == 0) {
+        /* bypass ""\r\nOK\r\n> " if present at the end of the chain */
+        read_amount -= 8;
+    } else {
+        debug_if(_ism_debug, "ISM43362 check_recv_status: ERROR, flushing %d bytes: ", read_amount);
+        // for (int i = 0; i < read_amount; i++) {
+        //      debug_if(_ism_debug, "%2X ", cleanup[i]);
+        // }
+        // debug_if(_ism_debug, "\r\n (ASCII)", cleanup);
+        cleanup[read_amount] = 0;
+        debug_if(_ism_debug, "%s\r\n", cleanup);
+        return -1; /* nothing to read */
+    }
+
+    debug_if(_ism_debug, "ISM43362 check_recv_status: id %d read_amount=%d\r\n", id, read_amount);
+    return read_amount;
+}
+
+bool ISM43362::close(int id)
+{
+    if ((id < 0) || (id > 3)) {
+        debug_if(_ism_debug, "ISM43362: Wrong socket number\n");
+        return false;
+    }
+    /* Set connection on this socket */
+    debug_if(_ism_debug, "ISM43362: CLOSE socket id=%d\n", id);
+    _active_id = id;
+    if (!(_parser.send("P0=%d", id) && check_response())) {
+        return false;
+    }
+    /* close this socket */
+    if (!(_parser.send("P6=0") && check_response())) {
+        return false;
+    }
+    return true;
+}
+
+bool ISM43362::readable()
+{
+    /* not applicable with SPI api */
+    return true;
+}
+
+bool ISM43362::writeable()
+{
+    /* not applicable with SPI api */
+    return true;
+}
+
+void ISM43362::attach(Callback<void()> func)
+{
+    /* not applicable with SPI api */
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362/ISM43362.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,250 @@
+/* ISM43362Interface Example
+ * Copyright (c) STMicroelectronics 2017
+ *
+ * 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.
+ */
+
+#ifndef ISM43362_H
+#define ISM43362_H
+#include "ATParser.h"
+
+#define ES_WIFI_MAX_SSID_NAME_SIZE                  32
+#define ES_WIFI_MAX_PSWD_NAME_SIZE                  32
+#define ES_WIFI_PRODUCT_ID_SIZE                     32
+#define ES_WIFI_PRODUCT_NAME_SIZE                   32
+#define ES_WIFI_FW_REV_SIZE                         16
+#define ES_WIFI_API_REV_SIZE                        16
+#define ES_WIFI_STACK_REV_SIZE                      16
+#define ES_WIFI_RTOS_REV_SIZE                       16
+
+// The input range for AT Command 'R1' is 0 to 1200 bytes
+// 'R1' Set Read Transport Packet Size (bytes)
+#define ES_WIFI_MAX_RX_PACKET_SIZE                     1200
+// Module maxume DATA payload for Tx packet is 1460
+#define ES_WIFI_MAX_TX_PACKET_SIZE                     1460
+typedef enum ism_security {
+    ISM_SECURITY_NONE         = 0x0,      /*!< open access point */
+    ISM_SECURITY_WEP          = 0x1,      /*!< phrase conforms to WEP */
+    ISM_SECURITY_WPA          = 0x2,      /*!< phrase conforms to WPA */
+    ISM_SECURITY_WPA2         = 0x3,      /*!< phrase conforms to WPA2 */
+    ISM_SECURITY_WPA_WPA2     = 0x4,      /*!< phrase conforms to WPA/WPA2 */
+    ISM_SECURITY_UNKNOWN      = 0xFF,     /*!< unknown/unsupported security in scan results */
+} ism_security_t;
+
+extern "C" int32_t ParseNumber(char *ptr, uint8_t *cnt);
+
+/** ISM43362Interface class.
+    This is an interface to a ISM43362 radio.
+ */
+class ISM43362 {
+public:
+    ISM43362(PinName mosi, PinName miso, PinName clk, PinName nss, PinName resetpin, PinName datareadypin, PinName wakeup, bool debug = false);
+
+    /**
+    * Check firmware version of ISM43362
+    *
+    * @return fw version or null if no version is read
+    */
+    uint32_t get_firmware_version(void);
+
+    /**
+    * Reset ISM43362
+    *
+    * @return true only if ISM43362 resets successfully
+    */
+    bool reset(void);
+
+    /**
+    * Enable/Disable DHCP
+    *
+    * @param enabled DHCP enabled when true
+    * @return true only if ISM43362 enables/disables DHCP successfully
+    */
+    bool dhcp(bool enabled);
+
+    /**
+    * Connect ISM43362 to AP
+    *
+    * @param ap the name of the AP
+    * @param passPhrase the password of AP
+    * @param ap_sec the security level of network AP
+    * @return nsapi_error enum
+    */
+    int connect(const char *ap, const char *passPhrase, ism_security_t ap_sec);
+
+    /**
+    * Disconnect ISM43362 from AP
+    *
+    * @return true only if ISM43362 is disconnected successfully
+    */
+    bool disconnect(void);
+
+    /**
+    * Get the IP address of ISM43362
+    *
+    * @return null-teriminated IP address or null if no IP address is assigned
+    */
+    const char *getIPAddress(void);
+
+    /**
+    * Get the MAC address of ISM43362
+    *
+    * @return null-terminated MAC address or null if no MAC address is assigned
+    */
+    const char *getMACAddress(void);
+
+    /** Get the local gateway
+    *
+    *  @return         Null-terminated representation of the local gateway
+    *                  or null if no network mask has been recieved
+    */
+    const char *getGateway();
+
+    /** Get the local network mask
+     *
+     *  @return         Null-terminated representation of the local network mask
+     *                  or null if no network mask has been recieved
+     */
+    const char *getNetmask();
+
+    /* Return RSSI for active connection
+     *
+     * @return      Measured RSSI
+     */
+    int8_t getRSSI();
+
+    /**
+    * Check if ISM43362 is conenected
+    *
+    * @return true only if the chip has an IP address
+    */
+    bool isConnected(void);
+
+    /** Scan for available networks
+     *
+     * @param  ap    Pointer to allocated array to store discovered AP
+     * @param  limit Size of allocated @a res array, or 0 to only count available AP
+     * @return       Number of entries in @a res, or if @a count was 0 number of available networks, negative on error
+     *               see @a nsapi_error
+     */
+    int scan(WiFiAccessPoint *res, unsigned limit);
+
+    /**Perform a dns query
+    *
+    * @param name Hostname to resolve
+    * @param ip   Buffer to store IP address
+    * @return 0 true on success, false on failure
+    */
+    bool dns_lookup(const char *name, char *ip);
+
+    /**
+    * Open a socketed connection
+    *
+    * @param type the type of socket to open "UDP" or "TCP"
+    * @param id id to give the new socket, valid 0-4
+    * @param port port to open connection with
+    * @param addr the IP address of the destination
+    * @return true only if socket opened successfully
+    */
+    bool open(const char *type, int id, const char *addr, int port);
+
+    /**
+    * Sends data to an open socket
+    *
+    * @param id id of socket to send to
+    * @param data data to be sent
+    * @param amount amount of data to be sent - max 1024
+    * @return true only if data sent successfully
+    */
+    bool send(int id, const void *data, uint32_t amount);
+
+    /**
+    * Receives data from an open socket
+    *
+    * @param id id to receive from
+    * @param data placeholder for returned information
+    * @param amount number of bytes to be received
+    * @return the number of bytes received
+    */
+    int32_t recv(int id, void *data, uint32_t amount);
+
+    /**
+    * Closes a socket
+    *
+    * @param id id of socket to close, valid only 0-4
+    * @return true only if socket is closed successfully
+    */
+    bool close(int id);
+
+    /**
+    * Checks if data is available
+    */
+    bool readable();
+
+    /**
+    * Checks if data can be written
+    */
+    bool writeable();
+
+    /**
+    * Attach a function to call whenever network state has changed
+    *
+    * @param func A pointer to a void function, or 0 to set as none
+    */
+    void attach(Callback<void()> func);
+
+    /**
+    * Check is datas are available to read for a socket
+    * @param id socket id
+    * @param data placeholder for returned information
+    * @param amount size to read for the check
+    * @return amount of read value, or -1 for errors
+    */
+    int check_recv_status(int id, void *data);
+
+    /**
+    * Attach a function to call whenever network state has changed
+    *
+    * @param obj pointer to the object to call the member function on
+    * @param method pointer to the member function to call
+    */
+    template <typename T, typename M>
+    void attach(T *obj, M method)
+    {
+        attach(Callback<void()>(obj, method));
+    }
+
+private:
+    BufferedSpi _bufferspi;
+    ATParser _parser;
+    DigitalOut _resetpin;
+    volatile int _active_id;
+    void print_rx_buff(void);
+    bool check_response(void);
+    struct packet {
+        struct packet *next;
+        int id;
+        uint32_t len;
+        // data follows
+    } *_packets, * *_packets_end;
+    void _packet_handler();
+    bool _ism_debug;
+
+    char _ip_buffer[16];
+    char _gateway_buffer[16];
+    char _netmask_buffer[16];
+    char _mac_buffer[18];
+    uint32_t _FwVersionId;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362Interface.cpp	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,555 @@
+/* ISM43362 implementation of NetworkInterfaceAPI
+ * Copyright (c) STMicroelectronics 2018
+ *
+ * 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.
+ */
+
+#include <string.h>
+#include "ISM43362Interface.h"
+#include "mbed_debug.h"
+
+                                            // Product ID,FW Revision,API Revision,Stack Revision,RTOS Revision,CPU Clock,Product Name
+#define LATEST_FW_VERSION_NUMBER "C3.5.2.5" // ISM43362-M3G-L44-SPI,C3.5.2.5.STM,v3.5.2,v1.4.0.rc1,v8.2.1,120000000,Inventek eS-WiFi
+
+// activate / de-activate debug
+#define ism_interface_debug 0
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+// ISM43362Interface implementation
+ISM43362Interface::ISM43362Interface(bool debug)
+    : _ism(MBED_CONF_ISM43362_WIFI_MOSI, MBED_CONF_ISM43362_WIFI_MISO, MBED_CONF_ISM43362_WIFI_SCLK, MBED_CONF_ISM43362_WIFI_NSS, MBED_CONF_ISM43362_WIFI_RESET, MBED_CONF_ISM43362_WIFI_DATAREADY, MBED_CONF_ISM43362_WIFI_WAKEUP, debug)
+{
+    _ism_debug = ism_interface_debug || debug;
+    memset(_ids, 0, sizeof(_ids));
+    memset(_socket_obj, 0, sizeof(_socket_obj));
+    memset(_cbs, 0, sizeof(_cbs));
+    memset(ap_ssid, 0, sizeof(ap_ssid));
+    memset(ap_pass, 0, sizeof(ap_pass));
+    ap_sec = ISM_SECURITY_UNKNOWN;
+
+    thread_read_socket.start(callback(this, &ISM43362Interface::socket_check_read));
+
+    _mutex.lock();
+
+    // Check all supported firmware versions
+    _FwVersion = _ism.get_firmware_version();
+
+    if (!_FwVersion) {
+        error("ISM43362Interface: ERROR cannot read firmware version\r\n");
+    }
+
+    debug_if(_ism_debug, "ISM43362Interface: read_version = %lu\r\n", _FwVersion);
+    /* FW Revision should be with format "CX.X.X.X" with X as a single digit */
+    if ( (_FwVersion < 1000) || (_FwVersion > 9999) ) {
+        debug_if(_ism_debug, "ISM43362Interface: read_version issue\r\n");
+    }
+
+#if TARGET_DISCO_L475VG_IOT01A
+    if (_FwVersion < ParseNumber(LATEST_FW_VERSION_NUMBER, NULL)) {
+        debug_if(_ism_debug, "ISM43362Interface: please update FW\r\n");
+    }
+#endif
+
+    _mutex.unlock();
+}
+
+int ISM43362Interface::connect(const char *ssid, const char *pass, nsapi_security_t security,
+                               uint8_t channel)
+{
+    if (channel != 0) {
+        return NSAPI_ERROR_UNSUPPORTED;
+    }
+
+    nsapi_error_t credentials_status = set_credentials(ssid, pass, security);
+    if (credentials_status) {
+        return credentials_status;
+    }
+
+    return connect();
+}
+
+int ISM43362Interface::connect()
+{
+    if (strlen(ap_ssid) == 0) {
+        return NSAPI_ERROR_NO_SSID;
+    }
+
+    _mutex.lock();
+
+    if (!_ism.dhcp(true)) {
+        _mutex.unlock();
+        return NSAPI_ERROR_DHCP_FAILURE;
+    }
+
+    int connect_status = _ism.connect(ap_ssid, ap_pass, ap_sec);
+    debug_if(_ism_debug, "ISM43362Interface: connect_status %d\n", connect_status);
+
+    if (connect_status != NSAPI_ERROR_OK) {
+        _mutex.unlock();
+        return connect_status;
+    }
+
+    if (!_ism.getIPAddress()) {
+        _mutex.unlock();
+        return NSAPI_ERROR_DHCP_FAILURE;
+    }
+
+    _mutex.unlock();
+
+    return NSAPI_ERROR_OK;
+}
+
+nsapi_error_t ISM43362Interface::gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version)
+{
+    if (strlen(name) == 0) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+
+    _mutex.lock();
+    if (address->set_ip_address(name)) {
+        if (version != NSAPI_UNSPEC && address->get_ip_version() != version) {
+            _mutex.unlock();
+            return NSAPI_ERROR_DNS_FAILURE;
+        }
+
+        _mutex.unlock();
+        return NSAPI_ERROR_OK;
+    }
+
+    char *ipbuff = new char[NSAPI_IP_SIZE];
+    int ret = 0;
+    if (!_ism.dns_lookup(name, ipbuff)) {
+        ret = NSAPI_ERROR_DEVICE_ERROR;
+    } else {
+        address->set_ip_address(ipbuff);
+    }
+    _mutex.unlock();
+
+    delete[] ipbuff;
+
+    return ret;
+}
+
+int ISM43362Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
+{
+    if ((strlen(ssid) == 0) || (strlen(ssid) > 32)) {
+        return NSAPI_ERROR_PARAMETER;
+    }
+
+    if ((security != NSAPI_SECURITY_NONE) && (strcmp(pass, "") == 0)) {
+        return NSAPI_ERROR_PARAMETER;
+    }
+
+    if (strlen(pass) > 63) {
+        return NSAPI_ERROR_PARAMETER;
+    }
+
+    _mutex.lock();
+    memset(ap_ssid, 0, sizeof(ap_ssid));
+    strncpy(ap_ssid, ssid, sizeof(ap_ssid));
+
+    memset(ap_pass, 0, sizeof(ap_pass));
+    strncpy(ap_pass, pass, sizeof(ap_pass));
+
+    switch (security) {
+        case NSAPI_SECURITY_NONE:
+            ap_sec = ISM_SECURITY_NONE;
+            break;
+        case NSAPI_SECURITY_WEP:
+            ap_sec = ISM_SECURITY_WEP;
+            break;
+        case NSAPI_SECURITY_WPA:
+            ap_sec = ISM_SECURITY_WPA;
+            break;
+        case NSAPI_SECURITY_WPA2:
+            ap_sec = ISM_SECURITY_WPA2;
+            break;
+        case NSAPI_SECURITY_WPA_WPA2:
+            ap_sec = ISM_SECURITY_WPA_WPA2;
+            break;
+        default:
+            ap_sec = ISM_SECURITY_UNKNOWN;
+            break;
+    }
+    _mutex.unlock();
+
+    return NSAPI_ERROR_OK;
+}
+
+int ISM43362Interface::set_channel(uint8_t channel)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int ISM43362Interface::disconnect()
+{
+    _mutex.lock();
+
+    if (!_ism.disconnect()) {
+        _mutex.unlock();
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    _mutex.unlock();
+
+    return NSAPI_ERROR_OK;
+}
+
+const char *ISM43362Interface::get_ip_address()
+{
+    _mutex.lock();
+    const char *ret = _ism.getIPAddress();
+    _mutex.unlock();
+    return ret;
+}
+
+const char *ISM43362Interface::get_mac_address()
+{
+    _mutex.lock();
+    const char *ret = _ism.getMACAddress();
+    _mutex.unlock();
+    return ret;
+}
+
+const char *ISM43362Interface::get_gateway()
+{
+    _mutex.lock();
+    const char *ret = _ism.getGateway();
+    _mutex.unlock();
+    return ret;
+}
+
+const char *ISM43362Interface::get_netmask()
+{
+    _mutex.lock();
+    const char *ret = _ism.getNetmask();
+    _mutex.unlock();
+    return ret;
+}
+
+int8_t ISM43362Interface::get_rssi()
+{
+    _mutex.lock();
+    int8_t ret = _ism.getRSSI();
+    _mutex.unlock();
+    return ret;
+}
+
+int ISM43362Interface::scan(WiFiAccessPoint *res, unsigned count)
+{
+    _mutex.lock();
+    int ret = _ism.scan(res, count);
+    _mutex.unlock();
+    return ret;
+}
+
+struct ISM43362_socket {
+    int id;
+    nsapi_protocol_t proto;
+    volatile bool connected;
+    SocketAddress addr;
+    char read_data[1400];
+    volatile uint32_t read_data_size;
+};
+
+int ISM43362Interface::socket_open(void **handle, nsapi_protocol_t proto)
+{
+    // Look for an unused socket
+    int id = -1;
+    for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) {
+        if (!_ids[i]) {
+            id = i;
+            _ids[i] = true;
+            break;
+        }
+    }
+
+    if (id == -1) {
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    _mutex.lock();
+    struct ISM43362_socket *socket = new struct ISM43362_socket;
+    if (!socket) {
+        _mutex.unlock();
+        return NSAPI_ERROR_NO_SOCKET;
+    }
+    socket->id = id;
+    debug_if(_ism_debug, "ISM43362Interface: socket_open, id=%d\n", socket->id);
+    memset(socket->read_data, 0, sizeof(socket->read_data));
+    socket->addr = 0;
+    socket->read_data_size = 0;
+    socket->proto = proto;
+    socket->connected = false;
+    *handle = socket;
+    _mutex.unlock();
+
+    return 0;
+}
+
+int ISM43362Interface::socket_close(void *handle)
+{
+    _mutex.lock();
+    struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+    debug_if(_ism_debug, "ISM43362Interface: socket_close, id=%d\n", socket->id);
+    int err = 0;
+
+    if (!_ism.close(socket->id)) {
+        err = NSAPI_ERROR_DEVICE_ERROR;
+    }
+
+    socket->connected = false;
+    _ids[socket->id] = false;
+    _socket_obj[socket->id] = 0;
+    _mutex.unlock();
+    delete socket;
+    return err;
+}
+
+int ISM43362Interface::socket_bind(void *handle, const SocketAddress &address)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int ISM43362Interface::socket_listen(void *handle, int backlog)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int ISM43362Interface::socket_connect(void *handle, const SocketAddress &addr)
+{
+    _mutex.lock();
+    int ret = socket_connect_nolock(handle, addr);
+    _mutex.unlock();
+    return ret;
+}
+
+int ISM43362Interface::socket_connect_nolock(void *handle, const SocketAddress &addr)
+{
+    struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+    const char *proto = (socket->proto == NSAPI_UDP) ? "1" : "0";
+    if (!_ism.open(proto, socket->id, addr.get_ip_address(), addr.get_port())) {
+        return NSAPI_ERROR_DEVICE_ERROR;
+    }
+    _ids[socket->id]  = true;
+    _socket_obj[socket->id] = (uint32_t)socket;
+    socket->connected = true;
+    return 0;
+
+}
+
+
+
+void ISM43362Interface::socket_check_read()
+{
+    while (1) {
+        for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) {
+            _mutex.lock();
+            if (_socket_obj[i] != 0) {
+                struct ISM43362_socket *socket = (struct ISM43362_socket *)_socket_obj[i];
+                /* Check if there is something to read for this socket. But if it */
+                /* has already been read : don't read again */
+                if ((socket->connected) && (socket->read_data_size == 0) && _cbs[socket->id].callback) {
+                    /* if no callback is set, no need to read ?*/
+                    int read_amount = _ism.check_recv_status(socket->id, socket->read_data);
+                    // debug_if(_ism_debug, "ISM43362Interface socket_check_read: i %d read_amount %d \r\n", i, read_amount);
+                    if (read_amount > 0) {
+                        socket->read_data_size = read_amount;
+                    } else if (read_amount < 0) {
+                        /* Mark donw connection has been lost or closed */
+                        debug_if(_ism_debug, "ISM43362Interface socket_check_read: i %d closed\r\n", i, read_amount);
+                        socket->connected = false;
+                    }
+                    if (read_amount != 0) {
+                        /* There is something to read in this socket*/
+                        if (_cbs[socket->id].callback) {
+                            _cbs[socket->id].callback(_cbs[socket->id].data);
+                        }
+                    }
+                }
+            }
+            _mutex.unlock();
+        }
+        wait_ms(50);
+    }
+}
+
+int ISM43362Interface::socket_accept(void *server, void **socket, SocketAddress *addr)
+{
+    return NSAPI_ERROR_UNSUPPORTED;
+}
+
+int ISM43362Interface::socket_send(void *handle, const void *data, unsigned size)
+{
+    _mutex.lock();
+    int ret = socket_send_nolock(handle, data, size);
+    _mutex.unlock();
+    return ret;
+}
+
+/*  CAREFULL LOCK must be taken before callling this function */
+int ISM43362Interface::socket_send_nolock(void *handle, const void *data, unsigned size)
+{
+    struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+
+    if (size > ES_WIFI_MAX_TX_PACKET_SIZE) {
+        size = ES_WIFI_MAX_TX_PACKET_SIZE;
+    }
+
+    if (!_ism.send(socket->id, data, size)) {
+        debug_if(_ism_debug, "ISM43362Interface: socket_send ERROR\r\n");
+        return NSAPI_ERROR_DEVICE_ERROR; // or WOULD_BLOCK ?
+    }
+
+    return size;
+}
+
+int ISM43362Interface::socket_recv(void *handle, void *data, unsigned size)
+{
+    _mutex.lock();
+    unsigned recv = 0;
+    struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+    char *ptr = (char *)data;
+
+    // debug_if(_ism_debug, "ISM43362Interface socket_recv: req=%d read_data_size=%d connected %d\r\n", size, socket->read_data_size, socket->connected);
+
+    if (!socket->connected) {
+        _mutex.unlock();
+        return NSAPI_ERROR_CONNECTION_LOST;
+    }
+
+    if (socket->read_data_size == 0) {
+        /* if no callback is set, no need to read ?*/
+        int read_amount = _ism.check_recv_status(socket->id, socket->read_data);
+        if (read_amount > 0) {
+            socket->read_data_size = read_amount;
+        } else if (read_amount < 0) {
+            socket->connected = false;
+            debug_if(_ism_debug, "ISM43362Interface socket_recv: socket closed\r\n");
+            _mutex.unlock();
+            return NSAPI_ERROR_CONNECTION_LOST;
+        }
+    }
+
+    if (socket->read_data_size != 0) {
+        // debug_if(_ism_debug, "ISM43362Interface socket_recv: read_data_size=%d\r\n", socket->read_data_size);
+        uint32_t i = 0;
+        while ((i < socket->read_data_size) && (i < size)) {
+            *ptr++ = socket->read_data[i];
+            i++;
+        }
+
+        recv += i;
+
+        if (i >= socket->read_data_size) {
+            /* All the storeed data has been read, reset buffer */
+            memset(socket->read_data, 0, sizeof(socket->read_data));
+            socket->read_data_size = 0;
+            // debug_if(_ism_debug, "ISM43362Interface: Socket_recv buffer reset\r\n");
+        } else {
+            /*  In case there is remaining data in buffer, update socket content
+             *  For now by shift copy of all data (not very efficient to be
+             *  revised */
+            while (i < socket->read_data_size) {
+                socket->read_data[i - size] = socket->read_data[i];
+                i++;
+            }
+
+            socket->read_data_size -= size;
+        }
+    }
+    // else {
+    //     debug_if(_ism_debug, "ISM43362Interface socket_recv: Nothing in buffer\r\n");
+    // }
+
+    _mutex.unlock();
+
+    if (recv > 0) {
+        debug_if(_ism_debug, "ISM43362Interface socket_recv: recv=%d\r\n", recv);
+        return recv;
+    } else {
+        debug_if(_ism_debug, "ISM43362Interface socket_recv: returns WOULD BLOCK\r\n");
+        return NSAPI_ERROR_WOULD_BLOCK;
+    }
+}
+
+int ISM43362Interface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
+{
+    _mutex.lock();
+    struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+
+    if (socket->connected && socket->addr != addr) {
+        if (!_ism.close(socket->id)) {
+            debug_if(_ism_debug, "ISM43362Interface: socket_sendto ERROR\r\n");
+            _mutex.unlock();
+            return NSAPI_ERROR_DEVICE_ERROR;
+        }
+        socket->connected = false;
+        _ids[socket->id] = false;
+        _socket_obj[socket->id] = 0;
+    }
+
+    if (!socket->connected) {
+        int err = socket_connect_nolock(socket, addr);
+        if (err < 0) {
+            _mutex.unlock();
+            return err;
+        }
+        socket->addr = addr;
+    }
+
+    int ret = socket_send_nolock(socket, data, size);
+
+    _mutex.unlock();
+
+    return ret;
+}
+
+int ISM43362Interface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
+{
+    int ret = socket_recv(handle, data, size);
+    _mutex.lock();
+    if ((ret >= 0) && addr) {
+        struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+        *addr = socket->addr;
+    }
+    _mutex.unlock();
+    return ret;
+}
+
+void ISM43362Interface::socket_attach(void *handle, void (*cb)(void *), void *data)
+{
+    _mutex.lock();
+    struct ISM43362_socket *socket = (struct ISM43362_socket *)handle;
+    _cbs[socket->id].callback = cb;
+    _cbs[socket->id].data = data;
+    _mutex.unlock();
+}
+
+void ISM43362Interface::event()
+{
+    for (int i = 0; i < ISM43362_SOCKET_COUNT; i++) {
+        if (_cbs[i].callback) {
+            _cbs[i].callback(_cbs[i].data);
+        }
+    }
+}
+
+#if MBED_CONF_ISM43362_PROVIDE_DEFAULT
+
+WiFiInterface *WiFiInterface::get_default_instance() {
+    static ISM43362Interface ism;
+    return &ism;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/ISM43362Interface.h	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,298 @@
+/* ISM43362 implementation of NetworkInterfaceAPI
+ * Copyright (c) STMicroelectronics 2017
+ *
+ * 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.
+ */
+
+#ifndef ISM43362_INTERFACE_H
+#define ISM43362_INTERFACE_H
+
+#include "mbed.h"
+#include "ISM43362.h"
+
+
+#define ISM43362_SOCKET_COUNT 4
+
+/** ISM43362Interface class
+ *  Implementation of the NetworkStack for the ISM43362
+ */
+class ISM43362Interface : public NetworkStack, public WiFiInterface
+{
+public:
+    /** ISM43362Interface lifetime
+     * @param debug     Enable debugging
+     */
+    ISM43362Interface(bool debug = MBED_CONF_ISM43362_WIFI_DEBUG);
+
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network. Requires ssid and passphrase to be set.
+     *  If passphrase is invalid, NSAPI_ERROR_AUTH_ERROR is returned.
+     *
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual int connect();
+
+    /** Start the interface
+     *
+     *  Attempts to connect to a WiFi network.
+     *
+     *  @param ssid      Name of the network to connect to
+     *  @param pass      Security passphrase to connect to the network
+     *  @param security  Type of encryption for connection (Default: NSAPI_SECURITY_NONE)
+     *  @param channel   This parameter is not supported, setting it to anything else than 0 will result in NSAPI_ERROR_UNSUPPORTED
+     *  @return          0 on success, or error code on failure
+     */
+    virtual int connect(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE,
+                        uint8_t channel = 0);
+
+    /** Translates a hostname to an IP address with specific version
+     *
+     *  The hostname may be either a domain name or an IP address. If the
+     *  hostname is an IP address, no network transactions will be performed.
+     *
+     *
+     *  @param host     Hostname to resolve
+     *  @param address  Destination for the host SocketAddress
+     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
+     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
+     *  @return         0 on success, negative error code on failure
+     */
+    virtual nsapi_error_t gethostbyname(const char *name, SocketAddress *address, nsapi_version_t version = NSAPI_UNSPEC);
+
+    /** Set the WiFi network credentials
+     *
+     *  @param ssid      Name of the network to connect to
+     *  @param pass      Security passphrase to connect to the network
+     *  @param security  Type of encryption for connection
+     *                   (defaults to NSAPI_SECURITY_NONE)
+     *  @return          0 on success, or error code on failure
+     */
+    virtual int set_credentials(const char *ssid, const char *pass, nsapi_security_t security = NSAPI_SECURITY_NONE);
+
+    /** Set the WiFi network channel - NOT SUPPORTED
+     *
+     * This function is not supported and will return NSAPI_ERROR_UNSUPPORTED
+     *
+     *  @param channel   Channel on which the connection is to be made, or 0 for any (Default: 0)
+     *  @return          Not supported, returns NSAPI_ERROR_UNSUPPORTED
+     */
+    virtual int set_channel(uint8_t channel);
+
+    /** Stop the interface
+     *  @return             0 on success, negative on failure
+     */
+    virtual int disconnect();
+
+    /** Get the internally stored IP address
+     *  @return             IP address of the interface or null if not yet connected
+     */
+    virtual const char *get_ip_address();
+
+    /** Get the internally stored MAC address
+     *  @return             MAC address of the interface
+     */
+    virtual const char *get_mac_address();
+
+    /** Get the local gateway
+    *
+    *  @return         Null-terminated representation of the local gateway
+    *                  or null if no network mask has been recieved
+    */
+    virtual const char *get_gateway();
+
+    /** Get the local network mask
+     *
+     *  @return         Null-terminated representation of the local network mask
+     *                  or null if no network mask has been recieved
+     */
+    virtual const char *get_netmask();
+
+    /** Gets the current radio signal strength for active connection
+     *
+     * @return          Connection strength in dBm (negative value)
+     */
+    virtual int8_t get_rssi();
+
+    /** Scan for available networks
+     *
+     * This function will block.
+     *
+     * @param  ap       Pointer to allocated array to store discovered AP
+     * @param  count    Size of allocated @a res array, or 0 to only count available AP
+     * @return          Number of entries in @a, or if @a count was 0 number of available networks, negative on error
+     *                  see @a nsapi_error
+     */
+    virtual int scan(WiFiAccessPoint *res, unsigned count);
+
+    /** Translates a hostname to an IP address with specific version
+     *
+     *  The hostname may be either a domain name or an IP address. If the
+     *  hostname is an IP address, no network transactions will be performed.
+     *
+     *  If no stack-specific DNS resolution is provided, the hostname
+     *  will be resolve using a UDP socket on the stack.
+     *
+     *  @param address  Destination for the host SocketAddress
+     *  @param host     Hostname to resolve
+     *  @param version  IP version of address to resolve, NSAPI_UNSPEC indicates
+     *                  version is chosen by the stack (defaults to NSAPI_UNSPEC)
+     *  @return         0 on success, negative error code on failure
+     */
+    using NetworkInterface::gethostbyname;
+
+    /** Add a domain name server to list of servers to query
+     *
+     *  @param addr     Destination for the host address
+     *  @return         0 on success, negative error code on failure
+     */
+    using NetworkInterface::add_dns_server;
+
+protected:
+    /** Open a socket
+     *  @param handle       Handle in which to store new socket
+     *  @param proto        Type of socket to open, NSAPI_TCP or NSAPI_UDP
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_open(void **handle, nsapi_protocol_t proto);
+
+    /** Close the socket
+     *  @param handle       Socket handle
+     *  @return             0 on success, negative on failure
+     *  @note On failure, any memory associated with the socket must still
+     *        be cleaned up
+     */
+    virtual int socket_close(void *handle);
+
+    /** Bind a server socket to a specific port
+     *  @param handle       Socket handle
+     *  @param address      Local address to listen for incoming connections on
+     *  @return             0 on success, negative on failure.
+     */
+    virtual int socket_bind(void *handle, const SocketAddress &address);
+
+    /** Start listening for incoming connections
+     *  @param handle       Socket handle
+     *  @param backlog      Number of pending connections that can be queued up at any
+     *                      one time [Default: 1]
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_listen(void *handle, int backlog);
+
+    /** Connects this TCP socket to the server
+     *  @param handle       Socket handle
+     *  @param address      SocketAddress to connect to
+     *  @return             0 on success, negative on failure
+     */
+    virtual int socket_connect(void *handle, const SocketAddress &address);
+
+    /** Accept a new connection.
+     *  @param handle       Handle in which to store new socket
+     *  @param server       Socket handle to server to accept from
+     *  @return             0 on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_accept(void *handle, void **socket, SocketAddress *address);
+
+    /** Send data to the remote host
+     *  @param handle       Socket handle
+     *  @param data         The buffer to send to the host
+     *  @param size         The length of the buffer to send
+     *  @return             Number of written bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_send(void *handle, const void *data, unsigned size);
+
+    /** Receive data from the remote host
+     *  @param handle       Socket handle
+     *  @param data         The buffer in which to store the data received from the host
+     *  @param size         The maximum length of the buffer
+     *  @return             Number of received bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_recv(void *handle, void *data, unsigned size);
+
+    /** Send a packet to a remote endpoint
+     *  @param handle       Socket handle
+     *  @param address      The remote SocketAddress
+     *  @param data         The packet to be sent
+     *  @param size         The length of the packet to be sent
+     *  @return             The number of written bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size);
+
+    /** Receive a packet from a remote endpoint
+     *  @param handle       Socket handle
+     *  @param address      Destination for the remote SocketAddress or null
+     *  @param buffer       The buffer for storing the incoming packet data
+     *                      If a packet is too long to fit in the supplied buffer,
+     *                      excess bytes are discarded
+     *  @param size         The length of the buffer
+     *  @return             The number of received bytes on success, negative on failure
+     *  @note This call is not-blocking, if this call would block, must
+     *        immediately return NSAPI_ERROR_WOULD_WAIT
+     */
+    virtual int socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size);
+
+    /** Register a callback on state change of the socket
+     *  @param handle       Socket handle
+     *  @param callback     Function to call on state change
+     *  @param data         Argument to pass to callback
+     *  @note Callback may be called in an interrupt context.
+     */
+    virtual void socket_attach(void *handle, void (*callback)(void *), void *data);
+
+    /** Provide access to the NetworkStack object
+     *
+     *  @return The underlying NetworkStack object
+     */
+    virtual NetworkStack *get_stack()
+    {
+        return this;
+    }
+
+private:
+    ISM43362 _ism;
+    bool _ids[ISM43362_SOCKET_COUNT];
+    uint32_t _socket_obj[ISM43362_SOCKET_COUNT]; // store addresses of socket handles
+    Mutex _mutex;
+    Thread thread_read_socket;
+    char ap_ssid[33]; /* 32 is what 802.11 defines as longest possible name; +1 for the \0 */
+    ism_security_t ap_sec;
+    uint8_t ap_ch;
+    char ap_pass[64]; /* The longest allowed passphrase */
+
+    bool _ism_debug;
+    uint32_t _FwVersion;
+
+    void event();
+    struct {
+        void (*callback)(void *);
+        void *data;
+    } _cbs[ISM43362_SOCKET_COUNT];
+
+    /** Function called by the socket read thread to check if data is available on the wifi module
+     *
+     */
+    virtual void socket_check_read();
+    int socket_send_nolock(void *handle, const void *data, unsigned size);
+    int socket_connect_nolock(void *handle, const SocketAddress &addr);
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/README.md	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,50 @@
+# ISM43362 WiFi driver for mbed-os
+
+The mbed OS driver for the ISM43362 WiFi module
+
+https://www.inventeksys.com/products-page/wifi-modules/ism4336-m3g-l44-e-embedded-serial-to-wifi-module/
+
+
+## Currently supported platforms
+
+ISM43362 module is soldered on the following platforms from STMicroelectronics
+
+ * [DISCO_L475VG_IOT01A](https://os.mbed.com/platforms/ST-Discovery-L475E-IOT01A/)
+ * [DISCO_F413ZH](https://os.mbed.com/platforms/ST-Discovery-F413H/)
+
+## Configuration
+
+Correct pins have already been configured for both supported platforms.
+
+Here is configured pins:
+
+- MBED_CONF_ISM43362_WIFI_MISO      : spi-miso pin for the ism43362 connection
+- MBED_CONF_ISM43362_WIFI_MOSI     : spi-mosi pin for the ism43362 connection
+- MBED_CONF_ISM43362_WIFI_SPI_SCLK  : spi-clock pin for the ism43362 connection
+- MBED_CONF_ISM43362_WIFI_SPI_NSS   : spi-nss pin for the ism43362 connection
+- MBED_CONF_ISM43362_WIFI_RESET     : Reset pin for the ism43362 wifi module
+- MBED_CONF_ISM43362_WIFI_DATAREADY : Data Ready pin for the ism43362 wifi module
+- MBED_CONF_ISM43362_WIFI_WAKEUP    : Wakeup pin for the ism43362 wifi module
+
+## Debug
+
+Some debug print on console can help to debug if necessary.
+
+- in ISM43362Interface.cpp file, set ism_interface_debug to 1
+- in ISM43362/ISM43362.cpp file, set ism_debug to 1
+- in ISM43362/ATParser/ATParser.cpp file, there are 3 different level : dbg_on / AT_DATA_PRINT / AT_COMMAND_PRINT
+
+Another way to enable these prints is overwrite MBED_CONF_ISM43362_WIFI_DEBUG in your json file:
+            "ism43362.wifi-debug": true
+
+
+## Firmware version
+
+This driver has been tested with C3.5.2.2 and C3.5.2.3.BETA9 firmware version
+
+## wifi module FW update
+
+Only Wifi module from DISCO_L475VG_IOT01A can be updated (HW limitation for DISCO_F413ZH).
+
+For more information about the wifi FW version, refer to the detailed procedure in
+http://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-embedded-software-expansion/x-cube-azure.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wifi-ism43362/mbed_lib.json	Fri Oct 12 21:22:49 2018 +0000
@@ -0,0 +1,63 @@
+{
+    "name": "ism43362",
+    "config": {
+        "wifi-miso": {
+            "help": "SPI-MISO connection to external device",
+            "value": "NC"
+        },
+        "wifi-mosi": {
+            "help": "SPI-MOSI connection to external device",
+            "value": "NC"
+        },
+        "wifi-sclk": {
+            "help": "SPI-CLOCK connection to external device",
+            "value": "NC"
+        },
+        "wifi-nss": {
+            "help": "SPI chip select of external device",
+            "value": "NC"
+        },
+        "wifi-reset": {
+            "help": "ISM43362 reset",
+            "value": "NC"
+        },
+        "wifi-dataready": {
+            "help": "ISM43362 dataready",
+            "value": "NC"
+        },
+        "wifi-wakeup": {
+            "help": "ISM43362 wakeup",
+            "value": "NC"
+        },
+        "wifi-debug": {
+            "help": "Defines whether logging is on or off",
+            "value": false
+        },
+        "provide-default": {
+            "help": "Provide default WifiInterface. [true/false]",
+            "value": false
+        }
+    },
+    "target_overrides": {
+        "DISCO_F413ZH": {
+            "ism43362.wifi-miso": "PB_4",
+            "ism43362.wifi-mosi": "PB_5",
+            "ism43362.wifi-sclk": "PB_12",
+            "ism43362.wifi-nss": "PG_11",
+            "ism43362.wifi-reset": "PH_1",
+            "ism43362.wifi-dataready": "PG_12",
+            "ism43362.wifi-wakeup": "PB_15",
+            "ism43362.provide-default": true
+        },
+        "DISCO_L475VG_IOT01A": {
+            "ism43362.wifi-miso": "PC_11",
+            "ism43362.wifi-mosi": "PC_12",
+            "ism43362.wifi-sclk": "PC_10",
+            "ism43362.wifi-nss": "PE_0",
+            "ism43362.wifi-reset": "PE_8",
+            "ism43362.wifi-dataready": "PE_1",
+            "ism43362.wifi-wakeup": "PB_13",
+            "ism43362.provide-default": true
+        }
+     }
+}